Java 中未经检查的分配警告

Unchecked assignment warning in Java

我正在使用一个 API 来执行几个操作,它目前正在开发中。为了隔离它,以便我可以轻松处理那些不断变化的情况,我创建了一个功能接口 Operation 和方法 perform,如下所示:

public interface Operation<R, T> {
    R perform(T arg);
}

我所有的操作都实现了这个接口。例如,查找文件操作的实现如下所示:

public class Finder implements Operation<InputStream, String> {
    @Override
    public InputStream perform(String arg) {
        //Code to find the file
    }
}

此 class 使用 InputStream 作为 return 和 String 作为参数,但其他操作可以采用其他参数并具有不同的 returns...

为了能够创建任何操作,我创建了一个名为 OperationTypeEnum 来标识每个操作以及创建这些操作的工厂。工厂如下:

public class OperationsFactory {
    public static Operation create(OperationType type) {
        switch (type) {
        case FIND:
            return new Finder();
        // cases for each operation
        default:
            throw new InvalidParameterException("Can't create operation type: " + type.toString());

        }
    }
}

好的,这就是我的结构。它可能不是您的最佳选择,但这不是我要在这里解决的问题。问题是,当我尝试使用它时,我收到 Unchecked Assignment 警告,我想删除它而不用注释来忽略此类警告(我认为这很糟糕)。让我放一个有这个异常的方法的代码:

public InputStream performFindOperation(String path) {
    Operation<InputStream, String> findOperation = OperationsFactory.create(OperationType.FIND); //warning here!!
    return findOperation.perform(path);
}

所以,Java专家,我该如何删除这个警告?

这是因为您的 OperationsFactory returns 是 Operation 而不是正确泛化的 Operation<X, Y>,所以如果您将它分配给 findOperation 类型 Operation<InputStream, String>,你得到这个警告(因为编译器不能保证你分配正确的类型)。

遗憾的是,您无法将泛型添加到 enum 中(它在未来的 Java 功能列表中),因此您将无法安全地这样做。摆脱警告的唯一方法是抑制它。

附带说明一下,您可以只使用 java.util.Function<T, R> 而不是定义自己的功能接口。

注意这里没有类型参数:

public static Operation create(OperationType type) {
//                    ^ isn't something supposed to be there?

这称为 raw type,实际上等同于 Operation<Object, Object>,但是,对于任何 A 和 [=16=,它都可以分配给 Operation<A, B> ].

什么语言促使您使用此警告来指定返回操作的实际类型,例如:

public static Operation<InputStream, String> create(OperationType type) {

现代代码中应避免使用原始类型,它们的存在是出于历史向后兼容的原因(Java 在版本 5 之前没有泛型)。


编辑: 实际上,您想要做的事情需要相当先进的类型系统,并支持一些依赖类型 Java 没有 - 如果你想避免警告,那就是。我建议您将选项枚举为普通字段,而不是尝试使用标准 enum,例如

public class OperationType {
  public static Operation<InputStream, String> FIND = ...
  public static Operation<OutputStream, String> WRITE = ...
  ...
}