[英]Java Generic Return type Issue
I am getting a very weird compilation error in the below Java code. 我在下面的Java代码中收到一个非常奇怪的编译错误。
I have a simple interface having an API with generic return type: 我有一个简单的接口,具有具有通用返回类型的API:
public interface AttributeGenerator {
<T> T generateAttribute(Record record);
}
I can write an implementation and this one compiles fine: 我可以写一个实现,这个可以编译:
public class StringAttributeGenerator implements AttributeGenerator {
@Override
public String generateAttribute(Record record) {
return "Test";
}
}
Now, lets say, I add another parameter to the above interface. 现在,可以说,我在上面的界面中添加了另一个参数。
public interface AttributeGenerator {
<T> T generateAttribute(Record record, Set<Integer> indices);
}
And I provide another implementation as: 我提供了另一种实现方式:
public class StringAttributeGenerator implements AttributeGenerator {
@Override
public String generateAttribute(Record record, Set<Integer> indices) {
return "Test";
}
}
The compilations fails and compiler complaints that: 编译失败,编译器抱怨:
The method does not override from its superclass. 该方法不会从其超类重写。
I cannot understand why the compiler is not able to compile the second instance, and if it is not, I would like to understand why is it not possible for Java to provide user a facility to write such a code. 我不明白为什么编译器不能编译第二个实例,如果不是,我想理解为什么Java无法为用户提供编写此类代码的便利。
AFAIK the problem is that in the first case you're actually disabling generics. AFAIK问题在于,在第一种情况下,您实际上是在禁用泛型。 This would result in T
being coerced to Object
in that case and due to return type covariace returning a String
is fine. 在这种情况下,这将导致T
被强制转换为Object
,并且由于返回类型为协方差,因此返回String
是可以的。 However, this should generate a warning since you're basically forcing the compiler to ignore generics and use the "traditional" way which would be equivalent to directly writing Object generateAttribute( Record record )
. 但是,这应该会产生警告,因为您基本上是在迫使编译器忽略泛型并使用“传统”方式,这相当于直接编写Object generateAttribute( Record record )
。
In the second case, if you disable generics in the way I described above the signature will look like generateAttribute(Record record, Set indices)
where the second parameter would be equivalent to Set<Object>
and thus the signature doesn't match anymore. 在第二种情况下,如果以上述方法禁用泛型,则签名将看起来像generateAttribute(Record record, Set indices)
,其中第二个参数等效于Set<Object>
,因此签名不再匹配。
Also note that while your first snippet would compile you could get runtime problems, eg if you did something like this: 还要注意,虽然您的第一个代码段可以编译,但是您可能会遇到运行时问题,例如,如果您执行了以下操作:
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 );
What you could do is define T
in the interface, eg like this: 您可以在接口中定义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";
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.