I'm using library which contains method I want to use. Simplified signature would look like this:
final class ThirdPartyClass
{
public static <T> void thirdPartyMethod(Class<T> clazz, T instance)
{
// does something
}
}
Inside thirdPartyMethod()
it expects class of T
as first argument and an instance of that specific class T
as second argument.
Now I have this simple abstract class, which is calling that method:
abstract class Parent<T extends Number>
{
public Parent(T instance)
{
ThirdPartyClass.thirdPartyMethod(instance.getClass(), instance);
}
}
I'm getting an error:
method thirdPartyMethod in class ThirdPartyClass cannot be applied to given types;
required: java.lang.Class, T
found: java.lang.Class<capture#1 of ? extends java.lang.Number>, T
reason: inference variable T has incompatible bounds
equality constraints: capture#2 of ? extends java.lang.Number
lower bounds: T
How can I modify the Parent
class so it conforms to expected arguments of thirdPartyMethod()
?
If possible with explanation.
CodePudding user response:
According to the return type of Object.getClass()
The actual result type is
Class<? extends |X|>
where|X|
is the erasure of the static type of the expression on which getClass is called.
Since T
extends Number
, the resulting type would be Class<? extends Number>
, i.e. means an unknown type extending Number
. Which doesn't match T extends Number
(i.e. a particular type extending Number
which would be provided at runtime).
How can I modify the Parent class so it conforms to expected arguments of thirdPartyMethod()?
1. Introduce a second parameter of type Class<T>
in your constructor.
abstract class Parent<T extends Number> {
public Parent(T instance, Class<T> tClass) {
ThirdPartyClass.thirdPartyMethod(tClass, instance);
}
}
2. Perform casting (as have been mentioned in the comments):
ThirdPartyClass.thirdPartyMethod((Class<T>) instance.getClass(), instance);
By the way, instead of calling methods from a constructor (especially ones that are not developed and tested by you/your colleagues) you might consider introducing a factory method that would produce your domain object based on the result of a method call.