代码之家  ›  专栏  ›  技术社区  ›  Tomas

Java 8如何推断lambdas参数类型

  •  3
  • Tomas  · 技术社区  · 8 年前

    NetServer server = vertx.createNetServer();
    server.listen(1234, "localhost", res -> {
      if (res.succeeded()) {
        System.out.println("Server is now listening!");
      } else {
        System.out.println("Failed to bind!");
      }
    });
    

    查阅以下文件: listen

    NetServer listen(int port,
                     String host,
                     Handler<AsyncResult<NetServer>> listenHandler)
    

    我的问题是JVM如何有机会推断通用数据类型,例如 Handler<AsyncResult<NetServer>> res ? 这对于像JavaScript这样做duck类型的语言来说似乎很好,但对于像Java这样做强类型的语言来说,这一点对我来说并不明显。如果我们使用匿名类而不是lambda,那么所有数据类型都将成为可能。

    --编辑-- 正如已经解释的@锆石,可能更好的例子从垂直。x文件如下:

    <T> void executeBlocking(Handler<Future<T>> blockingCodeHandler,
                             Handler<AsyncResult<T>> resultHandler)
    

    vertx.executeBlocking(future -> {
      // Call some blocking API that takes a significant amount of time to return
      String result = someAPI.blockingMethod("hello");
      future.complete(result);
    }, res -> {
      System.out.println("The result is: " + res.result());
    });
    

    其中类型不可用,因此只有方法在 Future AsyncResults 可以使用。

    1 回复  |  直到 8 年前
        1
  •  6
  •   Zircon    8 年前

    Netserver.listen Handler<AsyncResult<NetServer>> 作为其第三个参数。

    Handler 是一种具有一种方法的vertx功能接口 handle(E event) .在这种情况下, E AsyncResult<NetServer>

    在此处插入lambda使其取代 Handler.handle 因此,单一论点 res 必须是类型 异步结果(<NetServer> AsyncResult.succeeded 没有问题。

    简单来说:

    第三个论点是不可能的 listen 什么都不是 处理程序(<);异步结果(<NetServer>&燃气轮机; ,因此lambda必须提供类型为的参数 <AsyncResult<NetServer>> .

    关于在lambda中使用嵌套泛型,请考虑此类:

    public class myClass<T> {
        public void doSomething(int port, String host, Handler<AsyncResult<T>> handler) {
            //Stuff happens
        }
    }
    

    呼叫 此方法。我们需要一个MyClass的实例,这也意味着我们需要在调用之前声明泛型类型 doSomething

    MyClass<String> myObj = new MyClass<String>();
    result = myObj.doSomething(port, host, res -> {
      if (res.succeeded()) {
        System.out.println("I did a thing!");
      } else {
        System.out.println("I did not do a thing!");
      }
    });
    

    物件 作为一个 AsyncResult<String> 因为 T String AsyncResult 一串 方法如下 toUpperCase 等等。

    如果你最终引用了一个 MyClass<?> 并试图类似地利用lambda, 物件 AsyncResult<?> (您可以打开 ? 类型,但由于在编译时无法知道它的类型,您不得不将其视为 Object

    如果我们在声明过程中没有声明泛型类型,我们将收到一条警告,并且由于原始键入,此代码将无法工作(感谢Holger):

    MyClass myObj = new MyClass(); //Generic type warning
    result = myObj.doSomething(port, host, res -> {
      if (res.succeeded()) { //Error
        System.out.println("I did a thing!");
      } else {
        System.out.println("I did not do a thing!");
      }
    });
    

    myObj MyClass , 物件 对象 (不是 AsyncResult<Object> succeeded 在上面。

    通过这种方式,在不确切知道使用lambda的参数推断的类型的情况下,不可能使用lambda。

    MyClass.<MyType>doSomethingStatic 以便在声明lambda之前声明类型,以便可以推断类型。

    简单来说: