2015-05-07 14 views
5

Sau đây sẽ không biên dịch:Không thể tham khảo lớp bên từ một bối cảnh tĩnh, nhưng chỉ khi lớp bên ngoài là chung chung

class Outer<T> { 
    class Inner { 

    } 

    static class Nested { 
     Inner inner; // Error: Outer.this cannot be referenced from a static context 
    } 
} 

Tuy nhiên, nếu tôi loại bỏ <T>, nó biên dịch. Tại sao mâu thuẫn?

Ngoài ra, nếu tôi nói Outer.Inner inner;, thay vì Inner inner;, nó sẽ biên dịch. Một lần nữa, tại sao sự không thống nhất?

Tôi mong gặp lỗi trong cả hai trường hợp hoặc không có lỗi nào. Bất cứ ai có thể giải thích những gì đang xảy ra?

+2

Vâng, bạn có thể tham chiếu 'T' trong' Bên trong', ví dụ: biến thành viên. Làm thế nào 'Nested' sẽ biết bất cứ điều gì về loại đó nếu' Outer' là chung? –

+1

Thay đổi dòng đó thành 'Outer . Bên trong bên trong;' hoặc một số chuyên môn khác của 'T' –

Trả lời

4

Tại sao không nhất quán?

Tôi có thể nói đây không phải là mâu thuẫn. Điều này về cơ bản là một vấn đề của sự hiểu biết về Generics. Xét đoạn mã sau (mã sửa đổi của bạn):

class Outer<T> { 
    class Inner{ 
     T t;//Added this extra line 
    } 

    static class Nested { 
     Inner inner; 
    } 
} 

Trong ví dụ trên đây là hơi tương tự như những gì bạn đã viết duy nhất tôi đã thêm một biến mới t loại T đó là thuốc generic của Outer lớp trong lớp Inner. Bây giờ trong ví dụ trên sẽ không biên dịch vì có tham chiếu không tĩnh hoặc thời gian chạy trong lớp Inner, vì vậy, khi bạn khai báo Inner trong lớp tĩnh Nested trình biên dịch JAVA không biết loại T, chỉ được khai báo trong thời gian chạy, vì vậy bạn gặp lỗi. Nhưng trong trường hợp của bạn, bạn đã không làm gì như thế nhưng trình biên dịch vẫn không biết liệu có cái gì đó như thế có hiện diện hay không. Vì vậy, nó cung cấp cho các lỗi.

Hiện tại trong trường hợp thứ hai, bạn đã xóa số chung T khỏi tuyên bố lớp học của Outer. Vì vậy, không có khả năng khai báo biến t trong lớp Inner do đó không có lỗi.

Trong trường hợp thứ ba bạn khai báo Outer.Inner cho loại biến inner và được biên dịch thành công.Tại đây trình biên dịch được xem là OuterLOẠI RAW. Nhưng nên tránh loại khai báo kiểu thô này. Vì vậy, nó sẽ tốt hơn nếu viết:

Outer<?>.Inner inner; 

Dưới đây trình biên dịch Java coi Outer thực hiện bất kỳ đối tượng như các thông số đó sẽ kế thừa Object.

+0

Bạn nghĩ rằng bạn đã học được tất cả về các lớp bên trong và Generics nhưng sau đó bạn đi qua một cái gì đó như thế này ... Tôi tự hỏi những gì khác tương tác kỳ lạ tôi đã bỏ qua. Giải thích tuyệt vời! – Lii

1
class OuterClass { 

    ... 
    static class StaticNestedClass { 
     ... 
    } 
    class InnerClass { 
     ... 
    } 
} 

Lớp lồng nhau là thành viên của lớp kèm theo. Các lớp lồng nhau không tĩnh (các lớp bên trong) có quyền truy cập vào các thành viên khác của lớp bao quanh, ngay cả khi chúng được khai báo riêng. Các lớp lồng nhau tĩnh không có quyền truy cập vào các thành viên khác của lớp kèm theo.

Static Nested Classes 

Giống như với các phương thức và biến lớp, lớp lồng nhau được liên kết với lớp ngoài của lớp. Và giống như các phương thức lớp tĩnh, một lớp lồng nhau tĩnh không thể tham chiếu trực tiếp đến các biến mẫu hoặc các phương thức được định nghĩa trong lớp kèm theo của nó: nó có thể sử dụng chúng chỉ thông qua một tham chiếu đối tượng.

lớp lồng nhau tĩnh được truy cập bằng cách sử dụng tên lớp kèm theo:

OuterClass.StaticNestedClass 

Ví dụ, để tạo ra một đối tượng cho lớp lồng nhau tĩnh, sử dụng cú pháp sau:

OuterClass.StaticNestedClass nestedObject = 
new OuterClass.StaticNestedClass(); 

Để biết thêm thông tin xem nhấp chuột bên dưới:

https://docs.oracle.com/javase/tutorial/java/javaOO/nested.html

+2

Giải thích tốt về các lớp bên trong và tĩnh, nhưng nó không giải thích được vấn đề trong câu hỏi. – Lii

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