ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Java的泛型机制

2022-02-22 12:01:29  阅读:119  来源: 互联网

标签:map Java 数据类型 接口 类型 泛型 机制


Java的泛型机制

泛型是 Java 从 JDK5 开始引入的新特性,本质上是参数化类型,即所操作的数据类型被指定为一个参数。这意味着编写的代码可以被很多不同类型的对象所重用。

1. 泛型的使用方式

1.1 泛型类

用下面的语法可以定义一个泛型类:

class C< T, E, ...>{
    private T t;
    ...
}

常用的泛型标识有 T、E、K、V。

用下面的语法可以创建一个泛型对象:

C<具体的数据类型> c = new C<>();

泛型类有以下注意事项:

  • 如果没有指定具体的数据类型,操作类型是 Object。
  • 泛型的类型参数只能是类类型,不能是基本数据类型。
  • 泛型类型在逻辑上看作多个不同类型,但实际上是相同类型。

用下面的语法可以从泛型类派生子类:

// 子类也是泛型类,要和父类的泛型类型保持一致。但可以添加更多类型。
class Child<T> extends Father<T>
class Child<T, E, K> extends Father<T>  
// 子类不是泛型类,父类要明确一个泛型的数据类型
class Child extends Father<String>

1.2 泛型接口

定义方式类似于泛型类。

当需要用一个类实现泛型接口时:

  • 如果实现类不是泛型类,接口要明确数据类型。
  • 如果实现类是泛型类,实现类和接口的泛型类型要一致,但也可以增加更多。

1.3 泛型方法

用下面的语法可以定义一个泛型方法:

public <T, E, ...> void f(){
    ...
}

泛型类的类型由构造对象时决定,泛型方法的类型由调用方法时决定。

1.4 类型通配符

我们用?作为类型通配符,代表具体的类型实参。

使用extends语句可以代表类型通配符的上限:

类/接口<? extends 实参类型>

要求该泛型的类型,只能是实参类型或者实参类型的子类类型。

使用super语句可以代表类型通配符的下限:

类/接口<? super 实参类型>

带有超类型限定的通配符可以向泛型对象写入,带有子类型限定的通配符可以从泛型对象读取。

2. 类型擦除式泛型

Java 的泛型实现方式是类型擦除的伪泛型。在 Java 中,泛型只在程序源码中存在,编译后的字节码文件中泛型全部被擦除,替换为原来的裸类型,并在相应的位置插入了强制转型代码。

假设我们有下面这段代码:

public static void main(String[] args){
	Map<String, String> map = new HashMap<String, String>();
    map.put("hello", "你好");
    System.out.pirntln(map.get("hello"));
}

这里向泛型类型为<Stirng, String>的 map 内插入了一个键值对,又从中将值取出。如果我们先将这段 Java 代码编译为 Class 文件,又反编译 Class 文件,实际上会得到以下代码:

public static void main(String[] args){
	Map map = new HashMap();
    map.put("hello", "你好");
    System.out.pirntln((String)map.get("hello"));
}

显然,在前端编译过程中,对象的泛型类型被擦除,转换为了没有泛型的裸类型。而在字节码文件的相关位置插入了强制类型转换代码,从而实现泛型。

类型擦除式的泛型带来了几个严重的问题:

Ⅰ. 不支持基础数据类型的泛型

由于我们无法在 int、long 等基础数据类型和 Object 之间强制转型,所以 Java 的泛型不支持基础数据类型。

Ⅱ. 运行时无法获取泛型类型信息

加入我们想写一个泛型版本的 List 转换为数组的方法,由于不能再运行时获取泛型信息,只能再传入一个元素的类型。

public static <T> T[] convert(List<T> list, Class<T> componentType){
    Tp[] array = (T[])Array.newInstance(componentType, list.size());
}

Ⅲ. 无法正常的实现重载等功能

例如两个方法我们试图依赖泛型类型不同来实现重载,就会发生编译错误。因为泛型类型在前端编译器被擦除了,变成了两个一模一样的方法。

3. 桥接方法的机制

当一个类实现一个泛型接口时,泛型接口在编译后类型被擦除,这样我们在实现类中就不能找到对应接口的实现方法。为了解决这个问题,Java 在编译相关类时使用了一个桥接方法的机制,通过为实现类新增一个桥接方法,来实现类型擦除后接口的方法。

image-20220222114826866

标签:map,Java,数据类型,接口,类型,泛型,机制
来源: https://www.cnblogs.com/WangXianSCU/p/15922477.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有