标签:父类 its 是什么 类型 编译 ora 错误 运行 类重写
如果Sub是Par的一个子类型(子类或子接口),而G是具有泛型声明的类或接口,G并不是G
的子类型!
在早期的Java中,允许Integer[]数组赋值给Number[]变量存在着缺陷:
Integer[] integers = new Integer[5];
Number[] numbers = integers;
//下面程序会报异常java.lang.ArrayStoreException: java.lang.Double
//因为0.5不是Integer
numbers[0] = 0.5;
因此,Java在泛型设计时进行了改进,它不再允许把List
List<Integer> list = new ArrayList<>();
//编译错误
List<Number> list1 = list; //这俩也不是父类子类的关系
Java泛型的设计原则是:只要代码在编译时没有出现警告,就不会遇到运行时的ClassCastException异常。
为了表示各种泛型List的父类,可以使用类型通配符,类型通配符是一个问号(?),将一个问号作为类型实参传给List集合,写作:List<?>(意思是元素类型未知的List),问号可以匹配任何类型。
public void test(List<?> list){
for (int i = 0;i<list.size();i++){
System.out.println(list.get(i));
}
}
现在,使用任何类型的List来调用这个方法,程序依然可以访问集合c中的元素,其类型是Object,这永远是安全的,因为不管List的真实类型是什么,它包含的都是Object。
但这种带通配符的List仅表示他是各种泛型的父类,并不能把元素加入到其中:
List<?> list = new ArrayList<>();
//编译错误
list.add(new Object());
因为程序无法确定list集合中元素的类型,所以不能向其中添加对象。
写一个抽象类Shape:
public abstract class Shape {
public abstract void draw();
}
写一个子类Circle:
class Circle extends Shape{
@Override
public void draw() {
System.out.println("?");
}
}
写一个子类Rectangle:
class Rectangle extends Shape{
@Override
public void draw() {
System.out.println("??");
}
}
写一个测试类Canvas:
class Canvas{
public void drawAll(List<Shape> shapes){
for(Shape s:shapes){
s.draw();
}
}
public static void main(String[] args) {
List<Circle> circleList = new ArrayList<>();
Canvas canvas = new Canvas();
//因为List<Shape>不是List<Circle>的父类,下面程序编译错误
//canvas.drawAll(circleList);
}
}
为了能够传入List
将Canvas测试类重写??:
class Canvas{
public void drawAll(List<?> shapes){
for(Object shape:shapes){
//增加了强转
Shape s = (Shape)shape;
s.draw();
}
}
public static void main(String[] args) {
List<Circle> circleList = new ArrayList<>();
Canvas canvas = new Canvas();
//编译不再报错
canvas.drawAll(circleList);
}
}
这样也是一种解决办法,但这种解决显得比较笨拙(因为还要强转)。
实际上需要一种泛型表示方法,它可以表示所有的Shape泛型List的父类。为了满足这种需求,Java泛型提供了被限制的类型通配符:
class Canvas{
//表示所有Shape泛型List的父类
public void drawAll(List<? extends Shape> shapes){
for(Shape s:shapes){
s.draw();
}
}
public static void main(String[] args) {
List<Circle> circleList = new ArrayList<>();
Canvas canvas = new Canvas();
canvas.drawAll(circleList);
}
}
这样就可以把List
此时Shape 是这个通配符?的上限(upper bound)
public class Orangle<T extends Number> {
T org;
public static void main(String[] args) {
Orangle<Integer> oi = new Orangle<>();
Orangle<Double> od = new Orangle<>();
//下列代码将引发编译异常,下面代码试图把String类型赋给T形参
//String不是Number的子类型
// Orangle<String> os = new Orangle<>(); //not within its bound
}
}
还有更狠的情况:程序为类型形参设定多个上限(至多一个父类上限,可以有多个接口上限),表明该类型形参必须是其父类的子类(是父类本身也行),并且实现多个上限接口。
//表明T类型必须是Number类或其子类,并必须实现java.io.Serializable和Comparable接口
public class Demo1 <T extends Number & Serializable & Comparable> {
}
标签:父类 its 是什么 类型 编译 ora 错误 运行 类重写
原文地址:https://www.cnblogs.com/woshi123/p/12512677.html