2015-11-12 39 views
7
import java.util.concurrent.Callable; 

public class AdvancedLambda { 

    static void invoke(Runnable r){ 
     r.run(); 
    } 

    static Object invoke(Callable c) throws Exception { 
     return c.call(); 
    } 

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

     String s = (String) invoke(() -> true); 
     System.out.println(s); 
    } 
} 

Có ai giúp tôi hiểu điều này không? Tôi đã có ấn tượng rằng chúng ta chỉ có thể sử dụng các biểu thức lamba trong Java 8 chỉ khi chúng ta thực hiện một giao diện và ghi đè các phương thức của nó (thay thế các lớp ẩn danh bằng các biểu thức Lambda).Biểu thức Lambda trong Java8

Ngoài ra, trong trường hợp nào, phương pháp invoke(Runnable r) sẽ được gọi?

Trả lời

7

Trong dòng sau

String s = (String) invoke(() -> true); 

Nó thực sự là invoke(Callable) đó là được gọi. Lý do là:

  • () -> true là biểu thức lambda không có tham số chính thức bằng 0 và trả lại kết quả.
  • Chữ ký như vậy (tham số 0, kết quả đơn) tương thích với phương thức chức năng call() của giao diện Callable. Lưu ý rằng giao diện không cần phải có chú thích @FunctionalInterface, nó chỉ cần có một phương thức trừu tượng duy nhất.

Nếu bạn muốn gọi invoke(Runnable) thay vào đó, bạn sẽ cần phải tạo ra một lambda đó là tương thích với một phương pháp chức năng mà có zero tham số và trả về không có kết quả (ví dụ phù hợp với chữ ký của run()). Một cái gì đó như thế này:

invoke(() -> System.out.println("foo")); 

Chỉ in foo khi chạy.

5

chỉ khi chúng ta Thực hiện một giao diện và ghi đè phương thức của nó

Đó là, nhiều hơn hoặc ít hơn, những gì bạn làm ở đây. Không phải phương thức s, nhưng chỉ một phương pháp: call(). Phần () -> true này là việc bạn triển khai Callable#call().

Nói cách khác, dòng này:

String s = (String) invoke(() -> true); 

sẽ là hoàn toàn tương đương với điều này một:

String s = (String) invoke(new Callable() { 
     @Override 
     public Object call() throws Exception { 
      return true; 
     } 
    });  
7

Biểu thức lambda cung cấp triển khai cho giao diện chức năng. Đây là những gì đoạn mã của bạn làm.

Cuộc gọi của bạn tới invoke chuyển biểu thức lambda không có đối số trả về giá trị (trong trường hợp của bạn là boolean). Do đó, nó khớp với số Object invoke(Callable c) và không phải là void invoke(Runnable r) (vì phương thức 'call có giá trị trả về trong khi phương thức run của không trả lại bất kỳ giá trị nào).

invoke(() -> {System.out.println("something");}); 

sẽ gọi void invoke(Runnable r), vì trong trường hợp này biểu thức lambda không có loại trả về.

0

Biểu thức Lambda là một cách khác để viết một thể hiện của lớp ẩn danh, để tạo một thể hiện của lớp ẩn danh dễ viết hơn. Trong JVM, nó sẽ không chiếm nhiều bộ nhớ so với việc tạo đối tượng java bình thường với new (thực thi các biến tĩnh, các khối tĩnh, nạp các lớp từ toàn bộ hệ thống phân cấp).

enter image description here

Lambda biểu hiện cú pháp:

(params) -> expression to implement a @FunctionalInterface 

Trong trường hợp thử nghiệm của bạn: String s = (String) invoke(() -> true); biểu thức có kiểu trả về true không có đối số. Vì vậy, RunnableFunctionalInterface không khớp với biểu thức lambda vì nó có thuộc tính void run(). Nó khớp với CallableFuncationalInterface sử dụng
V call().

Biểu thức lambda hoạt động như thế nào?
Nó có thể giống như các biểu thức lambda chỉ là cú pháp đường cho các lớp bên trong vô danh, nhưng có nhiều cách tiếp cận thanh lịch hơn. Giải thích đơn giản nhất là: biểu thức lambda được biểu diễn bằng một phương thức mới, và nó được gọi vào thời gian chạy bằng cách sử dụng tính năng động.

Source Code:

class LambdaExample { 

    public void abc() { 
     Runnable r =() -> { 
      System.out.println("hello"); 
     } 
     r.run(); 
    } 

} 

Bytecode tương đương:

class LambdaExample { 

    public void abc() { 
     Runnable r = <lambda$1 as Runnable instance>; 
     r.run(); 
    } 

    static void lambda$1() { 
     System.out.println("hello"); 
    } 

} 

Bên trong JVM, có một nhà máy lambda tạo ra một thể hiện của giao diện chức năng (ví dụ Runnable) từ tạo ra phương thức lambda (ví dụ lambda $ 1).

biểu thức Lambda là rất lớn, và thậm chí có công cụ tuyệt vời hơn trong Java 8...

+0

Bắt điểm của bạn ở đây .. nhưng không hiểu phiên bản mã byte nhiều! – Ashu

+0

Nó không phải là một cách khác để tạo ra một lớp vô danh. Nó giống như một sự thay thế cho các lớp ẩn danh trong các trường hợp cụ thể. – shmosel

0

Hãy nhìn vào bên dưới ví dụ.

import javafx.beans.DefaultProperty; 
import jdk.nashorn.internal.codegen.CompilerConstants; 

import java.util.concurrent.Callable; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 
import java.util.concurrent.Future; 

/** 
* Created by KUMAJYE on 13/09/2016. 
*/ 
public class ThreadMonitor { 

private static int noOfThreads = 0; 


public static void main(String[] args) { 
    ThreadModel threadModel; 
    noOfThreads = Integer.parseInt(args[0]); 
    if (noOfThreads > 0) { 
     threadModel = getThreadingModelForCallsInCallingThread(); 
    } else { 
     threadModel = getAsynchThreadingModel(); 
    } 

} 

public static ThreadModel getThreadingModelForCallsInCallingThread() { 
    ExecutorService executor = Executors.newFixedThreadPool(noOfThreads); 
    return (r) -> executor.submit(r); 
} 


public static ThreadModel getAsynchThreadingModel() { 
    // do execution on same Thread or separate Thread. 
    // or 
    // r.run(); 
    return (r) -> new Thread(r).start(); 
} 

interface ThreadModel { 

    void invoke(Runnable r); 
} 

}

Các vấn đề liên quan