深入理解JAVA 泛型通配符
深入理解JAVA 泛型通配符(extends,super)
先解释为什么会用通配符 (非要用通配符不可么?)
class Fruit{}
class Apple extends Fruit{}
class Jonathan extends Apple{};
class Orange extends Fruit{};
public class ConvariantArrays {
public static void main(String [] argv){
Fruit[] fruits = new Apple[10];
fruits[0]= new Apple();
fruits[1]= new Jonathan();
try{
fruits[0] = new Fruit(); //此处会出现异常 向上类型转换异常
}catch (Exception ex){
ex.printStackTrace();
}
try{
fruits[0] = new Orange();
}catch (Exception ex){
ex.printStackTrace();
}
}
}
这种异常出现 会出现在运行期间,通过通配符做标记 可以将这种异常在编译期间就处理完成。
由此可见:通配符不是必须使用的 而是为何方便处理代码而提出的一种纠错机制
在Java中,?代表通配符
通配符的使用方法
1. 在实例化对象的时候, 不确定泛型参数,可以使用通配符进行定义
2. <? extends Object > 代表上边界限定通配符
3.<? super Object > 代表下边界限定通配符
上边界限定通配符 <? extends Object >
上边界通配符直接只用add()方法受限,但可以用来获取各种数据类型的数据,并赋值非父类的引用
List<? extends Number > list = null;
lits = new ArrayLiat<Integer>();
list.add(new integer(1));//error 因为不能确定实例化的对象具体类型到时add方法受限
...
list.get();//可以正常使用
下边界限定通配符<? super Object >
下边界通配符使用get()方法受限制(不使用强转),但是可以添加特定类型的值,用于对象写入到一个数据结构里面
List<? super Integet> list = null;
list = new ArrayList<Number>();
list.add();// OK
Number number = list.get(0); //报错 因为List<? super Integer>不知道list存放的对象类型,则使用get获得的值不知晓
package ConvariantArrays;
import java.util.ArrayList;
import java.util.List;
public class NonCovariantGenerics {
List<Fruit> flsit = new ArrayList<Apple>(); //error 无法实现向上类型的转换
}
写
package ConvariantArrays;
import java.util.ArrayList;
import java.util.List;
public class GenericWriting {
static <T> void writExact(List<T> list, T item){ //精确写入
list.add(item);
list.add(item);
}
static List<Apple> apples = new ArrayList<Apple>();
static List<Fruit> fruit = new ArrayList<Fruit>();
static void f1(){
writExact(apples, new Apple());
writExact(fruit, new Apple());
}
static <T> void writeWithWildcard(List<? super T> list, T item){ //泛型写入
list.add(item);
}
static void f2(){
writeWithWildcard(apples, new Apple());
writeWithWildcard(fruit, new Apple());
}
public static void main(String[] args){
f1();
f2();
}
}
读
package ConvariantArrays;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class GenericReading {
static <T> T ReadExact(List<T> list){//精确读出
return list.get(0);
}
static List<Apple> apples = Arrays.asList(new Apple());
static List<Fruit> fruit = Arrays.asList(new Fruit());
static void f1(){
System.out.println(ReadExact(apples).toString());
System.out.println(ReadExact(fruit).toString());
}
static class Reader<T>{ //封装内部类 进行读出
T ReadExact(List<T> list){
return list.get(0);
}
}
static void f2(){
Reader<Fruit> fruitReader = new Reader<Fruit>();
Fruit f = fruitReader.ReadExact(fruit);
System.out.println(f.toString());
}
static class ConvariantReadar<T>{
T readConvariant(List<? extends T> list){//内部类泛型读出
return list.get(0);
}
}
static void f3(){
ConvariantReadar<Fruit> fruitReader = new ConvariantReadar<Fruit>();
System.out.println(fruitReader.readConvariant(fruit).toString());
System.out.println(fruitReader.readConvariant(apples).toString());
}
public static void main(String [] args){
f1();
f2();
f3();
}
}