Java泛型

泛型

泛型——参数化类型:

方法或接口或类型,其定义中包含未知类型的参数/局部变量/返回值/字段。

其中的未知类型用写成大写字母的类型参数表示,一般有一个泛型参数就写T,两个就写T,U。

实例化时,需要用类型变量指定泛型参数。

一、泛型定义

泛型类

修饰符 class 类名<泛型参数列表>{

​ 类定义字段(其中一定有部分类型被泛型参数替代)

}

如:

public class ClassName<T>{
	private T data;
	public T getData() {
		return data;
	} 
    public void setData(T data) {
		this.data = data;
	}
}
泛型接口

修饰符 interface 接口名<泛型参数列表>{

​ 接口定义字段(其中一定有部分类型被泛型参数替代)

}

泛型方法

修饰符 <泛型参数列表> 返回类型 方法名(…){

​ …

}

如:

class ArrayAlg{
	public static <T> T getMiddle(T... a){
        return a[a.length/2];
    }
}
note:泛型可以嵌套、继承、实现…

二、类型变量的限定

背景:若一个代码可供多种类型使用,那么很有可能是这多种类型都实现了同样的方法,在这份代码中调用了这个共同的方法。显然,没实现这个方法的类型是不能使用这个泛型代码的

限定格式:<类型参数 extends 类/接口>,多个限定用 & 连接。

​ 每个类型参数可以有多个接口超类型,但只能最多有一个超类。如果有一个类作为限定,一定要放在第一个

三、使用泛型——指定具体类型

省略:

所有能推断出具体类型的地方可以省略< >里的内容或者连尖括号都可以省略;

有时省略会引起歧义,则编译器会报错,此时不能省略。

使用泛型类
  1. new一个泛型类实例:

    ClassName c = new ClassName<>(…);

  2. 定义一个普通方法时用泛型类的具体实现作为返回类型:

    返回类型的位置写:ClassName

  3. 继承、组合等同2。

使用泛型接口
  1. 实现泛型接口时可以类似使用泛型类。
  2. 也可以不指定具体类型。(相当于普通类中定义了泛型方法,再使用该方法时再指定具体类型)
调用泛型方法
// 此处可以省略<String>,通过传入的参数可以推断出String类型
String middle = ArrayAlg.<String>getMiddle("Mark", "Ben", "Alice"); 

// 此处省略<>里的类型,会报错
double middle = ArrayAlg.getMiddle(3.14, 1000, 0); // Error
// 报错原因:编译器将参数自动装箱为1个Double和2个Integer对象,因它们类型不同所以寻找它们共同的超类型。他们共同的超类型有2个:Number和Comparable接口。不止1个,则报错。
是编译器而不是JVM处理泛型:
  1. 泛型被定义后,编译器加载泛型定义时,将类型变量擦除,并替换成第一个类型限定(若无则为Object),生成一个原始类型,加载的是这个原始类型,而非泛型:

    这一步仅取决于泛型变量列表;

  2. 使用泛型时,要么明着给类型参数赋予了类型变量,要么省略了编译器可推断出的类型,编译器要根据实际的类型增加必要的强制类型转换语句:

    擦除并替换后的类型限定or Object->实际使用赋予的类型,下转。

    (加上这些语句的作用是:编译器可以进行类型检查)

  3. 若泛型被继承,且子类覆写了泛型中参数类型是类型变量的方法,则类型擦除会与多态发生冲突,编译器的解决方法是在子类中生成桥方法。桥方法中含有强制类型转换。

    了解类型擦除的意义——理解泛型的使用限制。
四、类型通配符

类型通配符是使用?代替方法具体的类型实参。
1. <? extends Parent> 指定了泛型类型的上界
2. <? super Child> 指定了泛型类型的下界
3. <?> 指定了没有限制的泛型类型

如:

// 假定定义了泛型类Plate盘子,定义了水果接口Fruit,定义了实现Fruit接口的类Apple
Plate<Apple> p1 = new Plate<Apple>;	 // 没问题
Plate<Fruit> p2 = new Plate<Apple>;  // 有问题,原因:Fruit和Apple有父子关系,但Plate<Fruit>和Plate<Apple>没有
Plate<? extends Fruit> p3 = new Plate<Apple>;  //没问题 
note:类型限定是定义泛型时使用,通配符是使用泛型时使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值