手机网站制作视频教程,长宁区网站建设网站制作,网站建设开发方式包括购买,建筑模板是干什么用的参考链接#xff1a; Java中具有泛型的有界类型
1、什么是泛型 泛型#xff0c;即“参数化类型”。一提到参数#xff0c;最熟悉的就是定义方法时有形参#xff0c;然后调用此方法时传递实参。那么参数化类型怎么理解呢#xff1f;顾名思义#xff0c;就是将类型由原来…参考链接 Java中具有泛型的有界类型
1、什么是泛型 泛型即“参数化类型”。一提到参数最熟悉的就是定义方法时有形参然后调用此方法时传递实参。那么参数化类型怎么理解呢顾名思义就是将类型由原来的具体的类型参数化类似于方法中的变量参数此时类型也定义成参数形式可以称之为类型形参然后在使用/调用时传入具体的类型类型实参。
2、一个小例子 import java.util.ArrayList;
import java.util.List; public static void main(String[] args) { List list new ArrayList(); list.add(hello); list.add(hallo); list.add(1); for (int i 0; i list.size(); i) { String str (String) list.get(i); System.out.println(str); } }
}
上面的程序 编译阶段正常而运行时会出现异常
Exception in thread main java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
存在的问题 当把一个对象收入集合中集合不会记住此对象的类型当再次从集合中取出此对象时对象变成了Object类型但其运行时类型任然为其本身类型。强制转换时容易出现异常正如程序中把Integer转为String失败。
解决方法 通过使用泛型来使集合能够记住集合内元素各类型
将上面的代码用泛型来实现
import java.util.ArrayList;
import java.util.List; public class Main { public static void main(String[] args) { ListString list new ArrayListString(); list.add(hello); list.add(hallo); list.add(1); for (int i 0; i list.size(); i) { String str list.get(i); System.out.println(str); } }
}
这时编译错误无法运行
Error:(13, 13) java: 对于add(int), 找不到合适的方法 方法 java.util.Collection.add(java.lang.String)不适用 (参数不匹配; int无法转换为java.lang.String) 方法 java.util.List.add(java.lang.String)不适用 (参数不匹配; int无法转换为java.lang.String)
通过List直接限定了list集合中只能含有String类型的元素从而在取得集合中的元素时无须进行强制类型转换编译器可以确定集合中存的都是String类型。
3、泛型的特性 Java中的泛型只在编译阶段有效。
在编译过程中正确检验泛型结果后会将泛型的相关信息擦出并且在对象进入和离开方法的边界处添加类型检查和类型转换的方法。
泛型信息不会进入到运行时阶段。
4、泛型的使用 在泛型使用过程中操作的数据类型被指定为一个参数这种参数类型可以用在类、接口和方法中分别被称为泛型类、泛型接口、泛型方法。
以几个小例子来分析一下
(1) 泛型类
public class ArrayListE
extends AbstractListE
implements ListE, RandomAccess, Cloneable, Serializable
用泛型类声明与建立对象
ArrayListString list new ArrayListString();
JDK7之后可以写成
ArrayListString list new ArrayList();
(2) 泛型接口
...
public interface ComparatorT{ int compare(T o1, T o2); ...
}
使用方法
public class StringComparator implements ComparatorString{ Override public int compare(String s1, String s2){ return -s1.compareTo(s2); }
}
(3) 泛型方法
public static T T elemof(T[] objs,int index){ return objs[index];
}
使用方法
public static String elemof(String[] objs,int index){ return objs[index];
}
5、泛型的上下边界问题 可以使用extends与super关键字、?类型通配符来限制泛型并且可以结合这三者来模拟共变性与逆变性。
共变性与逆变性
如果B是A的子类而Node B 可视为一种Node A 则称Node具有共变性(Covariance)或者有弹性的(Flexible)。
如果B是A的子类而Node A 可视为一种Node B 则称Node具有逆变性(Contravariance)。
Java泛型不支持共变性与逆变性
(1) 使用?与extends来模拟共变性
class Fruit{}
class Apple extends Fruit{}
class RedApple extends Apple{} List ? extends Fruit list1 new ArrayListFruit();
List ? extends Fruit list2 new ArrayListApple();
List ? extends Fruit list3 new ArrayListRedApple();
Fruit为上界即List ? extends Fruit 类型的对象可以引用持有Fruit及其子类的容器。
关于一个add方法
void add(List ? extends Fruit list, Apple a){ list.add(a);
}
如果list引用的是持有RedApple类型的容器那么将Apple类型向下转型是不安全的所以用List ? extends Fruit add方法是受到限制的即无法向容器中添加任何实际的类型除了null。
(2) 使用?与super来模拟逆变性
List ? super RedApple list4 new ArrayListRedApple();
List ? super RedApple list5 new ArrayListApple();
RedApple为下界即List ? super RedApple 类型的对象可以引用持有RedApple及其父类的容器。
此时add方法是没有限制的但是也只能是添加Jonathan及其父类型。若事先不知道List ? super RedApple 引用的对象所持有的类型则可以做到向上转型而向上转型是安全的。
6、小结 泛型的本质是参数化类型
只在编译阶段有效泛型使用无错误时擦出泛型的相关信息并且在对象进入和离开方法的边界处添加类型检查和类型转换的方法泛型信息不会进入到运行时阶段。
泛型可以被用在类、接口和方法中而且可以限制泛型的上下界。
虽然Java泛型不支持共变性与逆变性但是?与extends可模拟共变性;?与super可模拟逆变性。 参考资料
《Java学习笔记》 林信良
Java泛型的边界问题
java 泛型详解-绝对是对泛型方法讲解最详细的没有之一