繁体   English   中英

Java Generics和未选中的强制转换

[英]Java Generics and unchecked cast

我正在努力解决Java中泛型的这个方面。 希望有人可以帮我看看方法。

我有一个包含对象列表的类。 这段代码有效,但我想摆脱演员表。 我怎样才能使这更通用?

public class Executor {
    List<BaseRequest<BaseObj>> mRequests = new ArrayList<BaseRequest<BaseObj>>();

    public Executor() {
    }

    @SuppressWarnings("unchecked")
    public <T extends BaseObj> void add(final BaseRequest<T> request) {
        mRequests.add((BaseRequest<BaseObj>) request);
    }

    public void execute() {
        for (BaseRequest<BaseObj> r : mRequests) {
            // DO SOMETHING WITH r
        }
    }
}

在发布的代码片段中,您需要进行BaseRequest<? extends BaseObj>因为BaseRequest<? extends BaseObj> BaseRequest<? extends BaseObj>不是BaseRequest<BaseObj>的子类型,并且由于类型擦除而无法在运行时检查BaseRequest<BaseObj> ,这就是编译器警告您的原因。 但是如果你改变了mRequests的声明:

public class Executor  {

    List<BaseRequest<? extends BaseObj>> mRequests = new ArrayList<>();

    public Executor() {
    }

    public <T extends BaseObj> void add(final BaseRequest<T> request) {
        mRequests.add(request);
    }

    public void execute() {
        for (BaseRequest<? extends BaseObj> r : mRequests) {
            // DO SOMETHING WITH r
        }
    }
}

class BaseRequest<T> {}

class BaseObj {}

让我们一步一步解决问题。 你希望能够打电话

req.add(new BaseRequest<ExtObj1>());
req.add(new BaseRequest<ExtObj2>());
req.add(new BaseRequest<ExtObj3>());

其中ExtObj[1|2|3] extends BaseObj 给定List接口:

List<T> {
  void add(T el);
}

我们需要为BaseRequest<ExtObj1>BaseRequest<ExtObj2>BaseRequest<ExtObj3>找到一个公共超类型。 一个超类型是BaseRequest<?> ,另一个是BaseRequest<? extends BaseObj> BaseRequest<? extends BaseObj> 我选择了第二个,因为它是最可能限制的。 你应该知道,在Java中BaseRequest<ExtObj1>不是一个亚型BaseRequest<BaseObj>因为泛型是不变的。

现在我们有了mRequests的正确声明,找到Executor.add()的API非常简单。 顺便说一句,如果你需要的方法体非常简单,你甚至不需要type参数:

public void add(BaseRequest<? extends BaseObj> request) {
  mRequests.add(request);
}

警告不是错误。 有警告,所以你检查是否有错误,因为它可能不会被自动检查。 您应该检查它,然后使用注释注意已经检查过警告。

在你的情况下,它警告BaseRequest<T>不等于BaseRequest<BaseObj>

例:

public class NumberWrapper<N extends Number> {
    private N value;
    public void setValue(N value) {
        this.value = value;
    }
}

public class MainClazz {
    private NumberWrapper<Integer> wrappedNumber = new NumberWrapper<Integer>();
    public void run() {
        Number n = externalSource.getNumber();
        wrappedNumber.setValue(n); // <-- Error. What if getNumber returns a double?
    }
}

您可以出现此错误,而不是取决于您完成/集成所显示代码的方式。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM