Generics Question

R

Rhino

I am getting this warning:

Type safety: The method compareTo(Object) belongs to the raw type
Comparable.

References to generic type Comparable<T> should be parameterized

in the following code but I'm not sure how to rewrite the code so that the
error goes away (I don't want to disable the warning in the compiler). The
'//<===' comment indicates exactly where the warning occurs:

=================================================================

public class SimpleRange {

public static int NUMBER_OF_ELEMENTS = 2;

Comparable lowValue = null;
Comparable highValue = null;

public SimpleRange(Comparable firstObject, Comparable secondObject) {

if (firstObject == null) {
throw new IllegalArgumentException("The first Object cannot be
null.");
}

if (secondObject == null) {
throw new IllegalArgumentException("The second Object cannot be
null.");
}

/*
* Since only Comparable objects are permitted by this constructor,
compare them
* and store the lower one in the lowValue class variable. Store the
other one in the
* highValue class variable.
*/
try {
if (firstObject.compareTo(secondObject) > 0) { //<=== Warning
occurs here
this.highValue = firstObject;
this.lowValue = secondObject;
} else {
this.lowValue = firstObject;
this.highValue = secondObject;
}
} catch (ClassCastException cc_excp) {
throw new IllegalArgumentException("The first Object, " +
firstObject.toString() + ", belongs to class " +
firstObject.getClass().getName() + ". The second Object, " +
secondObject.toString() + ", belongs to class " +
secondObject.getClass().getName() + ". Both Objects implement the Comparable
interface but they cannot be compared with each other.");
}

}
}

=================================================================

How do I revise my code to prevent this warning?

I revised the method signature to say:

public SimpleRange(Comparable<Object> firstObject, Comparable<Object>
secondObject)

and this stopped the warning but then I wasn't sure how to invoke the
constructor; old invocations like:

SimpleRange myRange = new SimpleRange("cat", "dog");

stopped working when I did that.

I'm afraid I don't follow generics entirely yet....
 
J

John C. Bollinger

Rhino said:
I am getting this warning:

Type safety: The method compareTo(Object) belongs to the raw type
Comparable.

References to generic type Comparable<T> should be parameterized

in the following code but I'm not sure how to rewrite the code so that the
error goes away (I don't want to disable the warning in the compiler). The
'//<===' comment indicates exactly where the warning occurs:

=================================================================

public class SimpleRange {

public static int NUMBER_OF_ELEMENTS = 2;

Comparable lowValue = null;
Comparable highValue = null;

public SimpleRange(Comparable firstObject, Comparable secondObject) {

if (firstObject == null) {
throw new IllegalArgumentException("The first Object cannot be
null.");
}

if (secondObject == null) {
throw new IllegalArgumentException("The second Object cannot be
null.");
}

/*
* Since only Comparable objects are permitted by this constructor,
compare them
* and store the lower one in the lowValue class variable. Store the
other one in the
* highValue class variable.
*/
try {
if (firstObject.compareTo(secondObject) > 0) { //<=== Warning
occurs here
this.highValue = firstObject;
this.lowValue = secondObject;
} else {
this.lowValue = firstObject;
this.highValue = secondObject;
}
} catch (ClassCastException cc_excp) {
throw new IllegalArgumentException("The first Object, " +
firstObject.toString() + ", belongs to class " +
firstObject.getClass().getName() + ". The second Object, " +
secondObject.toString() + ", belongs to class " +
secondObject.getClass().getName() + ". Both Objects implement the Comparable
interface but they cannot be compared with each other.");
}

}
}

=================================================================

How do I revise my code to prevent this warning?

I revised the method signature to say:

public SimpleRange(Comparable<Object> firstObject, Comparable<Object>
secondObject)

and this stopped the warning but then I wasn't sure how to invoke the
constructor; old invocations like:

SimpleRange myRange = new SimpleRange("cat", "dog");

stopped working when I did that.

I'm afraid I don't follow generics entirely yet....

It's hard to dabble in generics unless you're willing to put up with (or
turn off) the warnings. You very quickly run into situations where you
need to perform a generics overhaul on classes, class hierarchies, and
even whole applications in order to get everything right with respect to
generics. That's not intended to be critical of generics, by the way;
generics constitute a significant and fundamental change to Java's type
system, so its not surprising that it their use has broad impact.

On to the problem at hand. You have run into one of those situations
that is not neatly restricted to a single method. As is often the case,
you have a larger-scale design problem that generics can solve, but for
which your current code appears to follow the best model available in
1.4. The issue revolves around your model of a "range". You have
designed a generic range by defining bounds with use of a very abstract
type (Comparable), which is good pre-1.5 style, but the /declarations/
do not express the constraint that the bounds be comparable to each
other. More succinctly, the question that the compiler wants to be able
to answer is "SimpleRange of /what/?" This demands a full generic
treatment, something along these lines:

public class SimpleRange<T extends Comparable<? super T>> {

T lowValue;
T highValue;

public SimpleRange(T low, T high) {
if (low == null) {
throw new IllegalArgumentException("Null lower bound");
} else if (high == null) {
throw new IllegalArgumentException("Null upper bound");
} else {
lowValue = low;
highValue = high;

// No need to test mutual comparability
}
}

// other methods ...
}

Key points:
(1) The class is made generic, with one type parameter (T) defining the
type of the range's bounds, and presumably also the type of the members
of the range.
(2) The type parameter is assigned an upper bound (Comparable<? super
T>) that ensures that valid type arguments are all of types that are
comparable to themselves, whether by implementing Comparable directly or
by inheriting it from a superclass.
(3) The type parameter allows easy expression of the constraint that the
constructor arguments be of mutually compatible, Comparable, types.
(4) Making this change will produce a cascade of type safety warnings
from the compiler, requiring you to specify a type argument everywhere
you declare a reference of this type.
 
T

Thomas Hawtin

John said:
(4) Making this change will produce a cascade of type safety warnings
from the compiler, requiring you to specify a type argument everywhere
you declare a reference of this type.

The amount of explicit type arguments can be reduced by using a creation
method rather than the constructor directly. Methods, unlike types, need
not have their generic type arguments specified explicitly.

public static <
T extends Comparable said:
SimpleRange<T> create(T low, T high) {
return new SimpleRange<T>(low, high);
}

Tom Hawtin
 
J

John C. Bollinger

Thomas said:
The amount of explicit type arguments can be reduced by using a creation
method rather than the constructor directly. Methods, unlike types, need
not have their generic type arguments specified explicitly.

public static <

return new SimpleRange<T>(low, high);
}

A good and valid point, but it doesn't really solve the problem that the
code of the class's clients is going to need to be modified all over
the place. In particular, it is going to need to be modified everywhere
an instance is created, whether to insert the correct type argument or
to switch from obtaining an instance via "new" to obtaining one via a
factory method. Also, I was more talking about parameterizing
/declarations/ than about parameterizing constructor invocations, and
none of that would be affected by your suggestion.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

Forum statistics

Threads
473,967
Messages
2,570,148
Members
46,694
Latest member
LetaCadwal

Latest Threads

Top