擦除规则

1. 如果是无界限的则会把类型参数替换成Object，如果是有界限的则会把类型参数替换为界限类型。
2. 插入一些类型转换来保证类型安全
3. 为了保证从泛型类型继承的多态性会增加一些桥接方法。

泛型类型的擦除

无边界类型擦除

public class Node<T> {

private T data;
private Node<T> next;

public Node(T data, Node<T> next) {
this.data = data;
this.next = next;
}

public T getData() { return data; }
// ...
}


public class Node {

private Object data;
private Node next;

public Node(Object data, Node next) {
this.data = data;
this.next = next;
}

public Object getData() { return data; }
// ...
}


有边界类型擦除

public class Node<T extends Comparable<T>> {

private T data;
private Node<T> next;

public Node(T data, Node<T> next) {
this.data = data;
this.next = next;
}

public T getData() { return data; }
// ...
}


public class Node {

private Comparable data;
private Node next;

public Node(Comparable data, Node next) {
this.data = data;
this.next = next;
}

public Comparable getData() { return data; }
// ...
}


泛型方法的类型擦除

无边界类型擦除

public static <T> int count(T[] anArray, T elem) {
int cnt = 0;
for (T e : anArray)
if (e.equals(elem))
++cnt;
return cnt;
}


public static <T> int count(T[] anArray, T elem) {
int cnt = 0;
for (T e : anArray)
if (e.equals(elem))
++cnt;
return cnt;
}


有边界类型擦除

class Shape { /* ... */ }
class Circle extends Shape { /* ... */ }
class Rectangle extends Shape { /* ... */ }
public class Util {
public static <T extends Shape> void draw(T shape) { /* ... */ }
}


类型擦除桥接方法

public class ANode<T> {

public T data;

public ANode(T data) { this.data = data; }

public void setData(T data) {
System.out.println("Node.setData");
this.data = data;
}

public T getData() { return data; }
// ...
}


public class ANode {

private Object data;

public ANode(Object data) { this.data = data; }

public void setData(Object data) {
System.out.println("Node.setData");
this.data = data;
}

public Object getData() { return data; }
// ...
}


public class MyNode extends ANode<Integer> {
public MyNode(Integer data) {
super(data);
}

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


public class MyNode extends ANode {
public MyNode(Integer data) {
super(data);
}

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


    public static void main(String[] args) {
ANode n = new MyNode(5);
n.setData("Hello");
Integer x = (Integer) n.getData();    // Causes a ClassCastException to be thrown.
}


1. setData("Hello")调用的参数其实Object，是父类的方法，因为子类的参数是Integer。
2. 然后getData()返回的是Object类型，但指向的还是String类型，强转依然会报错。

Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
at com.sweetop.studycore.generic.MyNode.main(MyNode.java:18)


public class MyNode extends ANode {
public MyNode(Integer data) {
super(data);
}

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

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


 public static void main(String[] args) {
ANode n = new MyNode(5);
Object a = "1";
if (a instanceof Integer) {
n.setData("1");
}
Integer x = (Integer) n.getData();    // Causes a ClassCastException to be thrown.
}