Java对象转换无法正常工作,因为我需要它 [英] Java object casting doesn't work like I need it to

查看:89
本文介绍了Java对象转换无法正常工作,因为我需要它的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在Java上开发本机Android应用程序,但是遇到了一些意外的行为.看一下这些类:

I'm developing native Android app on Java and I faced some unexpected behavior. Look at these classes:

public class Parent<C> {

    protected C mCallback;

    public void setCallback(Object callback) {
        mCallback = (C)callback;
    }
}

class Child<T extends Vehicle>
        extends Parent<Child.Callback<Vehicle>>{

    public void invoke(){
        mCallback.onAction(new Vehicle());
    }

    public interface Callback<T> {
        void onAction(T vehicle);
    }
}

class Vehicle {

}

现在

    Child<Vehicle> child = new Child<Vehicle>();
    child.setCallback(new Object()); // I expect ClassCastException to be thrown here!
    child.invoke(); //But it's thrown only here!

为什么.setCallback()方法中没有引发ClassCastException?

为什么只有当我尝试访问回调接口的方法时才会抛出该异常?

如何检查对象回调是C的实例?或者至少如何在setCallback()方法中获取ClassCastException?

P.S.这是简化的示例!请在此处考虑相同但真实的问题:如何检查在Fragment.onAttach()中键入回调类型

P.S. This is simplified example! Please consider the same, but real life question here: How to check typed callback type inside Fragment.onAttach()

@ luckydog32在评论中提出的一种解决方案

One of the solutions proposed by @luckydog32 in comments here

public abstract class Parent<C> {

    protected C mCallback;

    public void setCallback(Object callback) {
        mCallback = castCallback(callback);
    }

    protected abstract C castCallback(Object callback) throws ClassCastException;
}

class Child<T extends Vehicle>
        extends Parent<Child.Callback<Vehicle>>{
    @Override
    protected Callback<Vehicle> castCallback(Object callback) throws ClassCastException {
        return (Callback<Vehicle>)callback;
    }

    public void invoke(){
        mCallback.onAction(new Vehicle());
    }

    public interface Callback<T> {
        void onAction(T vehicle);
    }
}

推荐答案

这是因为称为类型为擦除.基本上,在您编译程序之后,泛型类型将替换为其上界.例如

This is because of something called Type Erasure. Basically after you program is compiled generic types are replaced with their Upper Bound. So for example

class Child<T extends Vehicle>

每个T实例都被当作是Vehicle类.

Every instance of T is just treated as if it were a Vehicle class.

因此在代码中:

public void setCallback(Object callback) {
    mCallback = (C)callback;
}

在运行时,您几乎是在说:

During run time you are pretty much saying:

public void setCallback(Object callback) {
    mCallback = (Object)callback;
}

由于您要立即投射回调,因此只需修改代码即可:

Since you are casting callback immediately, the simple fix for your code would to just do:

public void setCallback(C callback) {
    mCallback = callback;
}

这篇关于Java对象转换无法正常工作,因为我需要它的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