在varargs中转换对象数组

时间:2016-08-07 20:16:40

标签: java

在关于interfaces的Oracle教程之后,我尝试了代码并添加了一个moveAll方法,该方法将所有矩形(作为varargs)移动到已解析的位置。

    public static void moveAll(int x, int y, Relatable... obj) {
    Rectangle[] rects = (Rectangle[])obj;
    for(Rectangle r: rects){
        r.move(x, y);
    }
}

public interface Relatable {
public static void moveAll( int x, int y, Relatable... obj) {}
}

编译后我得到:

Exception in thread "main" java.lang.ClassCastException: [Linterfaces.Relatable; cannot be cast to [Linterfaces.RectanglePlus;
at interfaces.RectanglePlus.moveAll(RectanglePlus.java:52)
at interfaces.Main.main(Main.java:9)

1 个答案:

答案 0 :(得分:1)

假设Rectangle类实现了Relatable接口并且Rectangle类具有move(int x,int y)方法,则会得到ClassCastException,因为即使Rectangle实现了Relatable,也不能将Relatable数组视为Rectangle数组。 Java数组是协变的,这意味着允许它做这样的事情:

Integer.MIN

不管B []不是A []的子类。 Relatable []和Rectangle []都直接从Object派生(与任何其他数组类型一样),因此它们之间没有父子关系。

就您的示例而言,以下是一些解决此问题的不同方法:

1。 您可以在其上投射每个元素

public class A {...}
public class B extends A{...}
A[] array = new B[2];

2。您可以使用多态来改进上面的代码。要做到这一点,你必须在Relatable接口中声明move方法。我们现在可以拒绝转换,因为每个实现Relatable的类都必须实现 move(int x,int y) 方法(否则我们会得到java.lang.UnsupportedOperationException

public static void moveAll( int x, int y, Relatable... obj) {

    for(Relatable r: obj){
        ((Rectangle)r).move(x, y);
    }

}

希望这有帮助:)