繁体   English   中英

给定一个`Class`对象,获取对`toString`的方法引用

[英]Given a `Class` object, get a method reference to `toString`

如果你只有一个Class对象,那么如何获得对toString方法的方法引用 稍后我们将有这个特定类的实例,我们将通过方法引用调用此方法。

例如,考虑一个Java枚举,一个Enum的子类。 这里T被定义为<T extends Enum>

Class c = MyEnum.class
…
Function< T , String> f = c :: toString ;

我收到一条错误,说“无效的方法参考”。

对于toString ,它就像Object::toString一样简单。 所有Object都有toString ,所以你可以在那里使用它。 对于静态不知道对象具有该方法的其他方法,没有简单的方法; 你必须写一个lambda,以丑陋的反思方式。

如果可以使用Class<MyEnum> c=MyEnum.class;形式的类文字访问Class对象Class<MyEnum> c=MyEnum.class; ,这意味着MyEnum类型在编译时是已知的。 在这种情况下, Class对象是不必要的绕道。 您可以访问类的所有方法MyEnum使用形式MyEnum::methodName ,如

Function<MyEnum,String> f=MyEnum::toString;

这就是本教程描述为“对特定类型的任意对象的实例方法的引用”。 它不需要实际的MyEnum实例。

然而,当你想要一个Function<T,…>时,处理MyEnum毫无意义,因为该函数必须能够使用T任意实例,不一定是MyEnum 所以这个函数只能使用T存在的方法,不需要在MyEnum搜索它们。

由于您的目标方法不是特定于MyEnum ,因此可能:

Function<T,String> f=T::toString;

正如已经指出的那样toString方法在java.lang.Object定义,因此您也可以使用该表单

Function<T,String> f=Object::toString;

作为为所有对象声明的方法也可以在T实例上调用。 虽然这也有点无意义,因为你也可以使用

Function<Object,String> f=Object::toString;

反映消费任何Object实例的能力,而不仅仅是T 精心编写的通用代码将始终使用通配符来避免对其输入进行不必要的限制。 因此它将接受一个可以消耗 T的函数(这意味着能够使用MyEnum ),而不需要它的类型参数与该类型完全匹配。 例如:

<R> Stream<R> map(Function<? super T,? extends R> mapper)
map ,应用于Stream<T>将接受Function<Object,…>因为ObjectT的超类型...


因此,您可以使用T::methodName访问该类型边界的每个可用方法,即在您的情况下,您可以使用Enum所有方法,当然还有Object ,但是没有特定于MyEnum方法在其超类型中不存在。 这与您尝试在T实例上应用的普通方法调用没有什么不同。 此外, T不存在的方法无论如何都不适合创建有效的Function<T,…>


如果要为编译时未知的方法创建Function实例,则必须使用Reflection,这是必须处理Class对象的唯一情况(在方法引用的上下文中)。 这个答案的第二个例子展示了如何为返回一个对象的实例方法创建一个Function ,但这只适用于那些知道他们正在做什么的人......

还要注意,这种反射创建的Function必须使用原始类型,因为它们的相应泛型类型不能被声明,因为它将引用在编译时不存在的类型。

你在这里尝试的是获取类ClasstoString()引用,这可能不是你想要的。 由于toString()是为所有对象定义的,这应该工作(未测试):

Function< T , String> f = t -> t.toString();

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM