VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > 编程开发 > Java教程 >
  • 学习笔记:Java泛型

一、 为什么要使用泛型?
Java核心技术卷中写到:“使用泛型机制编写的程序代码要比那些杂乱的使用Object变量,然后在进行强制类型转换的代码具有更好的安全性和可读性。泛型(Generic)意味着编写的代码可以被很多的不同类型的对象重用”。
比如未使用泛型的ArrayList集合,只是维护一个Object类型数组。在实现中没有类型推断,只能在运行时检测错误,在获取值时必须进行强制类型转换,可能会出现ClassCastExcepyion异常。


 
@Test
 
public void test2(){
 
ArrayList a = new ArrayList();
 
a.add(132);
 
a.add(456);//没有进行类型检查,可以添加任意Object对象
 
a.add("Hello");
 
 
 
for (Object o :a) {
 
String str = (String) o;//进行强制类型转换,编译时不会报错,运行时会出现java.lang.ClassCastException异常
 
System.out.println(str);
 
}

Java SE 5.0增加了泛型机制,使用泛型的Arrsylist类,有一个类型参数来指示元素的类型。


 
@Test
 
public void test1(){
 
Collection<Integer> c = new ArrayList<Integer>();//类型推断
 
c.add(12);
 
c.add(22);//能在编译时而不是在运行时检测错误
 
c.add(52);
 
//c.add("good"); 只能添加Integer类的对象
 
 
 
for (Integer o :c) { //不用进行强制类型转换,编译器已经知道o的数据类型,且运行时不会报错
 
System.out.println(o);
 
}
 
}

二、 定义泛型类 “一个泛型类就是具有一个或多个类型变量的类”。如何实现?引入一个或多个类型变量,用< >括起来,并放在类名的后面。 作用是什么?类定义的类形变量可以指定类的内部结构的数据类型(比如属性的数据类型,方法的返回类型,方法的形参类型,成员变量的数据类型)。


 
//开发一个泛型Apple类,要求有一个重量属性weight在测试类中实例化不同的泛型对象,
 
public class Apple<T> {
 
private T weight;//指定属性的数据类型
 
public void setWeight(T weight){//指定方法的形参类型
 
this.weight = weight;
 
}
 
public T getWeight(){//指定方法的返回值类型
 
return weight;
 
}
 
//泛型类定义构造器方式和一般类一样
 
public Apple(){
 
}
 
//泛型类定义构造器方式和一般类一样
 
public Apple(T weight){
 
this.weight = weight;
 
}
 
}

“用具体的类型替换类型变量就可以实例化泛型类型。”不能用基本数据类型指定类型变量,而要用其对应的包装类。


 
@Test
 
public void test1(){
 
Apple<String> a1 = new Apple<>("500克");
 
Apple<Integer> a2 = new Apple<>(500);
 
Apple<Double> a3 = new Apple<>(500.0);
 
System.out.println(a1.getWeight());//返回值类型是String类型
 
System.out.println(a2.getWeight());//返回值类型是Integer类型
 
System.out.println(a3.getWeight());//返回值类型是Double类型
 
}
 
}

三、 怎么定义泛型方法 什么是泛型方法?“带有类型参数的方法”。泛型方法可以定义在普通类中,也可以定义在泛型类中。 类型变量放在权限修饰符的后面,返回值类型的前面。


 
public class Arrayex {
 
public static <E> void toArray(E[] e, Collection<E> c){//类型变量修饰形参
 
for (E ex: e){//类型变量修饰局部变量
 
c.add(ex);
 
}
 
}
 
}

可以看出,泛型方法定义的类型变量可以定义方法的内部结构(形参,局部变量)以及方法的返回值类型。 调用泛型方法?“调用时,在方法名的尖括号中放入具体的类型,也可以省略,编译器有足够的信息推断出所调用的方法。


 
@Test
 
public void test2(){
 
Collection<String> c1 = new ArrayList<>();
 
String[] str1 = new String[]{"C","Python","Java","C++"};
 
Arrayex.<String>toArray(str1,c1);//输入第一个参数后,编译器会类型推断,指定第二个参数为容纳String类型的Collection集合
 
System.out.println(c1);
 
}
 
}

显然,在泛型类和泛型方法的定义和调用过程中,可以体验到类型变量在类或方法的定义中充当的Object类型,当调用时指定具体传入数据类型,帮助编译器检查传入数据类型、类型推断的作用。

四、类型变量的限定 “在类或方法中有时需要对类型变量加以约束”。对比Object类等类型指定的类或方法的结构,通常继承的子类也能满足代码内部的使用。 “对于类型变量,可以指定为任何一个类的对象,假如内部调用了对象所属类的compareTo方法,怎么才能确信T对象所属类有CompareTo方法呢?解决方案是将T限定为实现了Comparable接口。 <T extends Compareable> 表示T是其实现了Comparable接口或者是绑定类型的子类型。一个类型变量可以有多个限定。限定类型用“&”分隔,用逗号来分隔类型变量。 <T super xxxClass> 表示类型变量指定的范围为xxxClass及其父类。


 
//返回数組元素最大值
 
public static <E extends Emploee & Comparable> E max(E[] e){
 
if (e == null || e.length == 0) return null;
 
E maxplayer = e[0];
 
for (int i = 1; i < e.length; i++) {
 
if (maxplayer.compareTo(e[i])<0){
 
maxplayer = e[i];
 
}
 
}
 
return maxplayer;
 
}

在此方法中,类型变量限定为实现Comparable接口并且是Employee及其子类。 创建Person类、Employee类、Mannager类,三个类是多层继承关系,Person重写了compareTo方法对salary属性。


 
@Test
 
public void test1(){
 
Emploee[] emploees = new Emploee[5];
 
emploees[0] = new Emploee("1号员工",12,100);
 
emploees[1] = new Emploee("2号员工",13,110);
 
emploees[2] = new Emploee("3号员工",13,120);
 
emploees[3] = new Manager("1号管理",12,100,50);
 
emploees[4] = new Manager("2号管理",14,130,50);
 
 
 
Object o = Emploee.max(emploees);//返回工资最高的人
 
System.out.println(o);//名字 2号管理工资是 130
 
}
 
}

五、泛型变量与擦除 “无论何时定义一个泛型类,都自动提供一个相应的原始类型,类名就是删除类型参数后的泛型类名”。 擦除类型变量,原始类型会替换为第一个限定类型,如果没有给定就用Object类型来替换。 “当程序调用泛型方法时,如果擦除返回类型,编译器会插入强制类型转换。” 在虚拟机中没有泛型,只有普通的类和方法。所有的类型参数都用它们的限定类型替换。桥方法被合成来保持多态(方法类型变量擦除时,调用来自父类的方法可能会变成另外一个父类方法,不在同名同参数产生重载,与多态冲突)。

六、泛型的约束与局限性 运行时类型查询只适用于原始类型。 使用instanceOf或涉及泛型类型的强制类型转换表达式都会看到一个编译器警告。 不能实例化泛型类参数化类型的数组。 不能实例化泛型类的类型变量。 在静态属性或者静态方法中不能使用泛型类的类型变量。 不能抛出或捕获泛型类的实例。

 

原文:https://www.cnblogs.com/echoxiatiandefeng/p/14477323.html

 


相关教程