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);
}
}
Whenever you want to restrict the type parameter to subtypes of a particular class you can use the bounded type parameter. If you just specify a type (class) as bounded parameter, only sub types of that particular class are accepted by the current generic class. These are known as bounded-types in generics in Java.
Bounded and unbounded wildcards in Generics are two types of wildcards available on Java. Any Type can be bounded either upper or lower of the class hierarchy in Generics by using bounded wildcards.
A Generic class can have muliple type parameters.
A type parameter can have multiple bounds.
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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With