欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2023-12-11 18:30:22
在java中,泛型的引入是为了在编译时提供强类型检查和支持泛型编程。为了实现泛型,java编译器应用类型擦除实现:     &nb...

在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; } 
 // ... 
} 

同样,泛型方法也可以擦除。规则类似,不细说。

类型擦除的影响和桥方法

有时候类型擦除会引起无法预知的情况。比如:

给定以下两个类:

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

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

上一篇:

下一篇: