Java 泛型学习一 泛型概念
Java 泛型学习二 泛型的限制
Java 泛型学习三 通配符
Java 泛型学习四 自动擦除
Java 泛型学习五 泛型擦除带来的不自然
Java 泛型学习六 泛型类型系统
什么是泛型通配符
我们来看看泛型的类型变量的继承吧,按照常规的继承理解,下面代码应该是没问题的:
package net.oseye; import java.util.ArrayList; public class FanXing { public static void main(String[] args) { ArrayList<String> as=new ArrayList<String>(); ArrayList<Object> ao=null; ao=as; } }
因为任何类都继承自Object类,但却不能通过编译:
net\oseye\FanXing.java:9: 错误: 不兼容的类型 ao=as; ^ 需要: ArrayList<Object> 找到: ArrayList<String> 1 个错误
可以总结出若A是B的子类,则G<A>可以当做G<B>使用并不成立。
如果想要达到目的就要使用通配符“?”,通配符“?”代表任意具体类型,如上述代码改成:
package net.oseye; import java.util.ArrayList; public class FanXing { public static void main(String[] args) { ArrayList<String> as=new ArrayList<String>(); ArrayList<?> ao=null; ao=as; } }
就可以编译通过。
使用泛型通配符注意事项:
- 泛型通配符只能用于引用的声明中,不可以在创建对象时使用;
package net.oseye; public class FanXing { public static void main(String[] args) { Fruit<?> fruit=new Fruit<?>(); } } class Fruit<T>{ private T color; public void setColor(T color){ this.color=color; } public String getColor(){ return this.color.toString(); } }
net\oseye\FanXing.java:5: 错误: 意外的类型 Fruit<?> fruit=new Fruit<?>(); ^ 需要: 不带限制范围的类或接口 找到: ? 1 个错误
- 不可以使用采用了泛型通配符的引用调用使用了泛型参数的方法;
package net.oseye; public class FanXing { public static void main(String[] args) { Fruit<?> fruit=new Fruit<String>(); fruit.setColor("red"); } } class Fruit<T>{ private T color; public void setColor(T color){ this.color=color; } public String getColor(){ return this.color.toString(); } }
net\oseye\FanXing.java:6: 错误: 无法将类 Fruit<T>中的方法 setColor应用到给定类型 ; fruit.setColor("red"); ^ 需要: CAP#1 找到: String 原因: 无法通过方法调用转换将实际参数String转换为CAP#1 其中, T是类型变量: T扩展已在类 Fruit中声明的Object 其中, CAP#1是新类型变量: CAP#1从?的捕获扩展Object 1 个错误
- 通配符也可以限制的,语法:? extends 类名或接口名;
package net.oseye; public class FanXing { public static void main(String[] args) { Apple<String> appleStr=new Apple<String>(); appleStr.setColor("红色"); Apple<Integer> appleNum=new Apple<Integer>(); appleNum.setColor(1); SayColor(appleStr); SayColor(appleNum); } static void SayColor(Apple<? extends String> apple){ System.out.println(apple.getColor()); } } class Apple<T>{ private T color; public void setColor(T color){ this.color=color; } public T getColor(){ return this.color; } }
net\oseye\FanXing.java:12: 错误: 无法将类 FanXing中的方法 SayColor应用到给定类型 ; SayColor(appleNum); ^ 需要: Apple<? extends String> 找到: Apple<Integer> 原因: 无法通过方法调用转换将实际参数Apple<Integer>转换为Apple<? extends String > 1 个错误