为什么这段代码会引发ClassCastException?

时间:2018-11-04 06:47:20

标签: java android

下面的代码来自我在Android Studio中的应用,并且运行正常:

static void removeViewParent(ImageView image) {
    if (image.getParent() != null) ((ViewGroup) image.getParent()).removeView(image);
}

我试图按照类似的想法重现它:由于原始的:抽象类ViewGroupImageView继承了相同的超类View,并且其方法getParent()返回一个接口参考。使用IntelliJ IDEA,我在以下代码中出于铸造目的进行了类似的复制:

interface ViewParent {
    ViewParent getParentView();
}

class View {
    ViewParent getParent() {
        return () -> null;
    }
}

abstract class ViewGroup extends View implements ViewParent {
    void removeView(ImageView image) {
        System.out.println(image); //Just for debugging.
    }
}

class ImageView extends View {
}

class RunMain {
    public static void main(String[] args) {
        ImageView image = new ImageView();
        ((ViewGroup) image.getParent()).removeView(image);
    }
}

线程“主”中的异常java.lang.ClassCastException:无法将View $$ Lambda $ 1/1078694789强制转换为ViewGroup。

已编辑: Android SDK中的原始类View实际上返回了一个ViewParent,所以怎么可能?

enter image description here enter image description here

为什么我会收到ClassCastException?

2 个答案:

答案 0 :(得分:0)

ViewGroupImageView都是View的子类,但是它们没有直接的继承关系(超子类)。一个不能在两个子类之间转换。仅在超类及其子类之间(上铸造或下铸造)

假设给出了层次结构树(意味着您无法更改它),然后要做此工作,您需要明确询问getParent()返回值的类型

if (image.getParent() != null && image.getParent() instanceof ViewGroup) { 
   ((ViewGroup) image.getParent()).removeView(image);
}

答案 1 :(得分:0)

这将使getParent()返回ViewGroup的实例,因此其与ParentView接口的实现使ViewGroup兼容,因此没有 ClassCastException

class View {
    ViewParent getParent() {
        return new ViewGroup() {
            @Override
            public ViewParent getParentView() {
                return null;
            }
        };
    }
}