2017-04-20 13 views
45

Tôi đang đấu tranh để hiểu tại sao đoạn mã sau biên dịch:Tại sao phương pháp này tham chiếu biên dịch chuyển nhượng?

public class MethodRefs { 

    public static void main(String[] args) { 
     Function<MethodRefs, String> f; 

     f = MethodRefs::getValueStatic; 

     f = MethodRefs::getValue; 
    } 

    public static String getValueStatic(MethodRefs smt) { 
     return smt.getValue(); 
    } 

    public String getValue() { 
     return "4"; 
    } 

} 

tôi có thể thấy lý do tại sao việc chuyển nhượng đầu tiên là hợp lệ - getValueStatic rõ ràng phù hợp với quy định Function loại (nó chấp nhận một đối tượng MethodRefs và trả về một String), nhưng cái thứ hai cản trở tôi - phương pháp getValue không chấp nhận đối số, vậy tại sao nó vẫn hợp lệ để gán nó cho f?

+1

Bản sao có thể có của [lambda với các phương thức không tĩnh trong Java 8] (http://stackoverflow.com/questions/25784337/lambda-with-non-static-methods-in-java-8) –

+1

Ngoài ra [: : (dấu hai chấm) toán tử trong Java 8] (http://stackoverflow.com/questions/20001427/double-colon-operator-in-java-8/22245383#22245383) và [Sử dụng dấu hai chấm - sự khác biệt giữa tĩnh và tham chiếu phương pháp không tĩnh] (http://stackoverflow.com/questions/34982972/use-of-double-colons-difference-between-static-and-non-static-method-reference?noredirect=1&lq=1) –

Trả lời

50

Thứ hai một

f = MethodRefs::getValue; 

cũng giống như

f = (MethodRefs m) -> m.getValue(); 

Đối với phương pháp không tĩnh luôn luôn có một cuộc tranh cãi ngầm được biểu diễn dưới dạng this trong callee.

LƯU Ý: Việc triển khai hơi khác ở cấp mã byte nhưng cũng giống như vậy.

+24

Lưu ý rằng đối số ngầm định có thể được làm rõ ràng (như của Java 8): 'public String getValue (MethodRefs this)' là hợp pháp và giống hệt với 'public getValue String()'. – Pokechu22

+0

@ Pokechu22 Tôi không biết điều đó.Có tên cho cấu trúc đó không? – immibis

+5

@immibis: [thông số] (http://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.4.1) (§8.4.1) gọi nó là "thông số người nhận" theo như tôi có thể nói. – Pokechu22

5

Đối với phương pháp không tĩnh, loại this được xem là ngầm định là loại đối số đầu tiên. Vì nó thuộc loại MethodRefs, các loại kiểm tra.

9

Một phương pháp không tĩnh về cơ bản có tham chiếu this của nó dưới dạng một loại đối số đặc biệt. Thông thường, đối số được viết theo một cách đặc biệt (trước tên phương thức, thay vì nằm trong dấu ngoặc đơn sau nó), nhưng khái niệm thì giống nhau. Phương thức getValue lấy một đối tượng MethodRefs (this) và trả về một chuỗi, vì vậy nó tương thích với giao diện Function<MethodRefs, String>.

9

Cho phép xác thịt nó ra một chút:

import java.util.function.Function; 

public class MethodRefs { 

    public static void main(String[] args) { 
    Function<MethodRefs, String> f; 


    final MethodRefs ref = new MethodRefs(); 

    f = MethodRefs::getValueStatic; 
    f.apply(ref); 
    //is equivalent to 
    MethodRefs.getValueStatic(ref); 

    f = MethodRefs::getValue; 
    f.apply(ref); 
    //is now equivalent to 
    ref.getValue(); 
    } 

    public static String getValueStatic(MethodRefs smt) { 
    return smt.getValue(); 
    } 

    public String getValue() { 
    return "4"; 
    } 
} 
6

Trong Hướng dẫn Java nó được giải thích rằng có 4 loại khác nhau của tài liệu tham khảo phương pháp:

  1. tham chiếu đến một phương pháp tĩnh
  2. tài liệu tham khảo cho một phương pháp thể hiện của một đối tượng cụ thể
  3. reference to an instance method of an arbitrary object of a particular type
  4. r eference đến một constructor

trường hợp của bạn là # 3, có nghĩa là khi bạn có một thể hiện của MethodRef ví dụ: ref, gọi apply trên chức năng của bạn f sẽ tương đương với String s = ref.getValue().

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