写点什么

java 教程——泛型(三)

作者:Java高工P7
  • 2021 年 11 月 11 日
  • 本文字数:1822 字

    阅读完需:约 6 分钟

Java 使用擦拭法实现泛型,导致了:


  • 编译器把类型<T>视为Object

  • 编译器根据<T>实现安全的强制转型。


使用泛型的时候,我们编写的代码也是编译器看到的代码:


selfMap<String> one = new selfMap<>("name","易齐");


String value = one.getValue();


System.out.println("value ->" + value);


而虚拟机执行的代码并没有泛型:


selfMap one = new selfMap("name","易齐");


String value = (String)one.getValue();


System.out.println("value ->" + value);


所以,Java 的泛型是由编译器在编译时实行的,编译器内部永远把所有类型T视为Object处理,但是,在需要转型的时候,编译器会根据T的类型自动为我们实行安全地强制转型。


局限


==


局限一:<T>不能是基本类型,例如int,因为实际类型是ObjectObject类型无法持有基本类型:


局限二:无法取得带泛型的Class。观察以下代码:



从打印结果我们可以很直观的看到:无法取得带泛型的Class。``其原因就是我们上面说的,泛型 是在编译器编译的时候实现的,到虚拟机中都是selfMap<Object>,所以,现在是不是明白了为什么打印的是一样的Class实例了。


局限三:无法判断带泛型的类型:



局限四:不能实例化T类型:



如果你偏要实例化,也不是不可以,那我们得动用实例化第二种方法了:反射



上述代码借助Class<T>参数并通过反射


【一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义】
浏览器打开:qq.cn.hn/FTf 免费领取
复制代码


来实例化T类型,使用的时候,也必须传入Class<T>。例如:


selfMap<String> stringselfMap = new selfMap<>(String.class);


因为传入了Class<String>的实例,所以我们借助String.class就可以实例化String类型。

泛型继承

一个类可以继承自一个泛型类。例如:父类的类型是selfMap<String>,子类的类型是selfStringMap,可以这么继承:


class selfStringMap extends selfMap<String>{


public selfStringMap(String key, String value) {


super(key, value);


}


}


使用的时候,因为子类selfStringMap并没有泛型类型,所以,正常使用即可:


selfStringMap selfStringMap = new selfStringMap("name", "易齐");


前面讲了,我们无法获取selfMap<String>T类型,即给定一个变量selfMap<String> p,无法从p中获取到String类型。


但是,在父类是泛型类型的情况下,编译器就必须把类型T(对selfStringMap来说,也就是String类型)保存到子类的 class 文件中,不然编译器就不知道selfStringMap只能存取String这种类型。


个人理解:因为子类又不是泛型,所以,你不能用檫试法来保存具体类型,即子类只能将具体类型存入自己的 class 文件中。


在继承了泛型类型的情况下,子类可以获取父类的泛型类型。例如:selfStringMap可以获取到父类的泛型类型String。获取父类的泛型类型代码比较复杂:


package test;


import java.lang.reflect.ParameterizedType;


import java.lang.reflect.Type;


import java.util.Arrays;


public class changeData {


public static void main(String[] args) {


Class<selfStringMap> selfStringMapClass = selfStringMap.class;


Type t = selfStringMapClass.getGenericSuperclass();


if (t instanceof ParameterizedType){


ParameterizedType pt = (ParameterizedType) t;


Type[] types = pt.getActualTypeArguments();


System.out.println(Arrays.toString(types));


}


}


}


class selfStringMap extends selfMap<String>{


public selfStringMap(String key, String value) {


super(key, value);


}


}


class selfMap<T> extends Object{


private T Key;


private T value;


public selfMap(T key,T value) {


this.Key = key;


this.value = value;


}


public T getTey() {


return Key;


}


public T getValue() {


return value;


}


}



因为 Java 引入了泛型,所以,只用Class来标识类型已经不够了。实际上,Java 的类型系统结构如下:


┌────┐


│Type│


└────┘




┌────────────┬────────┴─────────┬───────────────┐


│ │ │ │


┌─────┐┌─────────────────┐┌────────────────┐┌────────────┐


│Class││ParameterizedType││GenericArrayType││WildcardType│


└─────┘└─────────────────┘└────────────────┘└────────────┘

小结

Java 的泛型是采用擦拭法实现的;


擦拭法决定了泛型<T>

用户头像

Java高工P7

关注

还未添加个人签名 2021.11.08 加入

还未添加个人简介

评论

发布
暂无评论
java教程——泛型(三)