Reputation: 121
I have tested some things with bounded parameters in generic methods and I discovered some strange behavior.
It would be great If anybody could explain the two errors in the following code snippet.
Imagine there are two classes Class1
and Class2
both extend from a BaseClass
. Class2
implements an Interface.
In Class1
, I have a method which returns an instance of Class2
in the following way:
public class Class2 extends BaseClass implements Interface {
@Override
public void method() {
System.out.println("test"); //$NON-NLS-1$
}
}
public class Class1 extends BaseClass {
public <T extends BaseClass & Interface> T getTwo() {
return new Class2();
// Error: Type mismatch: cannot convert from Class2 to T
}
public static void main(String[] args) {
Interface two = new Class1().getTwo();
// Error: Bound mismatch: The generic method getTwo() of type Class1 is
// not applicable for the arguments (). The inferred type Interface is
// not a valid substitute for the bounded parameter <T extends BaseClass
// & Interface>
System.out.println(two);
}
}
Upvotes: 10
Views: 1611
Reputation: 70584
The first compilation error occurs because type parameters declared by methods are specified by the caller, not the method implementation. That is, given
class Class3 extends BaseClass implements Interface { ... }
a caller may write
Class3 c3 = new Class1().<Class3>getTwo();
, but the method implementation returns a Class2
, which isn't a subtype of T
= Class3
.
The second compilation error occurs because type parameters that aren't explicitly specified by the caller are inferred from method arguments and the type of the variable the method return value is assigned to. This inference fails here. The usual workaround, recommended by the Java Language Specification, is to specify the type parameters explicitly in such cases (type inference is intended as a convenience for simple cases; it doesn't aim to cover all cases).
As for how to properly declare this type parameter, I'd need to know what you are trying to accomplish with these declarations.
Upvotes: 5
Reputation: 425298
Why use generics for the method getTwo
, when you know it's a Class2
? Simply do this:
public Class2 getTwo() {
return new Class2();
}
If you're overriding a method public <T extends BaseClass & Interface> T getTwo()
, the compiler will allow you to declare your impl as public Class2 getTwo()
when your T
for your impl is Class2
Upvotes: 4