Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / General / January 2006

Tip: Looking for answers? Try searching our database.

Question about Generics

Thread view: 
Rhino - 18 Jan 2006 17:59 GMT
I am currrently trying to "genericize" some of my older classes but I'm
having trouble with this simple class:

================================================================
public class IntRange extends TreeSet {

   public IntRange(int firstInt, int secondInt) {

       add(new Integer(firstInt));
       add(new Integer(secondInt));
   }

   public IntRange(int[] intRange) {

       if (intRange.length != 2) {
           throw new IllegalArgumentException("The IntRange array must have
exactly two values.");
       }

       add(new Integer(intRange[0]));
       add(new Integer(intRange[1]));
   }

   public boolean between(int input) {

       if (input >= ((Integer) first()).intValue() && input <= ((Integer)
last()).intValue())
           return (true);
       else
           return (false);
   }

   public int[] getValues() {

       int[] values = new int[2];
       values[0] = ((Integer) first()).intValue();
       values[1] = ((Integer) last()).intValue();

       return values;
   }
}
================================================================

Can anyone tell me how to change the add() lines in the constructors to make
the compiler accept them? I thought that changing "public class IntRange
extends TreeSet" to "public class IntRange <Integer> extends TreeSet" might
solve all of my compiler warnings but it didn't; I'm not sure why. Could
someone explain what I _should_ do?

Frankly, I found the article on generics in the API pretty unhelpful in
getting beyond the most basic ideas. Can anyone point me to an article or
tutorial that explains these things more clearly? Then maybe I can
"genericize" the rest of my code on my own....

Signature

Rhino

Torkel Franzen - 18 Jan 2006 18:26 GMT
> Can anyone tell me how to change the add() lines in the constructors to make
> the compiler accept them? I thought that changing "public class IntRange
> extends TreeSet" to "public class IntRange <Integer> extends TreeSet" might
> solve all of my compiler warnings but it didn't; I'm not sure why.

 The other way around. Change

public class IntRange extends TreeSet {

to

public class IntRange extends TreeSet<Integer>{
Rhino - 18 Jan 2006 18:43 GMT
>> Can anyone tell me how to change the add() lines in the constructors to
>> make
[quoted text clipped - 10 lines]
>
> public class IntRange extends TreeSet<Integer>{

Yes, of course, that's it. I figured this out just after I posted but hadn't
managed to get back in time to mention that.

But if anyone can still point me to a clearer explanation of generics than
the one in the API, I'd love to hear about it :-) I feel sure that other,
harder, problems will come to light as I try to make older code use
generics.

Rhino
Mike Schilling - 18 Jan 2006 19:17 GMT
> But if anyone can still point me to a clearer explanation of generics than
> the one in the API, I'd love to hear about it :-) I feel sure that other,
> harder, problems will come to light as I try to make older code use
> generics.

Not the JLS :-)

Seriously, which in previous editions I've gone to the JLS for the
definitive answer to thorny questions, JLS 3 is crap.  Even many of the
examples are wrong.
Torkel Franzen - 18 Jan 2006 20:23 GMT
> Seriously, which in previous editions I've gone to the JLS for the
> definitive answer to thorny questions, JLS 3 is crap.

 No, no, it's great stuff.
Mike Schilling - 18 Jan 2006 21:13 GMT
>> Seriously, which in previous editions I've gone to the JLS for the
>> definitive answer to thorny questions, JLS 3 is crap.
>
>  No, no, it's great stuff.

Sorry, I can't tell if you'e joking or being serious.  If the latter, can
you tell me why you say that?
Torkel Franzen - 18 Jan 2006 21:53 GMT
> Sorry, I can't tell if you'e joking or being serious.  If the latter, can
> you tell me why you say that?

