Trong phần Run-Time Evaluation of Method References của ngôn ngữ Java Specification, nó được đề cập rằng:Runtime đánh giá biểu thức trong phương pháp Java tham chiếu
Vào lúc chạy, đánh giá của một biểu thức phương pháp tham chiếu là tương tự như đánh giá của một tạo lớp dụ biểu thức, trong khi hoàn thành bình thường tạo ra một tham chiếu đến một đối tượng. Việc đánh giá biểu thức tham chiếu phương thức khác biệt với việc gọi phương thức của chính nó.
Đầu tiên, nếu biểu thức tham chiếu phương thức bắt đầu bằng ExpressionName hoặc Primary, biểu thức con này được đánh giá. Nếu biểu thức con đánh giá là
null
, sốNullPointerException
được nâng lên và biểu thức tham chiếu phương thức hoàn thành đột ngột. Nếu biểu thức con hoàn thành đột ngột, biểu thức tham chiếu phương thức hoàn thành đột ngột vì cùng một lý do.
Và ExpressionName và Tiểu được định nghĩa trong method reference expression syntax:
MethodReference:
ExpressionName :: [TypeArguments] Identifier ReferenceType :: [TypeArguments] Identifier Primary :: [TypeArguments] Identifier super :: [TypeArguments] Identifier TypeName . super :: [TypeArguments] Identifier ClassType :: [TypeArguments] new ArrayType :: new
Tôi đã quan tâm bởi một phần tô đậm và muốn kiểm tra hành vi được đề cập bằng cách sử dụng mã bên dưới:
public class Test {
public static void main(String[] args) {
System.out.println("Testing...");
final Person p = null;
foo(p::getName); // I was expecting an NPE here
}
private static void foo(Supplier<String> supplier) {
System.out.println(supplier);
// supplier.get(); // uncommenting this causes an NPE, but not when evaluating
// the method reference, but rather when the method is invoked.
}
static class Person {
String getName() {
return "x";
}
}
}
Tuy nhiên, dòng foo(p::getName)
không ném NullPointerException. Tôi có hiểu sai câu nói trên từ JLS không? Nếu có, ai đó có thể giải thích thêm ý nghĩa của câu nói trên hoặc đưa ra một ví dụ mà nó sẽ xảy ra?
thú vị, tôi sẽ mong nó để ném ngoại lệ thực sự và tôi đã cố gắng thay đổi nó đến một biểu thức lambda (nghĩ rằng điều này chắc chắn sẽ phá vỡ), nhưng nó không. Câu hỏi hay – Eugene
Tôi đồng ý, theo thông số kỹ thuật, tham chiếu phương thức 'p :: getName' nên đã ném NPE. Đoán rằng họ đã không thêm xác nhận đó, vì vậy NPE được hoãn lại cho đến khi thực sự được sử dụng. Xem liên quan [JDK-8131323] (https://bugs.openjdk.java.net/browse/JDK-8131323). – Andreas
Có một [câu hỏi trước đó về nó] (https://stackoverflow.com/q/37681625/2711488), tuy nhiên, không có liên kết đến một báo cáo trong trình theo dõi lỗi Eclipse ở đó. Tôi yên tĩnh chắc chắn, tôi đã thấy một trong quá khứ… – Holger