Java 方法引用的通用函数接口的方法签名

Java 方法引用的通用函数接口的方法签名,java,java-8,method-reference,functional-interface,Java,Java 8,Method Reference,Functional Interface,假设你有一个方法 void m(String s) {} 通过使用新方法引用,您可以从中创建使用者 Consumer<String> c = Class::m; If通过创建匿名内部类以旧方式创建了使用者 Consumer<String> c = new Consumer<String>() { public void accept(String s){} } 消费者c=新消费者(){ 公共无效接受(字符串s){} } 将有桥接方法void-

假设你有一个方法

void m(String s) {} 
通过使用新方法引用,您可以从中创建
使用者

Consumer<String> c = Class::m;
If通过创建匿名内部类以旧方式创建了使用者

Consumer<String> c = new Consumer<String>() {
    public void accept(String s){}
}
消费者c=新消费者(){
公共无效接受(字符串s){}
}
将有桥接方法
void-accept(Object)
以及
void-accept(String)


现在让我们假设我们必须传递这个消费者,从而释放它的泛型类型。如果您有一个
Consumer
的实现,而不是一个Lambda表达式,那么您可以通过使用relfection访问其方法来获取它。因为通过方法引用创建的使用者只有通用方法,所以这不起作用。是否有方法获取由方法引用创建的使用者的参数类型

调用原始使用者(没有泛型类型)总是导致警告。您不应该这样做,因为您不知道类型。原始类型没有类型。Java8没有改变这一点

接口使用者具有泛型类型,但在运行时您不知道这一点。甚至连兰博达斯也没有。有些类可能确实有这些信息,但这对您没有帮助。 如果您确实需要知道类型,那么只需创建这样一个接口

  @FunctionalInterface
  public static interface StringConsumer {
    void consume(String s);
  }

  public static void main(String[] args) throws Throwable {
    StringConsumer sc = System.out::println;
    sc.consume("Hello");
    Method m = StringConsumer.class.getMethods()[0]; // only one: "consume"
    m.invoke(sc, m.getParameters()[0].getType().getSimpleName());
  }
下面是一些示例代码和输出,以查看有哪些方法以及如何调用它们:

package com.example.foo;

import static java.util.Arrays.asList;

import java.lang.reflect.Method;
import java.util.function.Consumer;

public class SomeClass {
  @FunctionalInterface
  static interface FI {
    public void m(String s);
  }

  static final class MyRegularClass {
    @SuppressWarnings("static-method")
    public void m(String s) {
      System.out.println("MyRegularClass: " + s);
    };
  }

  static final class MyGenericClass<T> {
    public void m(T s) {
      System.out.println("MyGenericClass: " + s);
    };
  }

  public static void main(String[] args) throws Exception {

    Consumer<String> c1 = (s) -> {
      System.out.println("Lambda: " + s);
    };
    Consumer<String> c2 = new Consumer<String>() {
      public void accept(String s) {
        System.out.println("Anonym: " + s);
      }
    };
    Consumer<String> c3 = new MyRegularClass()::m;
    Consumer<String> c4 = new MyGenericClass<String>()::m;

    for (Consumer<String> c : asList(c1, c2, c3, c4)) {
      c.accept("regular invocation of accept(String)");

      for (Method m : c.getClass().getDeclaredMethods()) {
        String n = m.getName() + "(" + m.getParameters()[0].getType().getSimpleName() + ")";
        try {
          m.invoke(c, n);
        } catch (Exception e) {
          System.out.println("Did not accept String: " + n + " => " + e);
        }
        try {
          m.setAccessible(true);
          m.invoke(c, new StringBuilder("StringBuilder of ").append(n));
        } catch (Exception e) {
          System.out.println("Did not accept StringBuilder: " + n + " => " + e);
        }
      }
      System.out.println("-----");
    }
  }
}

