I'm having trouble with casting for generics. What I'm trying to do is use a generic iterator to help me print out what is in my Binary Search Tree. However the for loop I'm implementing says their are incompatible types and therefore will not run. Wanted to get some insight on to what I'm doing wrong here.
public class BinarySearchTree<AnyType extends Comparable<? super AnyType>> implements Iterable{...}
public class MainBST {
public <AnyType> void print(BinarySearchTree<? extends AnyType> t ) {
for(AnyType x : t) //incompatible type
System.out.print(x + ", ");
System.out.println("\n");
}
}
The problem is your BinarySearchTree declaration. It's implementing the raw Iterable type, when it should be implementing Iterable<AnyType>. With the raw Iterator type, the code using the enhanced-for loop only knows that the values will be compatible with Object - so you could change your loop to for (Object x : t) but of course that's not what you really want.
I've reproduced the compile-time error you've shown, and then fixed it by changing the declaration to:
class BinarySearchTree<AnyType extends Comparable<? super AnyType>>
implements Iterable<AnyType> {
...
}
(And then changing the iterator method to return Iterator<AnyType> of course.)
Related
After looking into Java's Collection class (OpenJDK 8_update40), I found the following method:
public static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll) {
Iterator<? extends T> i = coll.iterator();
T candidate = i.next();
while (i.hasNext()) {
T next = i.next();
if (next.compareTo(candidate) > 0)
candidate = next;
}
return candidate;
}
I don't fully understand the use of generic types here. As far as I understand has T to be a subtype of Object which also has to implement the Comparable interface which is also parameterized via a generic parameter. The parameter of Comparable states that is have to be some supertype of T. Due to that we have some kind of recursive type definition.
But here is my question: As far as I know every type in Java is a subtype of Object, so why do they specify
it within the definition of T?
This is for backwards compatibility reasons.
When you use a generic type and this generic type has lower bounds, such as:
<T extends Foo & Bar> void someMethod(T xxx)
then the runtime signature of someMethod will be:
void someMethod(Foo xxx)
(well, OK, the argument name is not there, but you get the picture).
Now, Collections.max() was defined before JDK 5; and its signature was:
public static Object max(Collection coll)
which, in Java 5, could be translated as:
public static Object max(Collection<Object> coll)
The thing is that the return value of max cannot be a Comparable...
Of course, in this case, more difficulties are added:
the second lower bound it itself a generic type;
moreover Comparable is a "consumer" in the PECS way (hence Comparable<? super T>);
the Collection passed as an argument can have any type which is either T or anything extending T, hence ? extends T; we don't care about the actual type, only that the Collection is guaranteed to return something which is at least a T.
This explains the somewhat convoluted signature...
Because if you dont use the "T" the collection would only accept instances of Object.
For example String is subtype of Object, but would not compile because the collection would only accept Object instances.
This is due to covariance vs. contravariance.
As a general rule:
If a generic type T is used to return values, then you use <? extends T> as in Iterator
If a generic type T is used to accept values, then you use <? super T> as in Comparable
I am trying to make a SkipList and I have a method that takes a generic data type:
public void add(E key, Integer value)
{
Node<E> p;
p = find(key);
}
Which takes you here:
public Node<E> find(E key)
{
//Start at head
Node<E> p = head;
while (true)
{
while ( (p.getRight().getKey() != Node.posInf) && (p.getRight().getKey().compareTo(key) <= 0 ))
{
p.setRight(p.getRight());
}
//More stuff down here
}
}
The problem is on the compareTo() method. It says the compareTo() method is undefined for type E. In Eclipse it wants me to add two typecasts like this:
((String) p.getRight().getKey().compareTo((String) key) <= 0 )
Why does it want String? The data type could be anything. I tried doing typecast of E instead but Eclipse wants to change it back to String. Any help would be appreciated.
You haven't shown how E is defined, but the error message indicates that you didn't place an upper bound of Comparable<E> on the declaration of E.
You can accomplish that with something like this on your class:
public class SkipList<E extends Comparable<E>>
This will allow you to call compareTo on your key variable of type E.
As to why Eclipse is suggesting casting to a String, it looks like Eclipse is guessing as to what would be the best change to make to make it compile. It may have guessed String because it's Comparable<String>. In this case, it's wrong, because E isn't necessarily a String. The solution here is different, as I stated above: restrict E to be Comparable<E>.
The method compareTo is defined in the interface java.lang.Comparable. There is nothing in your code that tells the compiler that the type parameter E is Comparable. You can do this in the generic type declaration:
class Node<E extends Comparable<E>> {
...
}
By default if you don't declare extends Comparable, you can only access methods defined in the java.lang.Object class.
So I am reading about generic method and I am get confused. Let me state the problem here first:
In this example: Suppose that I need a version of selectionSort that works for any type T, by using an external comparable supplied by the caller.
First attempt:
public static <T> void selectionSort(T[] arr, Comparator<T> myComparator){....}
Suppose that I have:
Defined vehicle class
created VehicleComparator implementing Comparator while
compare vehicles by their price.
created Truck extends vehicle
instantiated Truck[] arr ; VehicleComparator myComparator
Now, I do:
selectionSort(arr, myComparator);
and it won't work, because myComparator is not available for any subclass of Vehicle.
Then, I do this:
public static <T> void selectionSort(T[] arr, Comparator<? super T> myComparator){....}
This declaration will work, but I don't completely sure what I've been doing... I know use is the way to go. If "? super T" means "an unknown supertype of T", then am I imposing a upper or lower bound? Why is it super? My intention is to let any subclass of T to use myComparator, why "? super T". So confused... I'd appreciate if you have any insight in this..
Thanks ahead!
Firstly, you could have solved it by having Vehicle[] which you then added Trucks to.
The reason you need <? super T> goes back to the generics rule that Comparator<Truck> is not a subtype of Comparator<Vehicle>; the unbounded type T must match exactly, which it doesn't.
In order for a suitable Comparator to be passed in, it must be a Comparator of the class being compared or any super class of it, because in OO languages any class may be treated as an instance of a superclass. Thus, it doesn't matter what the generic type of the Comparator is, as long as it's a supertype of the array's component type.
The quizzical phrase ? super T means that the destination list may have elements of any type
that is a supertype of T, just as the source list may have elements of any type that is a
subtype of T.
We can see pretty simple example copy from Collections:
public static <T> void copy(List<? super T> dst, List<? extends T> src) {
for (int i = 0; i < src.size(); i++) {
dst.set(i, src.get(i));
}
}
And call:
List<Object> objs = Arrays.<Object>asList(2, 3.14, "four");
List<Integer> ints = Arrays.asList(5, 6);
Collections.copy(objs, ints);
assert objs.toString().equals("[5, 6, four]");
As with any generic method, the type parameter may be inferred or may be given explicitly. In this case, there are four possible choices, all of which type-check and all of which have the same effect:
Collections.copy(objs, ints);
Collections.<Object>copy(objs, ints);
Collections.<Number>copy(objs, ints);
Collections.<Integer>copy(objs, ints);
Your method signature
public static <T> void selectionSort(T[] arr, Comparator<? super T> myComparator)
means that if you invoke it with an array of type T than you must also provide a Comparator of type T or a super type of T.
For example if you have the following classes
class Vehicle {}
class Truck extends Vehicle {}
class BigTruck extends Truck {}
class VehicleComparator implements Comparator<Vehicle> {
public int compare(Vehicle o1, Vehicle o2) {
return 0;
}
}
class BigTruckComparator implements Comparator<BigTruck> {
public int compare(BigTruck o1, BigTruck o2) {
return 0;
}
}
class TruckComparator implements Comparator<Truck> {
public int compare(Truck o1, Truck o2) {
return 0;
}
}
then this will work
Truck[] trucks = ...;
selectionSort(trucks, new TruckComparator());
selectionSort(trucks, new VehicleComparator());
Because
TruckComparator implements Comparator<Truck> and a Truck is equal to the array's type Truck
VehicleComparator implements Comparator<Vehicle> and a Vehicle is a super type of the array's type Truck
This will NOT WORK
selectionSort(trucks, new BigTruckComparator());
Because a BigTruckComparator is a Comparator<BigTruck> and a BigTruck is not a super type of the array's type Truck.
The two signatures are equivalent in terms of power -- for any set of arguments, if there exists a choice of type arguments that works for one of them, there exists a choice of type arguments that works for the other one, and vice versa.
You are simply running into limited inference in your compiler. Simply explicitly specify the desired type argument:
YourClass.<Vehicle>selectionSort(arr, myComparator);
After reading Sun's documentation on Generics I moved to the Q and E section at http://docs.oracle.com/javase/tutorial/java/generics/QandE/generics-questions.html.
For Q8 -
Write a generic method to find the maximal element in the range [begin, end) of a list.
the code I wrote is:
private static <T extends Comparable<T>> T max(List<T> l, int i, int j) {
List<T> sublist = l.subList(i, j);
System.out.println("Sublist "+sublist);
int c = 0;T max = null;
for(T elem: sublist) {
if(c == 0 || max.compareTo(elem) < 0) {
max = elem;
} ++c;
}
return max;
}
and Sun's answer is:
public static <T extends Object & Comparable<? super T>>
T max(List<? extends T> list, int begin, int end) {
T maxElem = list.get(begin);
for (++begin; begin < end; ++begin)
if (maxElem.compareTo(list.get(begin)) < 0)
maxElem = list.get(begin);
return maxElem;
}
Can someone please tell me with an example how Sun's version is better than mine?
EDIT: I want to compare the efficiency of the 2 solutions mainly on the basis of Type parameters/bounds used in the method declaration and not the logic e.g. in what situation(s) Sun's version is better for a caller of the function? Basically I don't understand why you need <T extends Object & Comparable<? super T> and List<? extends T> as used by Sun and not what I have used.
An example is much appreciated as I have been overwhelmed with theory. (Sorry if that sounds rude but I don't mean to be).
Thanks in advance,
Mustafa
There are two separate generics questions here.
Why use an intersection type used?
That is, why does the solution use T extends Object & Comparable<T> instead of the more straightforward T extends Comparable<T>? (I've elided the wildcards in this section; I'll cover them below.)
I don't believe that Object & Comparable<T> is any different from Comparable<T> within the type system, since every object extends Object. That is, there is no type T that extends Comparable<T> that doesn't also extend Object & Comparable<T>.
There is a difference, though. An intersection type erases to the first component of the intersection, so T extends Object & Comparable<T> erases to Object whereas T extends Comparable<T> erases to Comparable. Consider two alternative declarations of the max method:
<T extends Comparable<T>> T max1(List<T> list) { ... }
<T extends Object & Comparable<T>> T max2(List<T> list) { ... }
If you dump the signatures of these methods using javap -s you can see the internal signatures showing the erased types:
<T extends java/lang/Comparable<T>> T max1(java.util.List<T>);
Signature: (Ljava/util/List;)Ljava/lang/Comparable;
<T extends java/lang/Object & java/lang/Comparable<T>> T max2(java.util.List<T>);
Signature: (Ljava/util/List;)Ljava/lang/Object;
Who cares about the erased type? The JVM does. The JVM finds methods based on matching the argument types and the return type. So the erased return type is potentially significant.
And in fact, it is significant from a binary compatibility standpoint. Prior to Java SE 5, when generics were introduced, the Collections.max method was declared and had the erased signature as follows:
public static Object max(Collection coll)
Signature: (Ljava/util/Collection;)Ljava/lang/Object;
In Java SE 5 and later, the declaration and erased signature were:
public static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll)
Signature: (Ljava/util/Collection;)Ljava/lang/Object;
Crucially, the erased signature is the same.
If instead the Java SE 5 declaration weren't declared using an intersection type, it would look like this:
public static <T extends Comparable<? super T>> T max(Collection<? extends T> coll)
Signature: (Ljava/util/Collection;)Ljava/lang/Comparable;
This would be a binary incompatibility. Binaries compiled against old versions of the JDK would refer to a version of max that returns Object. If run against a JDK with this alternate, incompatible declaration, the only version of max would return Comparable instead, resulting in a NoSuchMethodError being thrown at link time.
Thus, the use of <T extends Object & Comparable<T>> is really to control the erasure of this declaration, which is driven by binary compatibility considerations. The tutorial seems somewhat misleading on this point. The actual declaration of Collections.max in Java SE is this way for binary compatibility. But if you were declaring this method for the first time, I don't believe that it would be useful to use an intersection type this way.
Why are wildcards used in the declaration?
That is, instead of:
static <T extends Comparable<T>> T max(List<T> list)
why are wildcards used:
static <T extends Comparable<? super T>> T max(List<? extends T> list)
Here, wildcards are necessary for the method to be used more flexibly in the presence of subtyping. Consider the following:
class A implements Comparable<A> { ... }
class B extends A { }
List<B> bList = ...;
B bMax = max(bList);
If the non-wildcarded declaration were used, there would be no T that matches. In order to make this work, Comparable<? super T> is necessary. This allows T to be inferred as B and everything works.
I must admit that I haven't been able to find an example that shows why List<? extends T> is required in this case. This example works fine if the parameter is declared simply List<T>. It may be that List<? extends T> is used for documentation purposes, to indicate that elements are only retrieved from the list, and that the list is not modified. (For more information on this, see Bloch's Effective Java in the generics chapter where he discusses PECS -- "Producer Extends, Consumer Super"; or Naftalin and Wadler's Java Generics and Collections where they discuss the "Put and Get Principle".)
Links:
Why is T bound by Object in the Collections.max() signature?
Angelika Langer's FAQ entry
Java Generics: What is PECS?
Why do we need bounded wilcard in Collections.max() method
Given some class SomeBaseClass, are these two method declarations equivalent?
public <T extends SomeBaseClass> void myMethod(Class<T> clz)
and
public void myMethod(Class<? extends SomeBaseClass> clz)
For the caller: yes, they are equivalent.
For the code inside the method: no.
The difference is that within the code of the first example you can use the type T (for example to hold an object created by clz.newInstance()), while in the second you can't.
No, they're not. With the first definition, you can use the type T inside the method definition, e.g. create an ArrayList<T> or return T. With the second definition, that's not possible.
Bounded wildcards are subject to certain restrictions to avoid heap pollution.
When you use the wildcard ? extends X you know you can read generic information, but you cannot write.
For instance
List<String> jedis = new ArrayList<String>();
jedis.add("Obiwan");
List<? extends CharSequence> ls = jedis
CharSequence obiwan = ls.get(0); //Ok
ls.add(new StringBuffer("Anakin")); //Not Ok
The compiler avoided heap pollution when you tried to add a CharSequence (i.e. StringBuffer) to the collection. Because the compiler cannot be sure (due to wildcards) that the actual implementation of the collection is of type StringBuffer.
When you use ? super X you know you can write generic information, but you cannot be sure of the type of what you read.
For instance
List<Object> jedis = new ArrayList<Object>();
jedis.add("Obiwan");
List<? super String> ls = jedis;
ls.add("Anakin"); //Ok
String obiwan = ls.get(0); //Not Ok, we canĀ“t be sure list is of Strings.
In this case, due to wildcards, the compiler knows that the actual implementation of the collection could be anything in the ancestors of String. Thus it cannot guarantee that what you will get will be a String. Right?
This same restrictions are the ones you would be subject too in any declaration with bounded wildcards. These are typically known as the get/put principle.
By using a type parameter T you change the story, from the method standpoint you are not using a bounded wildcard but an actual type and therefore you could "get" and "put" things into instances of the class and the compiler would not complain.
For instance, consider the code in Collections.sort method. If we write a method as follows, we would get a compile error:
public static void sort(List<? extends Number> numbers){
Object[] a = numbers.toArray();
Arrays.sort(a);
ListIterator<? extends Number> i = numbers.listIterator();
for (int j=0; j<a.length; j++) {
i.next();
i.set((Number)a[j]); //Not Ok, you cannot be sure the list is of Number
}
}
But if you write it like this, you can do the work
public static <T extends Number> void sort(List<T> numbers){
Object[] a = numbers.toArray();
Arrays.sort(a);
ListIterator<T> i = numbers.listIterator();
for (int j=0; j<a.length; j++) {
i.next();
i.set((T)a[j]);
}
}
And you could even invoke the method with collections bounded with wildcards thanks to a thing called capture conversion:
List<? extends Number> ints = new ArrayList<Integer>();
List<? extends Number> floats = new ArrayList<Float>();
sort(ints);
sort(floats);
This could not be achieved otherwise.
In summary, as others said from the caller standpoint they are alike, from the implementation standpoint, they are not.
No. On top of my head, I can think of the following differences:
The two versions are not override-equivalent. For instance,
class Foo {
public <T extends SomeBaseClass> void myMethod(Class<T> clz) { }
}
class Bar extends Foo {
public void myMethod(Class<? extends SomeBaseClass> clz) { }
}
does not compile:
Name clash: The method myMethod(Class) of type Bar has the same erasure as myMethod(Class) of type Foo but does not override it
If a type parameter appears more than once in a method signature, it always represents the same type, but if a wildcard appears more than once, each occurrence may refer to a different type. For instance,
<T extends Comparable<T>> T max(T a, T b) {
return a.compareTo(b) > 0 ? a : b;
}
compiles, but
Comparable<?> max(Comparable<?> a, Comparable<?> b) {
return a.compareTo(b) > 0 ? a : b;
}
does not, because the latter may be called by
max(Integer.MAX_VALUE, "hello");
The method body may refer to the actual type used by the caller using a type parameter, but not using a wildcard type. For instance:
<T extends Comparable<T>> T max(T... ts) {
if (ts.length == 0) {
return null;
}
T max = ts[0];
for (int i = 1; i < ts.length; i++) {
if (max.compareTo(ts[i]) > 0) {
max = ts[i];
}
}
return max;
}
compiles.
#Mark #Joachim #Michael
see the example in JLS3 5.1.10 Capture Conversion
public static void reverse(List<?> list) { rev(list);}
private static <T> void rev(List<T> list){ ... }
so the <?> version can do anything the <T> version can do.
this is easy to accept if the runtime is reified. a List<?> object must be a List<X> object of some specific non-wildcard X anyway, and we can access this X at runtime. So there's no difference using a List<?> or a List<T>
With type erasure, we have no access to T or X, so there's no difference either. We can insert a T into a List<T> - but where can you get a T object, if T is private to the invocation, and erased? There are two possibilities:
the T object is already stored in the List<T>. so we are manipulating elements themselves. As the reverse/rev example shows, there's no problem doing this to List<?> either
it comes out-of-band. There's other arrangement made by the programmer, so that an object somewhere else is guaranteed to be of type T for the invocation. Unchecked casting must be done to override compiler. Again, no problem to do the same thing to List<?>