 Well, it is the ultimate fountain of wisdom, and quite readable. Can
you give a couple of examples of thorny questions where it let you
down?
Mike Schilling - 18 Jan 2006 23:10 GMT
>> Sorry, I can't tell if you'e joking or being serious.  If the latter, can
>> you tell me why you say that?
>
>  Well, it is the ultimate fountain of wisdom, and quite readable. Can
> you give a couple of examples of thorny questions where it let you
> down?

If my copy were in front of me, I would give chapter and verse.   In
general, generics, and in particular, many of the examples that were new for
JLS 3 do not compile.
Tony Morris - 18 Jan 2006 23:26 GMT
> >> Sorry, I can't tell if you'e joking or being serious.  If the latter, can
> >> you tell me why you say that?
[quoted text clipped - 6 lines]
> general, generics, and in particular, many of the examples that were new for
> JLS 3 do not compile.

That's because at one stage they did compile, only the JSR "expert" groups
found that they had to change the definition of 'generics' in order to
appear less contrived - and without telling anyone (including themselves).
Welcome to corporate software.

--
Tony Morris
http://tmorris.net/

Java Questions and Answers
http://jqa.tmorris.net/
Torkel Franzen - 19 Jan 2006 10:57 GMT
> If my copy were in front of me, I would give chapter and verse.   In
> general, generics, and in particular, many of the examples that were new for
> JLS 3 do not compile.

 I would appreciate information about where these uncompilable
examples are to be found.
Mike Schilling - 19 Jan 2006 19:51 GMT
>> If my copy were in front of me, I would give chapter and verse.   In
>> general, generics, and in particular, many of the examples that were new
[quoted text clipped - 3 lines]
>  I would appreciate information about where these uncompilable
> examples are to be found.

When I locate my copy (it appears to have been "borrowed"), I'll post them.
Torkel Franzen - 18 Jan 2006 20:21 GMT
> But if anyone can still point me to a clearer explanation of generics than
> the one in the API, I'd love to hear about it :-) I feel sure that other,
> harder, problems will come to light as I try to make older code use
> generics.