/* ==========================================
Output:

Lambda: regular invocation of accept(String)
Lambda: accept(Object)
Did not accept StringBuilder: accept(Object) => java.lang.reflect.InvocationTargetException
-----
Anonym: regular invocation of accept(String)
Anonym: accept(String)
Did not accept StringBuilder: accept(String) => java.lang.IllegalArgumentException: argument type mismatch
Anonym: accept(Object)
Did not accept StringBuilder: accept(Object) => java.lang.reflect.InvocationTargetException
-----
MyRegularClass: regular invocation of accept(String)
MyRegularClass: accept(Object)
Did not accept StringBuilder: accept(Object) => java.lang.reflect.InvocationTargetException
Did not accept String: get$Lambda(MyRegularClass) => java.lang.IllegalAccessException: Class com.example.foo.SomeClass can not access a member of class com.example.foo.SomeClass$$Lambda$2/1175962212 with modifiers "private static"
Did not accept StringBuilder: get$Lambda(MyRegularClass) => java.lang.IllegalArgumentException: argument type mismatch
-----
MyGenericClass: regular invocation of accept(String)
MyGenericClass: accept(Object)
Did not accept StringBuilder: accept(Object) => java.lang.reflect.InvocationTargetException
Did not accept String: get$Lambda(MyGenericClass) => java.lang.IllegalAccessException: Class com.example.foo.SomeClass can not access a member of class com.example.foo.SomeClass$$Lambda$3/617901222 with modifiers "private static"
Did not accept StringBuilder: get$Lambda(MyGenericClass) => java.lang.IllegalArgumentException: argument type mismatch
-----
*/
package com.example.foo;
导入静态java.util.Arrays.asList;
导入java.lang.reflect.Method;
导入java.util.function.Consumer;
公共类{
@功能接口
静态接口{
公共空白m(字符串s);
}
静态最终类MyRegularClass{
@SuppressWarnings(“静态方法”)
公共void m(字符串s){
System.out.println(“MyRegularClass:+s”);
};
}
静态最终类MyGenericClass{
公共空间m(T s){
System.out.println(“MyGenericClass:+s”);
};
}
公共静态void main(字符串[]args)引发异常{
消费者c1=(s)->{
System.out.println(“Lambda:+s”);
};
消费者c2=新消费者(){
公共无效接受(字符串s){
System.out.println(“匿名:+s”);
}
};
消费者c3=新的MyRegularClass()::m;
消费者c4=新的MyGenericClass()::m;
对于(消费者c:asList(c1、c2、c3、c4)){
c、 accept(“accept(String)的常规调用”);
对于(方法m:c.getClass().getDeclaredMethods()){
字符串n=m.getName()+”(“+m.getParameters()[0].getType().getSimpleName()+”);
试一试{
m、 调用(c,n);
}捕获(例外e){
System.out.println(“未接受字符串:+n+”=>“+e”);
}
试一试{
m、 setAccessible(true);
m、 调用(c,新的StringBuilder(“StringBuilder of”)。追加(n));
}捕获(例外e){
System.out.println(“未接受StringBuilder:+n+”=>“+e”);
}
}
System.out.println(“----”);
}
}
}
/* ==========================================
输出:
Lambda:接受(字符串)的常规调用
Lambda:接受(对象)
未接受StringBuilder:accept(Object)=>java.lang.reflect.InvocationTargetException
-----
匿名:接受(字符串)的常规调用
匿名:接受(字符串)
未接受StringBuilder:accept(String)=>java.lang.IllegalArgumentException:参数类型不匹配
匿名:接受(对象)
未接受StringBuilder:accept(Object)=>java.lang.reflect.InvocationTargetException
-----
MyRegularClass:接受(字符串)的常规调用
MyRegularClass:接受(对象)
未接受StringBuilder:accept(Object)=>java.lang.reflect.InvocationTargetException
未接受字符串:get$Lambda(MyRegularClass)=>java.lang.IllegalAccessException:Class com.example.foo.SomeClass无法访问带有修饰符“private static”的类com.example.foo.SomeClass$$Lambda$2/117596212的成员
未接受StringBuilder:get$Lambda(MyRegularClass)=>java.lang.IllegalArgumentException:参数类型不匹配
-----
MyGenericClass:接受(字符串)的常规调用
MyGenericClass:接受(对象)
未接受StringBuilder:accept(Object)=>java.lang.reflect.InvocationTargetException
未接受字符串:get$Lambda(MyGenericClass)=>java.lang.IllegalAccessException:Class com.example.foo.SomeClass无法访问带有修饰符“private static”的类com.example.foo.SomeClass$$Lambda$3/617901222的成员
未接受StringBuilder:get$Lambda(MyGenericClass)=>java.lang.IllegalArgumentException:参数类型不匹配
-----
*/

调用原始使用者(没有泛型类型)总是会导致警告。您不应该这样做,因为您不知道类型。原始类型没有类型。Java8没有改变这一点

