通过使用未经检查的类型转换来避免使类具有通用性

时间:2016-12-19 02:12:34

标签: java generics unchecked-cast

假设我创建了一个包含公共类process的包Processor,它有一个构造函数,需要一个Container<I>类型的参数。类Container<I>位于我无法控制的不同包中,包含任意类型I的对象。包含项的容器在包process的多个类之间传递。

通过界面Processable的方法处理项目。 process用户可以通过方法getProcessedItem(Property property)检索它们。此方法返回具有属性property的已处理项,该属性确保包含在已传递的容器中,因此可以强制转换为容器的type参数。

示例类:

package process;

import container.Container;

public class Processor<I extends Processable> {
    private final ItemProcessor itemProcessor;

    public Processor(Container<I> container){       
        this.itemProcessor = new ItemProcessor(container);
    }

    @SuppressWarnings("unchecked")
    public I getProcessedItem(Property property){
        return (I)itemProcessor.getProcessedItem(property);
    }

}

在这种情况下进行未经检查的类型转换通常是个好主意吗?

我到目前为止唯一合理的选择是让包process中必须保存对参数化容器(如ItemProcessor)的引用的所有类也只是为了通用保留getProcessedItem(Property property)中所需的类型信息。

修改 为了阐明我的示例中容器类的功能:

我希望容器类能够代表一些相当原始的类似集合的类,它应该只使处理器能够检索它必须处理的项目。

这意味着ItemProcessorItemProcessor使用的类应该能够处理可处理的项目(一旦从容器中检索它们) 他们喜欢(例如将它们存储在列表或其他数据结构中)。最后,应该可以根据某个特定于处理器的属性请求已处理的项目。例如:

getProcessedItem(Property.MOST_RECENTLY_PROCESSED)

与java的标准集合类一样(例如ArrayListContainer<I>并不严格保证它只包含I及其后代。这意味着一旦容器的项目用作Processable,而实际上不是Processable,则会发生强制转换异常。

在上面的Processor类的版本中,当通过getProcessedItem请求的项与类型I不兼容时(由于未经检查的强制转换),不会立即抛出异常。但是如果我使ItemProcessor泛型(ItemProcessor<I>)并使其getProcessedItem返回I而不是使用未经检查的强制转换,则此时不会抛出任何异常。因此,我也不确定使用Class<I>中的getProcessedItem对象进行运行时类型检查是否更好。 Class<I>对象必须由调用者作为参数或通过给定容器显式提供。我觉得确保容器中的项目实际上与I兼容不应该是处理器的关注,因为处理器不负责给定容器内容的有效性。

2 个答案:

答案 0 :(得分:0)

我认为你的SuppressWarnings违背了仿制药的目的。你应该做的是使getProcessed项也是通用的。

public class ItemProcessor<I extends Processable> {
    public I getProcessedItem() {
       return somethingWhichIsProcessable;
    }

答案 1 :(得分:0)

Class类上有一个cast()方法,不会产生任何警告......

但是,你的模型是错误的。您应该询问容器的项目,而不是任意项目处理器。你打破了封装。事实上整个ItemProcessor都有它的味道。您应该考虑一种多态解决方案,其中对象对自己起作用,而不是外部actor在外部对象作用的模型。