Reputation: 27375
Consider example from the official help:
public class Node<T>{
private T data;
public Node(T data){ this.data=data; }
public void setData(T data){
System.out.println("Node.setData");
this.data=data;
}
}
public class MyNode extends Node<Integer>{
public MyNode (Integer data){ super(data); }
public void setData (Integer data){
System.out.println("MyNode.setData");
this.data=data;
}
}
public class MyClass{
public static void main(String[] args){
Node n = new MyNode(5);
n.setData(new Object());//ok
}
}
What does mean Node n= new MyNode(5);
? Node n
is reference to raw type, but i describe Node<T>
as generic class. Does raw type Node
is supertype of generic type Node<T>
for all T
? Is it true that if we define a reference to raw type Node n
, where Node<T>
is generic type compiler doesnt type checked, but started type erasure in Node<T>
? Statement that compiler matched T
to Object
by default is wrong because Node<Object>
isn't supertype for Node<Integer>
.
What is type parameter T
in Node<T>
for compiler? Is it true that compiler considering T
just as a reference type, but he doesnt know about description of T
?
Upvotes: 0
Views: 272
Reputation: 1508
1)
Node n= new MyNode(5);
You have a raw (unspecified type) Node reference pointing to a MyNode object (a subclass of Node<Integer>
).
Does raw type Node is supertype of generic type Node for all T?
Node is not a superclass (supertype) of Node<T>
Is it true that if we define a reference to raw type Node n, where
Node<T>
is generic type compiler doesnt type checked, but started type erasure inNode<T>
?
The compiler checks references only, if your references are raw then you can add any type you want. Generics were introduced to the Java language to provide tighter type checks at compile time and to support generic programming. Generics are a compiler only issue, during compilation types are erased (erasure) and generics incur no runtime overhead.
Statement that compiler matched T to Object by default is wrong because
Node<Object>
isn't supertype forNode<Integer>
.
You haven't specified a type for your generic class Node, this is equivalent to Node<Object>
. Node<Object>
is not a superclass of Node<Integer>
nor is any combination of Node<A>
and Node<B>
They are all the same class at runtime!
2)
Type T is what you specify when you use it. In the Node class definition, T is merely a placeholder so you can use the same type in the next line to specify the data type. Think of the T in Node<T>
as a parameter than can be used elsewhere in the class. (You can replace T with any variable you want however it is convention to use T unless it is a collection where we use E).
Consider the following...
public class MyClass extends ArrayList<Integer> {
public static void main(String[] args) {
ArrayList<Integer> a = new MyClass();
a.add(new Integer(5));
ArrayList b = a;
b.add(new String("abc"));
for (Integer i : a) {
//System.out.print(i);
}
}
}
This will compile just fine because a is an ArrayList.
Remember that generics are only for the compiler so once compiled they do not affect the code anymore. We can alias the same object with the reference b which is of raw type, thus allowing us to add other Objects to the list (such as a string).
Now when we try to loop through a as an ArrayList of Integers we are surprised at run-time to discover that it contains a String, perfectly allowable to have added (as all ArrayLists are ArrayList<Object>
at runtime) however not allowed to be cast to an Integer.
Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
at MyClass.main(MyClass.java:11)
Upvotes: 2