peter.petrov
peter.petrov

Reputation: 39477

Type erasure - Generics - getting ClassCastException not where expected

I was going through this page, just playing with the examples it provides.

http://docs.oracle.com/javase/tutorial/java/generics/bridgeMethods.html

I am using Java 8.

According to this tutorial page, the ClassCastException should be thrown at that line 200, but actually it's thrown earlier - at the line marked as 100. Why?! Is the tutorial outdated (not applicable to Java 8)?

Then I asked for all methods of n and I can see the method setData(Object) is there, it's in the Object pointed to by n (this is the so-called bridge method, I assume).

OK, so why do I get the exception at the line marked as 100? Is the compiler transforming my set call to this n.setData((Integer)"Hello"); If so, seems the tutorial is outdated indeed.

Could anyone explain this?

import java.lang.reflect.Method;

public class Test010 {

    public static void main(String[] args) {
        MyNode mn = new MyNode(5);
        Node n = mn; // A raw type - compiler throws an unchecked warning
        Method meth[] = n.getClass().getMethods();
        n.setData("Hello"); // 100 //
        System.out.println("001");
        Integer x = mn.data; // 200 // // Causes a ClassCastException to be thrown.
    }

}

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;
    }
}

class MyNode extends Node<Integer> {

    public MyNode(Integer data) {
        super(data);
    }

    public void setData(Integer data) {
        System.out.println("MyNode.setData");
        super.setData(data);
    }
}

Upvotes: 1

Views: 94

Answers (3)

LiYi Zhang
LiYi Zhang

Reputation: 1

Yes, the tutorial confuses me a lot. the comments in the following code doesn't indicate what happens when jvm executes these codes.

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.

It's just assumed that setData in Node was not overridden.

But actually the bridge method overrides the setData in Node and made it seems like it was overridden by the setData in MyNode.

And that will be more like a polymorphism is such a case.

Upvotes: 0

peter.petrov
peter.petrov

Reputation: 39477

OK, well, I figured it out shortly after posting the question here.

Actually the exception thrown at line 200: this is not a fact, the tutorial is just hypothetically mentioning that. Further down in the tutorial, it's clear that the bridge setData method contains a type cast to Integer.

public void setData(Object data) {
    setData((Integer) data);
}

That's what's causing my problem and my confusion.

In any case, this tutorial page seems a bit confusing, but OK, maybe it's just me.

Upvotes: 4

John Bollinger
John Bollinger

Reputation: 181734

I'm inclined to say that the tutorial is just wrong. It would be correct if class MyNode were not involved, or if MyNode inherited Node<T> generically, instead of specifying by the type parameter concretely. Once MyNode defines a specific value for the type parameter, however, type erasure no longer applies to it.

Upvotes: 1

Related Questions