Java泛型笔记
泛型参数是不型变的
List<String> list = new ArrayList<String>; list=new ArrayList<Object>; //编译失败
已知泛型上界
List<? extends Object> list=new ArrayList<Object>; list.add("1");//编译失败 list.add(new Object());//编译失败
? extends Object
说明 这个对象的上界是Object,但是你并不知道他实际的类型是什么- 假如你要读取,你可以把它当成Object来使用,因为这实际上是向上转型,是允许的。
假设这个对象的实际类型是String,则读取时操作是:Object o=string// string 的类型是String
- 假如你要写入,无论你把它当成什么类型,都是不允许的,因为你无法知道他的实际类型,所以任何类型进行写操作都是向下转型,这都是不允许的。
假设这个对象的实际类型是String,则写入时操作是:String string=(String)o// o的类型是Object
注意:这里很自然的就使用了向下转型,但是在通配符里,你根本无法知道你要向下转型成什么类型,所以你无法对一个已知上界的泛型进行写操作
- 假如你要读取,你可以把它当成Object来使用,因为这实际上是向上转型,是允许的。
已知泛型下界
List<? super String> list=new ArrayList<Object>; list.add("1");//成功 list.add(new Object());//成功
? super String
说明 这个对象的下界是String,但是你依然并不知道他实际的类型是什么- 假如你要读取,对不起,不允许,因为你不知道要向下转型成什么类型
假设这个对象的实际类型是Object,则读取时操作是:String string=(String)o// o的类型是Object
- 假如你要写入,你可以把它当成String来使用,因为这实际上是个向上转型
假设这个对象的实际类型是String,则写入时操作是:Object o=string// string的类型是String
注意:此处的o可使用任何String 的父类替代,但是如果方法返回的是T(泛型参数),依然还是会返回Object对象,而不会是实际的对象类型,因为编译器也不知道实际类型是什么,编译器只知道这个类型是String的父类而已
- 假如你要读取,对不起,不允许,因为你不知道要向下转型成什么类型
综上,已知上界的读取是允许的,已知下界的写入是允许的,已知上界和下界的话,就可以任意读取该泛型参数对象了。