源码网商城,靠谱的源码在线交易网站 我的订单 购物车 帮助

源码网商城

详解java 中泛型中的类型擦除和桥方法

  • 时间:2020-03-11 12:42 编辑: 来源: 阅读:
  • 扫一扫,手机访问
摘要:详解java 中泛型中的类型擦除和桥方法
在Java中,泛型的引入是为了在编译时提供强类型检查和支持泛型编程。为了实现泛型,Java编译器应用类型擦除实现:        1、  用类型参数(type parameters)的限定(如果没有就用Object)替换泛型类型中的所有类型参数。        2、  需要保持类型安全的时候插入类型转换(隐含插入)        3、  在extened 泛型类型中生成桥方法来保证多态性    类型擦除确保不会为已参数化了的类型(paramterized types)产生新类,这样泛型能保证没有运行时的负载。 泛型类型擦除       在类型擦除过程中,java编译器擦除所有类型参数,用它的限定或者Object(没限定时)替换。      考虑下面的泛型类:
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; } 
 // ... 
} 
因为类型参数T是非限定的,Java编译器使用Object替换它:
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; } 
 // ... 
} 
下面的例子,泛型Node类使用了限定类型参数:
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; } 
 // ... 
编译器会使用第一个限定类,Comparable替换限定参数类型T:
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; } 
 // ... 
} 
同样,泛型方法也可以擦除。规则类似,不细说。 [b]类型擦除的影响和桥方法[/b] 有时候类型擦除会引起无法预知的情况。比如: 给定以下两个类:
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 = mn;   // 原生类型 – 编译器会给出未检查警告 
n.setData("Hello");  
Integer x = mn.data; // 会引发抛出ClassCastException 
 类型擦除后,代码变成:
MyNode mn = new MyNode(5); 
Node n = (MyNode)mn;   //原生类型 – 编译器会给出未检查警告 
n.setData("Hello"); 
Integer x = (String)mn.data; //会引发抛出ClassCastException 
public class Node { 
 
 public Object data; 
 
 public Node(Object data) { this.data = data; } 
 
 public void setData(Object data) { 
  System.out.println("Node.setData"); 
  this.data = data; 
 } 
} 
 
public class MyNode extends Node { 
 
 public MyNode(Integer data) { super(data); } 
 
 public void setData(Integer data) { 
  System.out.println("MyNode.setData"); 
  super.setData(data); 
 } 
} 
类型擦除后,方法的签名已经不匹配。Node 方法变成setData(Object),MyNode方法变成setData(Integer)。MyNode setData方法已经不是覆盖Node setData方法。 为了解决这个问题,维持泛型类型的多态性,java编译器会生成一个桥方法:
class MyNode extends Node { 
 
 // 编译器生成的桥方法 
 // 
 public void setData(Object data) { 
  setData((Integer) data); 
 } 
 
 public void setData(Integer data) { 
  System.out.println("MyNode.setData"); 
  super.setData(data); 
 } 
 
 // ... 
感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!
  • 全部评论(0)
联系客服
客服电话:
400-000-3129
微信版

扫一扫进微信版
返回顶部