[英]Using wildcard with Generic method
Would like to get some advise on it想得到一些建议
My class structure is like this我的班级结构是这样的
public abstract class Base {}
public class Derived1 extends Base {}
public class Derived2 extends Base {}
public class ServiceClass {
public String method1(Derived1 derived1) {
return "derived1";
}
public String method2(Derived2 derived2) {
return "derived2";
}
}
In my main code (MainProg),I am trying to use the same function to refer to the 2 methods in service class and seeing the compilation error as put in the comment在我的主代码(MainProg)中,我尝试使用相同的函数来引用服务类中的 2 个方法,并看到注释中的编译错误
public class MainProg {
public static void main(String[] args) {
ServiceClass serviceClass = new ServiceClass();
//Incompatible types: Base is not convertible to Derived1
Function<? extends Base,String> function1 = serviceClass::method1;
//Incompatible types: Object is not convertible to Derived1
Function<?,String> function2 = serviceClass::method1;
//Incompatible types: Base is not convertible to Derived2
Function<? super Base,String> function3 = serviceClass::method2;
}
}
Is there a way to declare my function object so that same function object can be used to refer to methods taking different type of arguments?有没有办法声明我的函数对象,以便可以使用相同的函数对象来引用采用不同类型参数的方法?
Yes, by using an intermediary variable:是的,通过使用中间变量:
Function<Derived1, String> function1 = serviceClass::method1;
Function<Derived2, String> function2 = serviceClass::method2;
Function<? extends Base, String> function = condition ? function1 : function2;
That said, you won't be able to invoke function
, because you don't know whether to pass a Derived1
or a Derived2
, or as the compiler puts it:也就是说,您将无法调用
function
,因为您不知道是传递Derived1
还是Derived2
,或者像编译器所说的那样:
function.apply(new Derived2());
// error: The method apply(capture#1-of ? extends Base) in the type Function<capture#1-of ? extends Base,String> is not applicable for the arguments (Derived2)
You could, however, use generics to abstract over the argument type:但是,您可以使用泛型对参数类型进行抽象:
<T extends Base> invokeSafely(Function<T, String> function, T argument) {
function.apply(argument);
}
which would allow you to write这将允许你写
invokeSafely(serviceClass::method1, new Derived1());
invokeSafely(serviceClass::method2, new Derived2());
but not但不是
invokeSafely(function, new Derived1()); // same error as before
//Incompatible types: Base is not convertible to Derived1
Function<? extends Base,String> function1 = serviceClass::method1;
It's some weird quirk of type inference that I don't fully understand.这是我不完全理解的类型推断的一些奇怪的怪癖。 It's inferring
Function<Base,String>
from the left-hand side and trying to apply it to the right-hand-side.它从左侧推断
Function<Base,String>
并尝试将其应用于右侧。
You can fix it like this.你可以像这样修复它。 The cast is safe:
演员是安全的:
Function<? extends Base,String> function1 = (Function<Derived1, String>) serviceClass::method1;
or this:或这个:
Function<Derived1, String> tmp = serviceClass::method1;
Function<? extends Base,String> function1 = tmp;
It's worth noting that you can never invoke this function (except with null
), since you have thrown away the knowledge of what type of argument it expects.值得注意的是,你永远不能调用这个函数(除了
null
),因为你已经抛弃了它期望什么类型的参数的知识。 ? extends Base
? extends Base
is something that extends Base (ie Derived1 or Derived2) but we don't know which. ? extends Base
是扩展 Base(即 Derived1 或 Derived2)的东西,但我们不知道是哪个。
//Incompatible types: Object is not convertible to Derived1
Function<?,String> function2 = serviceClass::method1;
Same issue as the first one, except it's inferring Object instead of Base.与第一个问题相同,只是它推断的是 Object 而不是 Base。
//Incompatible types: Base is not convertible to Derived2
Function<? super Base,String> function3 = serviceClass::method2;
Derived1 or Derived2 are not super classes of Base. Derived1 或 Derived2 不是 Base 的超类。 They are subclasses.
它们是子类。 Only Object is a superclass of Base.
只有 Object 是 Base 的超类。
method2
does not expect Object
. method2
不期望Object
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.