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...
为了能够创建任何操作,我创建了一个名为 OperationType
的 Enum
来标识每个操作以及创建这些操作的工厂。工厂如下:
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 = ...
...
}
我正在使用一个 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...
为了能够创建任何操作,我创建了一个名为 OperationType
的 Enum
来标识每个操作以及创建这些操作的工厂。工厂如下:
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 = ...
...
}