公共无效乐趣(){
ArrayList arr=new ArrayList(); //没有使用泛型定义的集合
arr.add(1);
arr.add("你好");
//编译器无法发现下面的代码是错误的,但是JVM运行时会抛出ClassCastException类型转换异常。
String s=(String)arr.get(0);
s.trim();
}
2. 泛型为什么是语法糖?
Sun引入泛型后,编译器并没有强制要求在使用泛型类时必须明确定义泛型,但会出现黄色警告线。即使使用泛型类显式定义泛型后,编辑器也会执行类型擦除,即JVM 根本不识别泛型!
如果不进行类型擦除,很多JDK1.5之前的代码将无法兼容,所以使用语法糖来保持兼容性,但是对语法糖也带来了许多的弊端。
3.1 语法糖的弊端引入之一(数组与集合进行PK)
数组和集合进行了PK。数组说,我可以使用多态性定义
@测试
公共无效显示(){
对象[] arr=new String[2];
arr[0]="你好";
arr[1]=1; //语法没有问题,编辑没有错误,但是运行时会抛出ArrayStoreException数组错误类型存储异常。
}集合也想用泛型来做到这一点,但是一旦集合允许,JVM就没有办法为接下来的操作list.add(1);抛出异常,因为泛型是语法糖,编译器会执行类型擦除除此之外,JVM 不知道泛型!
所以编译阶段不允许存在这个语法,使用泛型前后必须保持类型一致。@Test
公共无效show2(){
ArrayList列表=新的ArrayList(); //这里编译错误
列表.add("你好")
//列表.add(1);
}
3.2 语法糖的弊端引入之二(形式参数)
以下面代码为例。使用泛型作为形参时,如果传递的参数是new ArrayList(),则相当于ArrayListarr=new ArrayList()。由于使用泛型前后类型必须一致,所以传递的实际参数只能是new ArrayList()。
公共无效方法(ArrayListarr){
}
@测试
公共无效显示(){
ArrayListarr1=new ArrayList();
ArrayListarr2=new ArrayList();
方法(arr1);
method(arr2);//这里编译错误
}
4. 泛型通配符的引入
如果上面的代码还需要传入泛型Number类型呢?让我们先把方法的多功能性放在一边,来想一个解决方案。为什么不尝试方法重载呢?一件非常尴尬的事情发生了。由于泛型是语法糖,因此编译后将执行类型擦除。我们眼中的重载方法简单来说就是一个方法!public void method(ArrayListarr) { //编译错误
}
public void method(ArrayListarr) { //编译错误
}于是,Sun公司的天才们引入了一种新的语法——通用通配符。泛型通配符的出现解决了方法可重用性的问题,特别是当泛型用作形式参数时,但其他本身还存在一些问题。
公共无效方法(ArrayList?arr){
}
5.1 无界泛型通配符弊端
当无界泛型通配符作为形参时,作为调用方,实际传递的参数类型不受限制。然而,在方法内部,泛型类的参数和返回值为泛型的方法,不能使用!泛型类ArrayList仅在创建对象时指定泛型的类型。然而,在method方法中声明的局部变量arr中,指定的泛型是?对应的T get(int index)和boolean add(T t)方法都是T?它是任意类型,因此该方法无效。
公共无效方法(ArrayList?arr){
Stirng s=arr.get(0);//编译错误
arr.add("hello");//编译错误
}
@测试
公共无效显示(){
ArrayListarr1=new ArrayList();
ArrayListarr2=new ArrayList();
方法(arr1);
方法(arr2);
}
5.2 子类限定泛型通配符弊端
//注意:Integer类是final修饰的,不能有子类。以下代码只是一个示例。
为了解决上述问题,出现了另一种语法——子类限定泛型通配符。调用方法时,只能传递其本身或其子类。调用者有一定的限制,但上帝已经关闭了它。一扇门还必须打开另一扇窗~~方法内部,泛型类的返回值为泛型的方法,可以使用了。方法method声明的局部变量arr,指定的泛型是? extends Integer,调用该方法时,ArrayList中的T必须是Integer对象或者Integer对象的子类。
对于T get(int index),返回的是Integer 对象或Integer 对象的子类。使用整数对象进行接收,父类引用指向子类对象。
对于boolean add(T t),要求传入的参数是Integer或者Integer的子类,所以不能传递Integer对象。
公共无效方法(ArrayList?扩展Integerarr){
整数i=arr.get(0);
arr.add(123);//编译错误
}
@测试
公共无效显示(){
ArrayListarr1=new ArrayList();
ArrayListarr2=new ArrayList();
方法(arr1);
method(arr2);//编译错误
}
5.3 父类限定泛型通配符弊端
父类限定通用通配符只能在调用者处传递其自身或其父类。方法内部,泛型类的参数列表为泛型的方法,可以使用了。方法method声明的局部变量arr,指定的泛型是? super Integer,调用该方法时,ArrayList中的T必须是Integer对象或者Integer对象的父类。
对于T get(int index),返回的是Integer对象或者Integer对象的父类,Integer对象不能用于接收。
对于boolean add(T t),要求传入的参数是Integer对象或者Integer对象的父类。如果传入Integer对象,父类引用就指向子类对象,这就是多态的原理。
公共无效方法(ArrayList?超级Integerarr){
Integer i=arr.get(0);//编译错误
arr.add(123);
}
@测试
公共无效显示(){
ArrayListarr1=new ArrayList();
ArrayListarr2=new ArrayList();
方法(arr1);
方法(arr2);
}
6. 总结
当定义泛型类作为方法的形参时,有以下几种情况:
1:只使用泛型,不使用泛型通配符。公共无效添加(ArrayListarr){}
实际参数只能以定义变量的受限数据类型传递。
2:使用无界通用通配符,public void add(ArrayList?arr){}
不能使用参数和返回值都是泛型的泛型方法。
3:使用子类限定通用通配符,public void add(ArrayList? extends Integerarr){}
参数列表为泛型的方法不能在泛型类中使用。
4:使用父类限定泛型通配符,public void add(ArrayList? super Integerarr){}
不能使用返回值为泛型的泛型方法
在定义方法时,需要根据实际情况进行具体分析。
导入java.util.ArrayList;
公开课演示{
Tt;
//对于第一种情况
公共无效show1(ArrayListarr){
}
//对于第二种情况
公共无效show2(ArrayList?arr){
}
//对于第三种情况
公共无效show3(ArrayList?扩展塔尔){
T t=arr.get(0);
}
//针对第四种情况
公共无效show4(ArrayList?超级塔尔){
arr.add(t);
}
好了,文章到这里就结束啦,如果本次分享的深入解析Java泛型及其通配符:应用场景与利弊分析和问题对您有所帮助,还望关注下本站哦!
【深入解析Java泛型及其通配符:应用场景与利弊分析】相关文章:
2.米颠拜石
3.王羲之临池学书
8.郑板桥轶事十则
用户评论
学习Java,总觉得泛型和泛型通配符这部分有点抽象, 这篇文章正好能解释一下实际应用
有12位网友表示赞同!
我觉得了解泛型就是为了写更安全、更可维护的代码,通配符也让代码更灵活
有20位网友表示赞同!
用 Java 来开发时遇到过很多类型错误,感觉泛型和通配符可以帮助解决这个问题!
有11位网友表示赞同!
刚接触Java的时候对泛型不太理解,现在看文章里这样详细的分析感觉醍醐灌顶了!
有14位网友表示赞同!
在团队项目中使用泛型和通配符能让代码更规范,其他人也更容易理解!
有16位网友表示赞同!
这篇文章写得很好,把泛型的优缺点都总结得很清楚了。
有19位网友表示赞同!
感觉学习泛型有点难度,希望可以多看一些例子来加深理解。
有19位网友表示赞同!
我一直在找一篇关于泛型和通配符的文章,正好今天看到了!
有18位网友表示赞同!
想学习 Java 高级知识,泛型一定要掌握啊,以后要好好跟进这方面的内容。
有14位网友表示赞同!
看来泛型和通配符在实际开发中还是非常有用的工具。
有8位网友表示赞同!
Java 的底层机制原来这么强大!
有6位网友表示赞同!
学习完这个文章感觉对 Java 编程有了更深入的理解...
有16位网友表示赞同!
以后写的代码一定要尽量使用泛型,可以避免很多类型错误 !
有15位网友表示赞同!
通配符的使用场景好像还是挺广泛的
有13位网友表示赞同!
感觉泛型的应用要根据实际情况选择,不能一味追求过度复杂化。
有7位网友表示赞同!
这篇文章很好的总结了泛型的优缺点,非常实用!
有12位网友表示赞同!
以后在写 Java 代码的时候,一定要注意使用泛型和通配符优化代码效率。
有12位网友表示赞同!
希望作者可以分享更多关于泛型和通配符的案例!
有6位网友表示赞同!