2012-05-28 19 views
16

Đây là một ví dụ đơn giản của một số mã mà biên dịch sử dụng Java 6, nhưng không biên dịch trong Java 7.Những thay đổi trong việc tiếp cận các biến cho các lớp học chung trong Java 7

public class Test<T extends Test> { 

    private final int _myVar; 

    public Test(int myVar) { 
    _myVar = myVar; 
    } 

    public int get(TestContainer<T> container){ 
    T t = container.get(); 
    return t._myVar; 
    } 

    private static class TestContainer<T extends Test> { 
    private final T _test; 
    private TestContainer(T test) { 
     _test = test; 
    } 
    public T get(){ 
     return _test; 
    } 
    } 
} 

Trong Java 7, nó không biên dịch theo phương pháp get(TestContainer<T> container), với lỗi:

error: _myVar has private access in Test

Tôi không hiểu tại sao điều này không còn biên dịch - theo ý tôi. Biến số t thuộc loại T, phải mở rộng Test. Nó đang cố truy cập vào trường _myVar của phiên bản Test từ bên trong lớp Test.

Thật vậy, nếu tôi thay đổi phương pháp get(TestContainer<T> container) đến những điều sau đây, nó biên dịch (không có cảnh báo):

public int get(TestContainer<T> container){ 
    Test t = container.get(); 
    return t._myVar; 
} 
  • Tại sao điều này không còn biên dịch?
  • Đây có phải là lỗi trong Java 6 không? Nếu vậy tại sao?
  • Đây có phải là lỗi trong Java 7 không? bình luận

Tôi đã có một google và tìm kiếm trong cơ sở dữ liệu lỗi Oracle, nhưng đã không tìm thấy bất cứ điều gì về vấn đề này ...

+5

Đây là một lỗi trong Java 6: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7022052 – pingw33n

+0

@ pingw33n, bạn nên gửi đó như là một câu trả lời. –

+0

@ pingw33n, và sau đó tôi có thể chấp nhận nó ... mặc dù nếu có ai hiểu rõ hơn về JLS có thể giải thích phần 'Đánh giá' của báo cáo lỗi, tôi cũng đánh giá cao điều đó. – amaidment

Trả lời

9

§4.9 ... Then the intersection type has the same members as a class type (§8) with an empty body, direct superclass Ck and direct superinterfaces T1', ..., Tn', declared in the same package in which the intersection type appears.

Từ sự hiểu biết của tôi về một phần JLS, trường hợp của bạn với một loại biến <T extends Test> tạo giao điểm sau:

package <the same as of Test>; 

class I extends Test {} 

Vì vậy khi bạn truy cập các thành viên của các loại T bạn thực sự truy cập vào các thành viên của ngã tư nhập I. Vì các thành viên riêng không bao giờ được thừa kế bởi các kiểu con truy cập thành viên đó không thành công với lỗi biên dịch. Trên truy cập Mặt khác để gói-tư nhân (mặc định) và các thành viên bảo vệ được cho phép bởi thực tế các ngã tư là

... declared in the same package in which the intersection type appears.

0

Xem @ pingw33n cho câu trả lời, nhưng cách để sửa lỗi này là để loại bỏ các tham số chung trên lớp lồng nhau. Trừ khi bạn có một trường hợp sử dụng trong đó T bên trong và bên ngoài có thể khác nhau, chúng là thừa. Tất cả những gì họ đang làm là gây ra sự đau buồn này.

+0

Bạn có gợi ý làm cho nó đơn giản: 'lớp tĩnh private TestContainer'? Vì lớp bên trong tĩnh, bạn không thể (trong các từ ngắn gọn của trình biên dịch) * tạo một tham chiếu tĩnh đến kiểu T * không tĩnh. –

+0

Tôi có một trường hợp sử dụng - tương đương với TestContainer thực sự là một lớp riêng biệt hoàn toàn - nhưng đây chỉ là một SSCCE để chứng minh vấn đề trình biên dịch mà tôi đang phải đối mặt. – amaidment

0

Một cách giải quyết của việc này là để cast trường hợp tổng quát cho lớp siêu kiểu bê tông mà tuyên bố lĩnh vực tư nhân, ví dụ

public int get(TestContainer<T> container){ 
    T t = container.get(); 
    return ((Test) t)._myVar; 
} 
Các vấn đề liên quan