Java泛型你所不知道的点

程序员小迷 2024-04-24 17:58:54

1.泛型方法可以在任何地方和任何场景中使用,包括普通类和泛型类。

泛型类型参数可以是任何引用类型,包括数组和其他泛型类型。

泛型的类型参数不支持基本类型(需要用包装类)。

当显式提供类型参数时,Java 语言不支持省略调用该方法的类或对象,否则会出现这样错误的代码<String>.callMethod("foo","bar")。

2.限定类型中,只允许有一个类(单继承导致,可以允许多个接口),而且如果有类,这个类必须是限定列表的第一个。

这种类的限定既可以用在泛型方法上也可以用在泛型类上。

不能使用|子句将泛型参数绑定到任一类型。可使用&绑定到多个类型。

3.运行时类型查询只适用于原始类型

1)if(restrict instanceOf Restrict<Double>){}//合法

2)if(restrict instanceOf Restrict<T>){}//不合法

3)Restrict<Double> restrictDouble=new Restrict<>();

Restrict<String> restrictString=new Restrict<>();

System.out.println(restrictDouble.getClass()==restrictString.getClass());//合法,返回true

4.你始终可以使用无界通配符 (?)在 instanceof 中指定类型,如下所示:

public boolean isAList(Object obj) {

return obj instanceof List<?>;//合法

}

5.以下代码是合法的

class Solution<T> {

public boolean isTypeARandomString(T t) {

return t instanceof String; //合法

}

public boolean isTypeInstanceOfAString(String s) {

return s instanceof T; // 不合法

}

}

6.泛型类在静态上下文中类型变量失效。

不能在静态域或方法中引用类型变量。但若静态方法本身是泛型方法,就可以。

7.不能创建参数化类型的数组。

Restrict<Double>[] restrictArray;//合法

Restrict<Double>[] restrictArray=new Restrict<Double>[10];//不合法

8.不能实例化类型变量。

9.不能捕获泛型类的实例。

10.自定义的泛型类不能extends Exception/Throwable

class Problem<T> extends Exception{}//不合法

但是这样可以:

public <T extends Throwable> void doWork(T t) throws T{

try{

}catch(Throwable e){

throw t;

}

}

11.泛型类可以继承或者扩展其他泛型类,比如List和ArrayList.

? extends X

对泛型类来说,如果其中提供了get和set类型参数变量的方法的话,set方法是不允许被调用的,会出现编译错误。

? super X

对泛型类来说,如果其中提供了get和set类型参数变量的方法的话,set方法可以被调用的,且能传入的参数只能是X或者X的子类。get方法只会返回一个Object类型的值。

12.泛型技术在C#和Java之中的使用方式看似相同,但实现上却有着根本性的分歧。

C#里面泛型无论在程序源码中、编译后的IL中(Intermediate Language,中间语言,这时候泛型是一个占位符),或是运行期的CLR中,都是切实存在的,List<int>与List<String>就是两个不同的类型,它们在系统运行期生成,有自己的虚方法表和类型数据,这种实现称为类型膨胀,基于这种方法实现的泛型称为真实泛型。

Java语言中的泛型则不一样,它只在程序源码中存在,在编译后的字节码文件中,就已经替换为原来的原生类型(Raw Type,也称为裸类型)了,并且在相应的地方插入了强制转型代码,因此,对于运行期的Java语言来说,ArrayList<int>与ArrayList<String>就是同一个类,所以泛型技术实际上是Java语言的一颗语法糖,Java语言中的泛型实现方法称为类型擦除,基于这种方法实现的泛型称为伪泛型。

另外,从Java字节码中Signature属性里我们还可以得出结论,擦除法所谓的擦除,仅仅是对方法的Code属性中的字节码进行擦除,实际上元数据中还是保留了泛型信息,这也是我们能通过反射手段取得参数化类型的根本依据。

微风不燥,阳光正好,你就像风一样经过这里,愿你停留的片刻温暖舒心。

我是程序员小迷(致力于C、C++、Java、Kotlin、Android、Shell、JavaScript、TypeScript、Python等编程技术的技巧经验分享),若作品对您有帮助,请关注、分享、点赞、收藏、在看、喜欢,您的支持是我们为您提供帮助的最大动力。

欢迎关注。助您在编程路上越走越好!

0 阅读:33