I am getting a very weird compilation error in the below Java code.
I have a simple interface having an API with generic return type:
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.
AFAIK the problem is that in the first case you're actually disabling generics. This would result in T
being coerced to Object
in that case and due to return type covariace returning a String
is fine. 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 )
.
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.
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:
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";
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.