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

作者:lqh 时间:2021-07-10 23:55:08 

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

// ...

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

来源:http://blog.csdn.net/Allenalex/article/details/50246985

标签:java,泛型,桥方法
0
投稿

猜你喜欢

  • C#实现递归调用的Lambda表达式

    2022-10-03 05:13:29
  • Java编程实现判断网上邻居文件是否存在的方法

    2022-12-27 09:49:46
  • Android 点击ImageButton时有“按下”的效果的实现

    2022-04-10 05:11:23
  • 为SpringBoot服务添加HTTPS证书的方法

    2023-10-11 03:03:22
  • Java命令行下Jar包打包小结

    2023-01-04 19:25:44
  • JavaFX实现UI美观效果代码实例

    2021-08-27 21:02:15
  • Android studio 3.0上进行多渠道打包遇到的问题小结(超简洁版)

    2022-09-16 07:58:40
  • 详解如何利用C#实现设置系统时间

    2023-09-04 13:55:05
  • Java 中HttpURLConnection附件上传的实例详解

    2022-05-26 13:54:39
  • redisson特性及优雅实现示例

    2022-02-13 19:51:25
  • spring boot 即时重新启动(热更替)使用说明

    2023-01-19 02:41:05
  • android实现图片裁剪的两种方法

    2022-10-27 18:41:05
  • 深入学习Java 热部署的知识

    2023-10-16 18:23:24
  • Java concurrency集合之 CopyOnWriteArrayList_动力节点Java学院整理

    2022-10-27 05:03:36
  • SpringCloud Eureka服务治理之服务注册服务发现

    2021-12-27 15:07:16
  • C#函数式程序设计之用闭包封装数据的实现代码

    2021-06-30 01:44:34
  • 老生常谈Java异常处理和设计(推荐)

    2023-08-21 02:26:06
  • java实现大文件分割与合并的实例代码

    2023-11-11 04:31:21
  • c# 获得局域网主机列表实例

    2022-07-12 21:46:58
  • Mybatis SqlSessionFactory与SqlSession详细讲解

    2021-12-24 22:42:56
  • asp之家 软件编程 m.aspxhome.com