【问题标题】:Given a `Class` object, get a method reference to `toString`给定一个 `Class` 对象,获取对 `toString` 的方法引用
【发布时间】:2015-08-27 05:02:29
【问题描述】:

如果您只有一个Class 对象,如何将method reference 传递给toString 之类的方法?稍后我们将拥有这个特定类的实例,我们将在其上通过方法引用调用此方法。

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

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

我收到一条错误消息,提示“方法引用无效”。

【问题讨论】:

    标签: java lambda enums java-8 method-reference


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

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

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

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

      尽管如此,当您想拥有Function&lt;T,…&gt; 时,处理MyEnum 毫无意义,因为该函数必须能够使用T 的任意实例,不一定是MyEnum。所以这个函数只能使用T中已有的方法,不需要在MyEnum中搜索。

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

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

      但是as already pointed out,方法toString是在java.lang.Object中定义的,所以你也可以使用形式

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

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

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

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

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


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


      如果要为编译时未知的方法创建Function 实例,则必须使用反射,这是唯一需要处理Class 对象的情况(在方法的上下文中)参考)。 this answer 的第二个示例展示了如何为返回对象的实例方法创建 Function,但这实际上只适用于那些确切知道自己在做什么的人……

      还要注意,这种反射式创建的 Functions 必须使用原始类型,因为它们的适当泛型类型无法声明,因为它会引用编译时不存在的类型。

      【讨论】:

        【解决方案3】:

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

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-12-01
          • 1970-01-01
          • 2013-08-29
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-04-02
          • 1970-01-01
          相关资源
          最近更新 更多