我在下面的 Java 代码中遇到了一个非常奇怪的编译错误。
我有一个简单的接口(interface),它有一个具有通用返回类型的 API:
public interface AttributeGenerator {
<T> T generateAttribute(Record record);
}
我可以编写一个实现,并且这个可以很好地编译:
public class StringAttributeGenerator implements AttributeGenerator {
@Override
public String generateAttribute(Record record) {
return "Test";
}
}
现在,假设我向上述接口(interface)添加另一个参数。
public interface AttributeGenerator {
<T> T generateAttribute(Record record, Set<Integer> indices);
}
我提供了另一个实现:
public class StringAttributeGenerator implements AttributeGenerator {
@Override
public String generateAttribute(Record record, Set<Integer> indices) {
return "Test";
}
}
编译失败并且编译器提示:
该方法不会从其父类(super class)重写。
我无法理解为什么编译器无法编译第二个实例,如果不能,我想理解为什么Java不能为用户提供编写此类代码的工具。
最佳答案
据我所知,问题在于,在第一种情况下,您实际上禁用了泛型。这将导致 T
被强制Object
在这种情况下,由于返回类型协方差返回 String
很好。但是,这应该会生成一个警告,因为您基本上是在强制编译器忽略泛型并使用“传统”方式,这相当于直接编写 Object generateAttribute( Record record )
.
在第二种情况下,如果您按照我上面描述的方式禁用泛型,签名将类似于 generateAttribute(Record record, Set indices)
其中第二个参数相当于 Set<Object>
因此签名不再匹配。
另请注意,虽然您的第一个代码片段可以编译,但您可能会遇到运行时问题,例如如果你做了这样的事情:
AttributeGenerator unknownGenerator = new StringAttributeGenerator();
//You'd get a string and the system would try to cast to Integer, which clearly will fail
Integer iWontCompile = unknownGenerator.generateAttribute( someRecord );
你可以做的就是定义 T
在界面中,例如像这样:
public interface AttributeGenerator<T> {
T generateAttribute(Record record, Set<Integer> indices);
}
public class StringAttributeGenerator implements AttributeGenerator<String> {
@Override
public String generateAttribute(Record record, Set<Integer> indices) {
return "Test";
}
}
关于Java 通用返回类型问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33524714/