public Collection<String> transform(Collection<String> list) { return new HashSet<String>(); }; //1
It seems to me that //1 is actually an implementation of the given method with T=String...Is that perhaps the problem? One cannot give an explicit parametrization of a generic method to avoid collisions with the 'compiler-generated' one?
Think about it from the perspective of the user of this method. The base class's method's argument is transform(Collection<T> list), where T extends CharSequence, which means one could pass any CharSequence. So, they could pass a StringBuilder also.
But the subclass method is trying to break the contract by saying it will only accept a String. What if, based on the promise of the base class has code like this:
void methodX(Base b){
Collection<StringBuilder> c = ...;
b.tansform(c);
}
Now, if someone calls methodX with an object of type Derived, what will happen?
If you like our products and services, please help us by posting your review here.
public <T extends CharSequence> Collection<T> transform(List<T> list) { return new HashSet<T>(); }; //4
Overriding method returns type: Collection<T> which looks to be not covariant with base method return type: Collection<String>
As for me it looks like return method may return Collection of anything, while base method allows only Collection of String to be returned
Could you please advise on following as it's not clear for me:
Why //4 is correct override of transform method?
I fell for this as well. 4 is an overload, not an override. The option states "//4 correctly overloads the method in Base.". Derived has two "transform" methods in option 4.
Could you please advise on following as it's not clear for me:
Why //4 is correct override of transform method?
I fell for this as well. 4 is an overload, not an override. The option states "//4 correctly overloads the method in Base.". Derived has two "transform" methods in option 4.
If T is a super class of String, then you can't pass List<T> as an argument when argument type is List<String>. (Because, for example, T could be Object and List<Object> will break List<String>).
But if T is a subclass of String you can pass List<T> for List<String>.
If you like our products and services, please help us by posting your review here.
class Base {
public <T> Collection<String> transform(Collection<String> list) {
return null;
}
}
class Derived extends Base {
@Override
public <T> Collection<String> transform(Collection list) {
return null;
}
}
it won't compile, but when I remove the <T> from the overriding method, it does compile. Can you please explain why?
The presence of <T> makes the method in the derived class a generic method, which prompts compiler to apply a different set of rules for overriding of generic methods (see the error message generated by the compiler). When there is no <T>, it is not a generic method and the specification allows a generic method to be overridden by a non generic method.
If you like our products and services, please help us by posting your review here.
Second, if it is a potential override, check the generic type specification of the parameters. If the overriding method does not use a generic type specification for the parameter type, then it is valid. The reverse is not valid i.e. the overriding method is allowed to erase the generic type specification but is not allowed to add a generic type specification if the overridden method does not have it. If both the methods have a generic type specification, then the specification must match exactly.
I wrote "different" because I was talking about the difference between <T> and no <T>. When you have <T> in both, the same set of rules apply. I know it is a complicated but go through the complete explanation. If you try to pick sentences in isolation, you may feel some things sound contradictory.
If you like our products and services, please help us by posting your review here.
Thanks a lot, I think I got it now:) I merged the Second step with the type parameter-part and some new wording to make it clearer for myself. Would this be accurate?
"Second, if it is a potential override, check the generic type specification of the type-parameter(with bounds if any) and actual parameters. If the overriding method does not use a generic type specification in these places, then it is valid. The reverse is not valid i.e. the overriding method is allowed to erase the generic type specification but is not allowed to add a generic type specification if the overridden method does not have it. If both the methods have generic type specification, then the specification must match exactly (this goes for both type-parameter and parameters). For example, if the overridden method has the parameter Set<Integer>, then the overriding method can use Set or Set<Integer>. But if overridden method has Set, then the overriding method must also have Set for a valid override.
The T in <T> is called as the "type" parameter. It is used as a place holder.........etc"