Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Potential issue with one of Oracle's trails on Java generics

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?

like image 972
Tim Biegeleisen Avatar asked Jan 26 '16 15:01

Tim Biegeleisen


People also ask

What is the disadvantages of using generics?

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.

What problem does generics solve?

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.

Is it a good idea to use generics in collections?

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.


1 Answers

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.

like image 117
Adam Avatar answered Oct 02 '22 10:10

Adam