 You might try Angelika Langer's page:

http://www.angelikalanger.com/GenericsFAQ/JavaGenericsFAQ.html
Rhino - 18 Jan 2006 20:44 GMT
>> But if anyone can still point me to a clearer explanation of generics
>> than
[quoted text clipped - 5 lines]
>
> http://www.angelikalanger.com/GenericsFAQ/JavaGenericsFAQ.html

Thank you, that looks promising!

Rhino
Thomas Hawtin - 18 Jan 2006 20:25 GMT
> public class IntRange extends TreeSet {

As mentioned in another reply, that should be:

public class IntRange extends TreeSet<Integer> {

This is a really odd class. It sounds like a range of int (with
inclusive values by the looks of the code, which is sensible as you
can't have one more than Integer.MAX_VALUE in int).

>     public IntRange(int firstInt, int secondInt) {

Not very descriptive parameters.

>         add(new Integer(firstInt));
>         add(new Integer(secondInt));

Can be written as:

        add(firstInt);
        add(secondInt);

If you didn't want to use autoboxing, you can do it slightly better as:

        add(Integer.valueOf(firstInt));
        add(Integer.valueOf(secondInt));

>     public boolean between(int input) {

Again you could go for a better method name.

>         if (input >= ((Integer) first()).intValue() && input <= ((Integer)
> last()).intValue())
>             return (true);
>         else
>             return (false);

This can be better written as:

        return first() <= input && input <= last();

>         int[] values = new int[2];
>         values[0] = ((Integer) first()).intValue();
>         values[1] = ((Integer) last()).intValue();
>
>         return values;

Again, that can be written:

     return new int[] { first(), last() };

Either of the above could throw a peculiar exception if the set is empty.

Tom Hawtin
Signature

Unemployed English Java programmer
http://jroller.com/page/tackline/

Rhino - 18 Jan 2006 20:40 GMT
>> public class IntRange extends TreeSet {
>
[quoted text clipped - 48 lines]
>
> Either of the above could throw a peculiar exception if the set is empty.

That class is trying to capture a range of ints so that there is a way of
saying that some third int is or is not within the range depicted by the
IntRange. For instance, if I say that the IntRange consists of a low value
of 3 and a high value of 9, I want to be able to say that the number 23 is
not between the values in the set while 7 is.

I probably haven't done it as well as it could be done; it was really just
an early attempt in an old project that I've put to the side for a while.
Thanks for your suggestions on improving it; if you have more, please go
ahead.

I'm not sure how I could ever have that IntRange be empty to cause me
problems: both constructors insist on exactly two values. Is there some way
to instantiate the IntRange that I haven't thought of which might cause an
empty set?

Rhino
Thomas Hawtin - 18 Jan 2006 22:10 GMT
>>public class IntRange extends TreeSet<Integer> {
>>>
> I'm not sure how I could ever have that IntRange be empty to cause me
> problems: both constructors insist on exactly two values. Is there some way
> to instantiate the IntRange that I haven't thought of which might cause an
> empty set?

You could have:

    IntRange range = new IntRange(42, 0);
    range.clear();
    System.err.println(range.between(3));

If you want IntRange to support SortedSet<Integer> extend
AbstractSet<Integer> and provide the missing methods as needed. A lot of
the methods should throw UnsupportedOperationException.

Tom Hawtin
Signature

Unemployed English Java programmer
http://jroller.com/page/tackline/

Rhino - 18 Jan 2006 22:34 GMT
>>>public class IntRange extends TreeSet<Integer> {
>>>>
[quoted text clipped - 8 lines]
>     range.clear();
>     System.err.println(range.between(3));

Ahh, I see....

Hmm, maybe I should override the clear() method and make the override empty
to prevent that. Or would it be better to make the implementation throw
UnsupportedOperationException? Yes, the latter makes more sense, otherwise a
user might not realize that clear() is not doing anything by design and that
it isn't broken.

> If you want IntRange to support SortedSet<Integer> extend
> AbstractSet<Integer> and provide the missing methods as needed. A lot of
> the methods should throw UnsupportedOperationException.

Yes, I see your point. Thanks for the suggestions!

Rhino
Eric Sosman - 18 Jan 2006 23:19 GMT
Rhino wrote On 01/18/06 17:34,:

>>>>public class IntRange extends TreeSet<Integer> {
>>>>
[quoted text clipped - 16 lines]
> user might not realize that clear() is not doing anything by design and that
> it isn't broken.

   I'd take yet another step back and ask why you've
decided to make IntRange extend TreeSet.  The inherited
methods are potential sources of trouble, since the
caller can use them to modify the TreeSet without the
IntRange's knowledge.  And there's nothing in what you've
shown us of IntRange that appears to need TreeSet's
machinery.  Why not just a free-standing IntRange that
holds two values?

    public class IntRange {
       private final int low, high;
       public IntRange(int low, int high) {
           this.low = Math.min(low, high);
           this.high = Math.max(low, high);
       }
       public IntRange(int[] range) {
           this(range[0], range[1]);
       }
       public boolean isInRange(int value) {
           return low <= value && value <= high;
       }
       public int[] getValues() {
           int[] values = { low, high };
           return values;
       }
    }

Unless there's more to IntRange than you've revealed, I'd
recommend following the KISS ("Keep It Simple, Stupid!")
principle.

Signature

Eric.Sosman@sun.com

Ian Pilcher - 18 Jan 2006 23:32 GMT
> Unless there's more to IntRange than you've revealed, I'd
> recommend following the KISS ("Keep It Simple, Stupid!")
> principle.

Presumably, the OP wants his IntRange to behave like a Set<Integer>,
with contains, containsAll, iterator, etc.

If this is the case, extending AbstractSet (or possibly AbstractList) is
probably the way to go.

Signature

========================================================================
Ian Pilcher                                        i.pilcher@comcast.net
========================================================================

Rhino - 19 Jan 2006 05:15 GMT
>> Unless there's more to IntRange than you've revealed, I'd
>> recommend following the KISS ("Keep It Simple, Stupid!")
[quoted text clipped - 5 lines]
> If this is the case, extending AbstractSet (or possibly AbstractList) is
> probably the way to go.

In all honesty, I can't remember what reasoning process I was going through
when I wrote this IntSet class. That was at least a year ago and I've long
since set the project aside, although I want to revive it at some point.

Everyone's comments are much appreciated but I'm not going to be able to act
on any improvements right now anyway; maybe in a couple of months if things
go well.... In the meantime, your remarks have helped me learn a bit more
about making warnings about Generics go away so thanks for that.

Rhino
Stefan Ram - 18 Jan 2006 23:15 GMT
>That class is trying to capture a range of ints so that there
>is a way of saying that some third int is or is not within the
>range depicted by the IntRange.

 This is somewhat similar to:

http://download.java.net/jdk6/docs/api/javax/swing/DefaultBoundedRangeModel.html

 Here is a simple implementation:

class Range
{ final int min; final int max;
 public void Range( final int min, final int max )
 { this.min = min; this.max = max; }
 public bool contains( final int value )
 { return value >= min && value <= max; }}

 I see no reason to use TreeSets, arrays or Integer objects.
Robert M. Gary - 18 Jan 2006 23:06 GMT
I will be interested in hearing how this works out for you. I've mostly
given up on "Generics" (we call them "Templates" in C++). The problem
with Generics is that without a "typedef" type ability you end up with
classes who's names can often wrap around your screen. Define an
Iterator for one and I've actually had cases where the class name
itself was two lines long. C++ solved this with typedef, allowing you
to rename the big long ugly class name to something reasonable.

-Robert
Danno - 19 Jan 2006 04:57 GMT
I think the idea of generics is that your code should be "generic". In
other words, while IntRange is fine for a class, generics force to be
more generic in your approach, so I created a regular class called
Range.  I provided an example below, using your code, that seems to
work ok. I included a main method so you can check it out using longs,
short, etc.

I am no badass with generics, I just know the regular stuff. You just
happened to post while I was researching some advanced uses for
generics. ;)

Let me know if that works for ya through here or email. ;)

package com.evolutionnext;

import java.util.TreeSet;

/**
*
* @author valued customer
*/
public class Range<E extends Comparable<E>> extends TreeSet<E>{
   public Range(E first, E second) {
       add(first);
       add(second);
   }

   public Range(E[] range) {
       if (range.length != 2) {
           throw new IllegalArgumentException("The Range array must
have exactly two values.");
       }
       add(range[0]);
       add(range[1]);
   }

   public boolean input(E element) {
       return last().compareTo(element) > first().compareTo(element);
   }

   public Object[] getValues() {
       Object[] result = new Object[2];
       result[0] = first();
       result[1] = last();
       return result;
   }

   public static void main(String[] args) {
       Range<Integer> range = new Range<Integer>(1, 4);
       System.out.println(range.input(3));
       System.out.println(range.input(5));
       System.out.println(range.input(-2));
       System.out.println(range.input(0));
       System.out.println(range.input(1));
   }
}

> I am currrently trying to "genericize" some of my older classes but I'm
> having trouble with this simple class:
[quoted text clipped - 38 lines]
> }
> ================================================================
Thomas Hawtin - 19 Jan 2006 17:00 GMT
>     public boolean input(E element) {
>         return last().compareTo(element) > first().compareTo(element);
>     }

Very clever. But not actually correct.

I think it should go something like:

    public boolean contains(E element) {
        return
            first().compareTo(element) <= 0 &&
            element.compareTo(last() ) <= 0;
    }

(Disclaimer: Neither tested nor compiled.)

Not that I think it is a brilliant idea. It appears that the original
intention was for a SortedSet of the range. That in general is not going
to work for a Comparable. String for instance would iterate over
successively long values.

Tom Hawtin
Signature

Unemployed English Java programmer
http://jroller.com/page/tackline/

Danno - 19 Jan 2006 17:41 GMT
All my test cases passed just fine  (Try it for yourself ;) ):

Range<Integer> range = new Range<Integer>(1, 4);
       System.out.println(range.input(3)); //true
       System.out.println(range.input(5)); //false
       System.out.println(range.input(-2)); //false
       System.out.println(range.input(0));  //false
       System.out.println(range.input(1)); //true

       System.out.println("--------");

       Range<Integer> range2 = new Range<Integer>(-5, 5);
       System.out.println(range2.input(3)); //true
       System.out.println(range2.input(5)); //true
       System.out.println(range2.input(-2)); //true
       System.out.println(range2.input(0)); //true
       System.out.println(range2.input(1)); //true
       System.out.println(range2.input(-5)); //true
       System.out.println(range2.input(-8)); //false

I was assuming from the code that it was inclusive of the boundary. ;)
Thomas Hawtin - 19 Jan 2006 18:46 GMT
> All my test cases passed just fine  (Try it for yourself ;) ):

Just because all of your tests pass, it does not mean your code is
correct. Your tests are significantly inadequate.

Tom Hawtin
Signature

Unemployed English Java programmer
http://jroller.com/page/tackline/

Danno - 19 Jan 2006 19:17 GMT
So test away some more at it. Crash it! It would only help out Rhino in
the end.
I was just helping someone here on usenet and not getting paid for
production quality code.   Should I have put a disclaimer to satiate
the usenet code critics?  Nah, they should test it for themselves.

Other than null handling, which this class doesn't have, I think it is
a pretty cool solution. Let me know of any fail case that you find.

Have fun ;)
Danno
Thomas Hawtin - 19 Jan 2006 19:57 GMT
> So test away some more at it. Crash it! It would only help out Rhino in
> the end.

Cursory code review caught a problem (and not just that the code was
needlessly difficult to understand). I think you would gain more by
going back and thinking over the code. There are at least two things I'd
probably change in my own version.

> I was just helping someone here on usenet and not getting paid for
> production quality code.   Should I have put a disclaimer to satiate
> the usenet code critics?  Nah, they should test it for themselves.

You put forward an obfuscated technique that is buggy (surprise!). Are
you not expecting anyone to pick up on that? No one should criticise
exceptionally poor code?

> Other than null handling, which this class doesn't have, I think it is
> a pretty cool solution. Let me know of any fail case that you find.

K3wl, certainly. Working, no. Often those things go together.

Tom Hawtin
Signature

Unemployed English Java programmer
http://jroller.com/page/tackline/

Danno - 19 Jan 2006 20:14 GMT
Show me the buggy! hehe

Plus, it's not exceptionally poor code, I take umbrage at that, I think
it kicks a.s for doing it in 10 minutes.  If you don't find a bug in
that method,  you owe me a tortilla. :)
Thomas Hawtin - 19 Jan 2006 21:38 GMT
> Show me the buggy! hehe
>
> Plus, it's not exceptionally poor code, I take umbrage at that, I think
> it kicks a.s for doing it in 10 minutes.  If you don't find a bug in
> that method,  you owe me a tortilla. :)

You would save time if you wrote more straightforward code.

I expect you to find the bugs. It might persuade you to aim for simpler
code.

Tom Hawtin
Signature

Unemployed English Java programmer
http://jroller.com/page/tackline/

Danno - 19 Jan 2006 22:01 GMT
Whatever
I think someone owes me a tortilla
Luc The Perverse - 19 Jan 2006 22:08 GMT
> Whatever
> I think someone owes me a tortilla

Huh why?

--
LTP

:)
Danno - 19 Jan 2006 22:31 GMT
Because he said there is a bug and I say nay! NAY!  I asked him to tell
me the bug, and I'd give him a tortilla.  He is refusing, because I
think he is bluffing. For what it was worth in my few minutes of
jotting code late at night on c.l.j.p I thought that little tidbit was
weird albeit awesome!

So unless he gives me his expert test case, I am assuming he owes me a
tortilla.
John C. Bollinger - 20 Jan 2006 03:17 GMT
>>     public boolean input(E element) {
>>         return last().compareTo(element) > first().compareTo(element);
>>     }
>
> Very clever. But not actually correct.

You at least have to award him partial credit.  I see one class of error
cases where the above method provides results inconsistent with Rhino's
between() method, but otherwise it does look like it works.

> I think it should go something like:
>
[quoted text clipped - 5 lines]
>
> (Disclaimer: Neither tested nor compiled.)

That one solves the problem I see with Danno's.  Sorry, Danno, no
tortilla for you.

> Not that I think it is a brilliant idea. It appears that the original
> intention was for a SortedSet of the range. That in general is not going
> to work for a Comparable. String for instance would iterate over
> successively long values.

No, I think the intention was to hijack TreeSet's machinery to evaluate
properties and conditions of the range, such as the one you and Danno
are arguing over.  The set itself is not intended to be an exhaustive
collection of the elements of the range, and might never contain more
than the two endpoints.

You're right, it's not a brilliant idea, but not for the reason you
mentioned.  I think Rhino talked about this back when he first was
working on it; I didn't like it then, either.

--
John Bollinger
jobollin@indiana.edu
Danno - 20 Jan 2006 04:18 GMT
Now if we are talking about taking it from the top and organizing a way
to do this correctly. I wholeheartedly agree.  I wouldn't approach it
this way at all.  All I did was take Rhino's code for better or worse
and converted it. ;)

I sure like tortillas though.
Oliver Wong - 20 Jan 2006 21:39 GMT
>>     public boolean input(E element) {
>>         return last().compareTo(element) > first().compareTo(element);
[quoted text clipped - 11 lines]
>
> (Disclaimer: Neither tested nor compiled.)

   For what it's worth, I could not find an example where the two methods
would return different values given the same input, except if element is
null, in which case Thomas' method would throw an NPE, and Danno's method
would behave depending on how compareTo() is implemented.

   This is assuming that the contract for compareTo() is properly obeyed,
and that first() and last() always return the same values, and that that
value is not null.

   - Oliver
Eric Sosman - 20 Jan 2006 22:46 GMT
Oliver Wong wrote On 01/20/06 16:39,:

>>>    public boolean input(E element) {
>>>        return last().compareTo(element) > first().compareTo(element);
[quoted text clipped - 20 lines]
> and that first() and last() always return the same values, and that that
> value is not null.

   For what it's worth, two scenarios:

   1: If the range is trivial (first() and last() compare
equal) and the element being tested is that same value,
Danno's method returns false while Oliver's returns true.

   2: compareTo() returns a value whose sign is important
but whose magnitude is not.  If last().compareTo(element)
returns 7 and first().compareTo(element) returns 3, Danno's
method returns true while Oliver's returns false.

Signature

Eric.Sosman@sun.com

Thomas Hawtin - 21 Jan 2006 00:01 GMT
>     For what it's worth, two scenarios:
>
[quoted text clipped - 6 lines]
> returns 7 and first().compareTo(element) returns 3, Danno's
> method returns true while Oliver's returns false.

I think Danno owes Eric a tortilla on both counts.

Tom Hawtin
Signature

Unemployed English Java programmer
http://jroller.com/page/tackline/

Danno - 21 Jan 2006 22:03 GMT
Damn! Oh well, you win some, you lose some.

If you are interested in some tortillas, email me with an address so I
can send them to you. I could also pitch in some chile from NM too.  ;)


Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2009 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.