接口使用者具有泛型类型,但在运行时您不知道这一点。甚至连兰博达斯也没有。有些类可能确实有这些信息,但这对您没有帮助。 如果您确实需要知道类型,那么只需创建这样一个接口

  @FunctionalInterface
  public static interface StringConsumer {
    void consume(String s);
  }

  public static void main(String[] args) throws Throwable {
    StringConsumer sc = System.out::println;
    sc.consume("Hello");
    Method m = StringConsumer.class.getMethods()[0]; // only one: "consume"
    m.invoke(sc, m.getParameters()[0].getType().getSimpleName());
  }
下面是一些示例代码和输出,以查看有哪些方法以及如何调用它们:

package com.example.foo;

import static java.util.Arrays.asList;

import java.lang.reflect.Method;
import java.util.function.Consumer;

public class SomeClass {
  @FunctionalInterface
  static interface FI {
    public void m(String s);
  }

  static final class MyRegularClass {
    @SuppressWarnings("static-method")
    public void m(String s) {
      System.out.println("MyRegularClass: " + s);
    };
  }

  static final class MyGenericClass<T> {
    public void m(T s) {
      System.out.println("MyGenericClass: " + s);
    };
  }

  public static void main(String[] args) throws Exception {

    Consumer<String> c1 = (s) -> {
      System.out.println("Lambda: " + s);
    };
    Consumer<String> c2 = new Consumer<String>() {
      public void accept(String s) {
        System.out.println("Anonym: " + s);
      }
    };
    Consumer<String> c3 = new MyRegularClass()::m;
    Consumer<String> c4 = new MyGenericClass<String>()::m;

    for (Consumer<String> c : asList(c1, c2, c3, c4)) {
      c.accept("regular invocation of accept(String)");

      for (Method m : c.getClass().getDeclaredMethods()) {
        String n = m.getName() + "(" + m.getParameters()[0].getType().getSimpleName() + ")";
        try {
          m.invoke(c, n);
        } catch (Exception e) {
          System.out.println("Did not accept String: " + n + " => " + e);
        }
        try {
          m.setAccessible(true);
          m.invoke(c, new StringBuilder("StringBuilder of ").append(n));
        } catch (Exception e) {
          System.out.println("Did not accept StringBuilder: " + n + " => " + e);
        }
      }
      System.out.println("-----");
    }
  }
}

/* ==========================================
Output:

Lambda: regular invocation of accept(String)
Lambda: accept(Object)
Did not accept StringBuilder: accept(Object) => java.lang.reflect.InvocationTargetException
-----
Anonym: regular invocation of accept(String)
Anonym: accept(String)
Did not accept StringBuilder: accept(String) => java.lang.IllegalArgumentException: argument type mismatch
Anonym: accept(Object)
Did not accept StringBuilder: accept(Object) => java.lang.reflect.InvocationTargetException
-----
MyRegularClass: regular invocation of accept(String)
MyRegularClass: accept(Object)
Did not accept StringBuilder: accept(Object) => java.lang.reflect.InvocationTargetException
Did not accept String: get$Lambda(MyRegularClass) => java.lang.IllegalAccessException: Class com.example.foo.SomeClass can not access a member of class com.example.foo.SomeClass$$Lambda$2/1175962212 with modifiers "private static"
Did not accept StringBuilder: get$Lambda(MyRegularClass) => java.lang.IllegalArgumentException: argument type mismatch
-----
MyGenericClass: regular invocation of accept(String)
MyGenericClass: accept(Object)
Did not accept StringBuilder: accept(Object) => java.lang.reflect.InvocationTargetException
Did not accept String: get$Lambda(MyGenericClass) => java.lang.IllegalAccessException: Class com.example.foo.SomeClass can not access a member of class com.example.foo.SomeClass$$Lambda$3/617901222 with modifiers "private static"
Did not accept StringBuilder: get$Lambda(MyGenericClass) => java.lang.IllegalArgumentException: argument type mismatch
-----
*/
package com.example.foo;
导入静态java.util.Arrays.asList;
导入java.lang.reflect.Method;
导入java.util.function.Consumer;
公共类{
@功能接口
静态接口{
公共空白m(字符串s);
}
静态最终类MyRegularClass{
@SuppressWarnings(“静态方法”)
公共void m(字符串s){
System.out.println(“MyRegularClass:+s”);
};
}
静态最终类MyGenericClass{
公共空间m(T s){
System.out.println(“MyGenericClass:+s”);
};
}
公共静态void main(字符串[]args)引发异常{
消费者c1=(s)->{
System.out.println(“Lambda:+s”);
};
消费者c2=新消费者(){
公共无效账户