2015-05-19 31 views
6

Dưới đây là mẫu mã mà không biên dịch trong Java 8 (1.8.0_40) nhưng biên dịch trong Eclipse 4.4 JDT biên dịch độc lập (Bundle-Version: 3.10.0.v20140604-1726) và chạy thành công:Phương thức tham chiếu phương thức đến các hàm tạo lớp địa phương trong Java 8 hoạt động như thế nào?

import java.util.Arrays; 

import org.junit.Test; 

import static org.junit.Assert.assertEquals; 

/** 
* Test method references to local class constructors. 
*/ 
public class LocalClassTest { 

    public long sumOfLengths(String[] input) { 
    class Sum { 
     final long value; 

     Sum(long value) { 
     this.value = value; 
     } 

     Sum(Sum left, Sum right) { 
     this.value = left.value + right.value; 
     } 

     Sum add(String s) { 
     return new Sum(value + s.length()); 
     } 
    } 

    return Arrays.stream(input) 
       .reduce(new Sum(0), Sum::add, Sum::new) 
       .value; 
    } 

    static String[] input = 
     { 
      "a", "ab", "abc" 
     }; 

    @Test 
    public void localClassConstructorMethodRefs() { 
    assertEquals(sumOfLengths(input), 6); 
    } 
} 

javac spits ra thông báo lỗi sau:

Error:(32, 25) java: incompatible types: cannot infer type-variable(s) U 
    (argument mismatch; invalid constructor reference 
     cannot access constructor Sum(Sum,Sum) 
     an enclosing instance of type LocalClassTest is not in scope) 

Đọc qua JLS 15.9.2 (Xác định Instances Kèm theo) và 15.13.3 (Run-Time đánh giá Phương pháp Tài liệu tham khảo), tôi không thể hiểu tại sao điều này sẽ không biên dịch và thông báo lỗi có vẻ hoàn toàn sai vì tôi có thể tạo một phiên bản Sum theo cách thủ công trong cùng một phương pháp tốt.

Tôi đã tìm thấy câu hỏi trước Constructor reference for inner class fails with VerifyError at runtime dường như có liên quan và vấn đề JDK được liên kết ở đó (https://bugs.openjdk.java.net/browse/JDK-8037404) cho biết một loạt các vấn đề về trình biên dịch trong lĩnh vực này; có lẽ đây là một ví dụ khác của một vấn đề tổng quát hơn. Tuy nhiên, tôi không chắc tôi đang đọc đúng thông số; điều này có thể hoạt động theo cách khác không?

+2

Đó là cùng một vấn đề như được mô tả trong [câu hỏi này] (http://stackoverflow.com/q/26258412/2711488), tuy nhiên, không có giải pháp nào được nêu ra. Vâng, ngoài việc sử dụng biểu thức lambda thay vì tham chiếu phương thức… – Holger

Trả lời

4

Điều này trông giống như một lỗi trình biên dịch đối phó với các lớp địa phương (khai báo lớp trong một phương thức). Nếu bạn thay đổi thành một lớp bên trong (di chuyển khai báo lớp bên ngoài phương thức), thì nó hoạt động tốt. Bạn có thể thay đổi nó thành một lớp tĩnh cùng một lúc, điều này sẽ làm giảm đáng kể chi phí.

(Lớp bên trong và lớp cục bộ đều có tham chiếu ngầm định đến lớp chứa, nghĩa là hàm tạo có tham số đầu tiên "ẩn", bạn có thể thấy bằng javap. Tôi nghi ngờ trình biên dịch biết bù cho tham số ẩn này khi sử dụng Sum::new cho một lớp bên trong, nhưng logic chỉ là thiếu để làm tương tự cho một lớp học địa phương.)

+0

Phải; vì lợi ích của ví dụ, tôi vừa mới sử dụng một lớp địa phương đơn giản. Trong trường hợp thực tế của tôi, tôi có một liên quan nhiều hơn mà không yêu cầu quyền truy cập vào các tham số phương thức, và tôi muốn tránh sự gián đoạn trong mã cần thiết cho workaround. – Cagatay

+1

Vì lỗi này, tôi không nghĩ có cách nào để tránh điều đó, vì vậy tôi nghĩ tùy chọn tốt nhất của bạn là gửi báo cáo lỗi và áp dụng giải pháp thay thế tại đây. –

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