class 和超级 class 数组的有界通配符
Bounded wildcards for class and super class array
我有一个 class Shape
和一个 class Circle
扩展 Shape
如下:
public class Shape {
private double area;
public Shape(double thatArea) {
this.area = thatArea;
}
public double getArea() {
return this.area;
}
}
public class Circle extends Shape {
private double radius;
public Circle(double radius) {
super(3.14*radius*radius);
}
public double getRadius() {
return this.radius;
}
}
假设我创建一个形状数组如下
Shape[] shapes = new Shape[3];
shapes[0] = new Shape(100.0);
shapes[1] = new Circle(5.0);
shapes[2] = new Shape(35.0);
并且有一个像这样的按区域过滤的方法
public Shape[] filterByMaxArea(double maxArea) {
ArrayList<Shape> shapeResult = new ArrayList<>();
for (Shape s : shapes) {
if (s.getArea < maxArea) shapeResult.add(s);
}
return (Shape[]) shapeResult.toArray();
}
如果我这样调用 filterByMaxArea()
方法
filterByMaxArea(1000); // in order to include the
circle too
然后编译器抛出一个ClassCastException
Exception in thread "main" java.lang.ClassCastException: java.base/[Ljava.lang.Object; cannot be cast to [Lmypackage.Shape;
at mypackage.Main.filterByMaxArea(Main.java:74)
代码中第74行是这样的
return (Shape[]) shapeResult.toArray();
有人可以解释为什么即使 Circle 是 Shape 的子类型并且之前我有一个 Shape 和 Circle 实例数组,转换仍然失败吗?
P.S 我也试过用有界通配符声明 ArrayList,但没有成功。
ArrayList<? extends Shape> shapeResult = new ArrayList<>();
toArray()
returns Object[]
,有一个重载版本的 toArray(T[] a)
会给出想要的结果,像
一样使用它
return shapeResult.toArray(new Shape[shapeResult.size()]);
toArray()
被重载为 return 集合中声明的泛型类型的数组:
T[] List.toArray(T[] a)
但实际上你不需要那个。
您可以使用 Stream.toArray(IntFunction)
从 List
.
创建一个 Shape
的数组
使用实际代码你可以做到:
return shapeResult.stream().toArray(Shape[]::new);
比 :
更优雅
return shapeResult.toArray(new Shape[shapeResult.size()]);
或者通过使用全流方法,整个方法可以写成:
public Shape[] filterByMaxArea(double maxArea) {
return Arrays.stream(shapes)
.filter(s -> s.getArea() < maxArea)
.toArray(Shape[]::new);
}
针对您的问题:
让我们看两个数组示例:
有效:
Object[] array = new MyObject[2];
MyObject[] myarrau = (MyObject[])os; //ok, since array is of type MyObject[]
这不会(与您的情况一样 java.lang.ClassCastException)
Object[] array = new Object[2];
MyObject[] myarrau = (MyObject[])os; //ClassCastException here since array is not type of MyObject[]
以及 ArrayList
class 的 toArray
代码片段:
public Object[] toArray() {
Object[] r = new Object[size()];
return r;
}
如您所见,返回的数组是 Object[]
类型,如上面的第二个示例。
我有一个 class Shape
和一个 class Circle
扩展 Shape
如下:
public class Shape {
private double area;
public Shape(double thatArea) {
this.area = thatArea;
}
public double getArea() {
return this.area;
}
}
public class Circle extends Shape {
private double radius;
public Circle(double radius) {
super(3.14*radius*radius);
}
public double getRadius() {
return this.radius;
}
}
假设我创建一个形状数组如下
Shape[] shapes = new Shape[3];
shapes[0] = new Shape(100.0);
shapes[1] = new Circle(5.0);
shapes[2] = new Shape(35.0);
并且有一个像这样的按区域过滤的方法
public Shape[] filterByMaxArea(double maxArea) {
ArrayList<Shape> shapeResult = new ArrayList<>();
for (Shape s : shapes) {
if (s.getArea < maxArea) shapeResult.add(s);
}
return (Shape[]) shapeResult.toArray();
}
如果我这样调用 filterByMaxArea()
方法
filterByMaxArea(1000); // in order to include the
circle too
然后编译器抛出一个ClassCastException
Exception in thread "main" java.lang.ClassCastException: java.base/[Ljava.lang.Object; cannot be cast to [Lmypackage.Shape;
at mypackage.Main.filterByMaxArea(Main.java:74)
代码中第74行是这样的
return (Shape[]) shapeResult.toArray();
有人可以解释为什么即使 Circle 是 Shape 的子类型并且之前我有一个 Shape 和 Circle 实例数组,转换仍然失败吗?
P.S 我也试过用有界通配符声明 ArrayList,但没有成功。
ArrayList<? extends Shape> shapeResult = new ArrayList<>();
toArray()
returns Object[]
,有一个重载版本的 toArray(T[] a)
会给出想要的结果,像
return shapeResult.toArray(new Shape[shapeResult.size()]);
toArray()
被重载为 return 集合中声明的泛型类型的数组:
T[] List.toArray(T[] a)
但实际上你不需要那个。
您可以使用 Stream.toArray(IntFunction)
从 List
.
Shape
的数组
使用实际代码你可以做到:
return shapeResult.stream().toArray(Shape[]::new);
比 :
更优雅return shapeResult.toArray(new Shape[shapeResult.size()]);
或者通过使用全流方法,整个方法可以写成:
public Shape[] filterByMaxArea(double maxArea) {
return Arrays.stream(shapes)
.filter(s -> s.getArea() < maxArea)
.toArray(Shape[]::new);
}
针对您的问题:
让我们看两个数组示例:
有效:
Object[] array = new MyObject[2];
MyObject[] myarrau = (MyObject[])os; //ok, since array is of type MyObject[]
这不会(与您的情况一样 java.lang.ClassCastException)
Object[] array = new Object[2];
MyObject[] myarrau = (MyObject[])os; //ClassCastException here since array is not type of MyObject[]
以及 ArrayList
class 的 toArray
代码片段:
public Object[] toArray() {
Object[] r = new Object[size()];
return r;
}
如您所见,返回的数组是 Object[]
类型,如上面的第二个示例。