Java Type Erasure: Rules of cast insertion?

三世轮回 提交于 2019-12-12 02:30:43

问题


The Java tutorial on type erasure doesn't seem to detail the specific rules of cast insertion by the compiler. Can someone please explain the specific rules that cause the transformation detailed by the tutorial (reproduced below):

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

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.

Specifically, I'm wondering what rules cause the insertion of (MyNode) and (String). When is a cast inserted, and how is the type chosen for the cast?


回答1:


  1. MyNode mn = new MyNode(5);

    • will create an instance of MyNode which defines the generic type T of interface Node as Integer
    • casting: no casting necessary by developer, no casts added by compiler
  2. Node n = (MyNode)mn;

    • this will basically tell the compiler forget about the generic type T and use the interface Node completely without generics which will have the following consequence: imagine generic type T to be treated as java.lang.Object
    • casting: no casting necessary by developer, no casts added by compiler
  3. n.setData("Hello");

    • will allow you to add any kind ob object because T is treated as Object (String, Integer, array, anything else)
    • casting: no casting necessary by developer, no casts added by compiler
  4. Integer x = mn.data;

    • nm.data should return an Integer type as Integer is defined as generic type argument T in the MyNode class
    • however because you used raw types which allowed you to add a String instead, the nm.data holds a String instance
    • casting: no casting necessary by developer, however the compiler will add casts to Integer behind the scenes for you and because of type mismatch, you will get the ClassCastException



回答2:


The ClassCastException would be throw when a call is made to

n.setData("Hello");

This is because the compiler builds bridge methods to preserve polymorphism. The bridge method will look like:

 public void setData(Object data) {
       setData((Integer)data);   //the exception is thrown here
  }

since an instance of a string cannot be converted to Integer, the ClassCastException would be thrown.

You can read about bridge methods here.



来源:https://stackoverflow.com/questions/29587502/java-type-erasure-rules-of-cast-insertion

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!