Java基础知识每日总结(12)---Java泛型程序设计

泛型程序设计

1.简介
泛型常用于集合,它是一种把类型明确的工作推迟到创建对象时或调用方法时才去明确的特殊的类型。它对集合的作用与声明数组时指定数组内元素数据类型一样,它指定声明集合时集合对象内可以存放的元素的数据类型,且指定的数据类型必须是引用类型。
在Java SE7及以后的版本中,构造函数中可以省略泛型的类型,省略的类型可以从变量的类型推断得出。例,ArrayList<String> files=new ArrayList<String>();–> ArrayList<String> files=new ArrayList<>();,指定files集合内只能存放String类型的变量。
泛型提供了类型参数,这使得程序具有更好的可读性和安全性。

2.简单泛型类
一个泛型类就是具有一个或多个类型变量的类,且类型变量必须是引用类型。例,

public calss People<T,U,Z,...>{
...
}

类定义中的类型变量指定了类中方法的返回类型以及域和局部变量的类型。
类型变量使用大写形式,且较短。在Java的库中,使用变量E表示集合的元素类型,K和V分别表示表的关键字与值的类型,T表示“任意类型”。
用具体的类型替换类型变量就可以实例化泛型类型。例,People<String>
List类和ArrayList类就是泛型类。例,

List<String> l=new ArrayList<String>();
l.add("haha");
l.add(3);   //报错,只能放String
List<Integer> l2=new ArrayList<Integer>();
l2.add(3);
l2.add("haha");   //报错,只能放Integer类型变量

3.泛型方法
可以在普通类中定义一个带有类型参数的简单方法。例,

Class People{
  public static <T> 返回值类型 getNO(T...a){
    return ...;
    }
}

Class People<T>{
  public static 返回值类型 getNO(T...a){
    return ...;
    }
}

此时,类型变量放在修饰符的后面,返回类型的前面。泛型的方法可以定义在普通的类中也可以定义在泛型类中。当调用一个泛型的方法时,在方法名前的尖括号中放入具体的类型。

4.泛型接口
泛型接口和它的实现类:

public interface ListTest<T> {
	public void test(T t);
}

class StrImpl implements ListTest<String> {   //不常见

	@Override
	public void test(String t) {
		// TODO Auto-generated method stub

	}
}

class StrImpl<T> implements ListTest<T> {   //常见

	@Override
	public void test(T t) {
		// TODO Auto-generated method stub

	}
}

5.泛型代码和虚拟机
①类型擦除
当定义一个泛型类型时,会自动提供一个相应的原始类型。原始类型的名字就是删去类型参数后的泛型类型名。擦除类型变量,并替换为限定类型(无限定的变量用Object)。
②翻译泛型表达式
当程序调用泛型方法时,如果擦除返回类型,编译器会插入强制类型转换。当存取一个泛型域时也会插入强制类型转换。
③翻译泛型方法
类型擦除也会出现在泛型方法中。Java泛型转换要点:

  • 虚拟机中没有泛型,只有普通的类和方法
  • 所有的类型参数都用它们的限定类型替换
  • 桥方法被合成来保持多态
  • 为保持类型安全性,必要时插入强制类型转换

6.约束和局限性
①不能用基本类型实例化类型参数
People<int>是错误的,原因是类型擦除。int不是一个类,类型擦除后,People类含有Object类型的域,而Object不能存储int值。
②运行时类型查询只适用于原始类型
当试图查询一个对象是否属于某个泛型类型时,倘若使用instanceof会得到一个编译器错误,如果使用强制类型转换会得到一个警告。同样,getClass方法总是返回原始类型。
③不能创建参数化类型的数组
Java不支持泛型类型的数组,但是可以声明类型为像People<String>[]的变量。
④不能实例化类型变量
⑤泛型类的静态上下文中类型变量无效
不能在静态域或方法中引用类型变量。
⑥不能抛出或捕获泛型类的实例
既不能抛出也不能捕获泛型类对象。

7.泛型类型的继承规则
无论S和T有什么联系,通常,People<S>People<T>没有什么联系。

8.通配符类型
通配符类型中允许类型参数变化。例,Pair<? extends E> 表示任何泛型Pair类型(向下限定,上限),它的类型参数是E及它的子类,如Pair<? extends People> p = new Pair<Student>();,这可以用在方法的参数中。
通配符还有一种超类型限定:Pair<? super E>表示任何泛型Pair类型(向上限定,下限),它的类型参数是E及它的父类,如Pair<? super People> p = new Pair<Object>();,它可以为方法提供参数,但并不提供返回值。
带有超类型限定的通配符可以向泛型对象写入,带有子类型限定的通配符可以从泛型对象读取。
还有一种无限定通配符,例Pair<?>
通配符不是类型变量,因此不能在编写代码中使用“?”作为一种类型。

9.要点

当定义泛型变量时,前后必须一致,否则要用通配符

List<String> l=new ArrayList<String>();
List<Object> l2=new ArrayList<String>();   //报错,前后不一致
List<?> l3=new ArrayList<String>();
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值