I was reviewing one of the Oracle trails on Java generics, entitled "Effects of Type Erasure and Bridge Methods", and I could not convince myself of an explanation given. Curious, I tested the code locally and I could not even reproduce the behavior which the trail explains. Here is the relevant code:
public class Node<T> {
public 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");
super.setData(data);
}
}
The Oracle trail claims the following behavior for this code snippet:
MyNode mn = new MyNode(5);
Node n = mn; // A raw type - compiler throws an unchecked warning
n.setData("Hello");
Integer x = mn.data; // Causes a ClassCastException to be thrown.
This code snippet should look like the following after type erasure:
MyNode mn = new MyNode(5);
Node n = (MyNode)mn; // A raw type - compiler throws an unchecked warning
n.setData("Hello");
Integer x = (String)mn.data; // Causes a ClassCastException to be thrown.
I did not understand the casts being used here or the behavior. When I tried running this code locally using IntelliJ with Java 7, I got this behavior:
MyNode mn = new MyNode(5);
Node n = mn; // A raw type - compiler throws an unchecked warning
n.setData("Hello"); // Causes a ClassCastException to be thrown.
Integer x = mn.data;
In other words, the JVM will not allow a String
to be used with setData()
. This is actually intuitive to me, and it agrees with my understanding of generics. Since MyNode
mn
was constructed with Integer
, the compiler should be casting every call to setData()
with Integer
to ensure type safety (i.e. an Integer
is being passed in).
Can someone shed some light on this apparent bug in the Oracle trail?
According to oracle documentation, the following points are the disadvantage of generics: Cannot instantiate Generic types with primitive types. Cannot create instances of type parameters. Cannot declare static fields whose types are type parameters.
In a nutshell, generics solves the problem of having to use loosely typed objects. For example, consider ArrayList vs List<T> . It allows you to have a strongly typed collection.
By using generics, programmers can implement generic algorithms that work on collections of different types, can be customized, and are type safe and easier to read.
You've misread the Oracle page. If you read all the way to the end, you'll find it states that what happens is what you describe.
It's not a well-written page; the author says "blah happens" when what they mean is "IF THIS WERE THE CASE THEN blah happens BUT AS WE'LL SEE THAT IS NOT THE CASE". They are being too loose with their language.
The point of the page - bridge methods - is to explain how the real behaviour is as you observed, when the predicted behaviour (based on Generics acutal design + implementation) is what they "suggested" at the start.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With