《Java核心技术》第八章读书笔记(泛型)

第八章 泛型程序设计

泛型方法

class ArrayAlg{
	public static <T> T getMiddle(T... a){
		return a[a.length / 2]
	}
}

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

String middle = ArrayAlg.<String>getMiddle("J","k","L")

类型变量的限定

public static <T extends Comparable> T func(T[] a){...}

这个泛型方法规定了 T 必须实现 Comparable (Comparable本身也是一个泛型类型)接口。此方法只能被实现了Comparable接口的类(如String,localDate)的数组调用。否则会编译报错。

一个类型变量或通配符可以有多个限定

T extends Comparable & Serializable

翻译泛型方法

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

约束与局限性

  • 不能有基本类型实例化类型参数

    没有Pair<double>,只有Pair<Double>
    
  • 运行时类型查询只适用于原始类型

    if (a instanceof Pair<String>)  // Error
    Pair<String> p = (Pair<String>) a // Warning ---can only test that a is a Pair
    
    同样的道理,getClass总是返回原始类型
    Pair<String> stringPair = .....
    Pair<Employee> employeePair = ...
    if (StringPair.getClass()==employeePair.getClass()) 
    结果为true,因为两次调用getClass豆浆返回Pair.class
    
  • 不能创建参数化类型的数组

    因为对于泛型类型,擦除会使类型参数无效。能够通过数组存储检查,但是会导致一个类型错误。

    Pair<String> table = new Pair<String>[10] // Error
    
  • 不能实例化类型变量

    public Pair() {
    	first = new T();
    	second = new T();
    }  // error
    

    类型擦除会将T改变成Object,而且本意不希望调用new Object。

  • 不能构造泛型数组

    public static <T extends Comparable> T[] minmax(T[] a){T[] mm = new T[2]}
    // Error
    当类型擦除时,Object[]引用赋给Comparable[]时,会发生ClassCastException
    
  • 泛型类的静态上下文中类型变量无效

    public class Singleton<T>{
    	private static T singleInstance // Error
    	public static T getSingleInstance // error
    	{
    		if (singleInstance == null) {
    			return singleInstance
    		}
    	}
    }
    

    类型擦除后,只有一个Singleton类,只包含一个singleInstance域,因此禁止使用带有类型变量的静态域和方法。

  • 不能抛出或捕获泛型类的实例

    public class Problem<T> extends Exception {}  // Error
    catch中不能使用类型变量。
    

通配符类型

如果要编写一个答应雇员的方法:

public static void printBuddies(Pair<Employee> p){}
由于Pair<Employee>和Pair<Manager>没有什么联系,所以并不能将Pair<manager>传递
使用通配符类型
public static void printBuddies(Pair<? extends Employee> p){}
  • 无限定通配符

    Pair<?> 和 Pair有很大不同
    Pair<?>有?get 和 void set方法
    get方法返回值只能赋值给一个Object,set方法不能被调用。
    两者本质区别是Pair<?> 可以用任意Object对象调用原始Pair类的setObject方法
    
posted @ 2020-11-01 13:58  Jimmyhe  阅读(108)  评论(0编辑  收藏  举报