2012-10-17 35 views
11

Trong đoạn mã sau đây, có lẽ nó xuất hiện rằng nó nên ban hành một số lỗi biên dịch nhưng nó không:Sử dụng một tên lớp bên trong và một cái tên cùng một đối tượng trong Java

class Outer { 
    public static class Inner { 
     static String obj = "Inner"; 
    } 

    static Optional Inner = new Optional(); 
    //The (inner) class name and the object name are same. 
} 

class Optional { 
    String obj = "Optional"; 
} 

public class Main { 

    public static void main(String[] args) { 
     System.out.println(Outer.Inner.obj); 
     //Refers to the string inside the optional class 
    } 
} 

Lớp Outer có tĩnh lớp bên trong nó có tên là Inner. Ngoài ra, nó tuyên bố một đối tượng (tĩnh) của lớp Optional (static Optional Inner = new Optional();)

Đối tượng này và tên lớp (bên trong lớp Outer) giống nhau là Inner. Chương trình hiển thị Optional. Biểu thức duy nhất Outer.Inner.obj trong phạm vi main() được mong đợi sẽ hiển thị Inner nhưng không. Tuy nhiên, đầu ra thực tế là Optional là trường hợp của lớp Optional.

Một cách để hiển thị Inner là thay đổi tên đối tượng thành tên khác.

static Optional Inner1 = new Optional(); 

Từ đầu ra nó sẽ hiển thị, dường như tên đối tượng (hoặc một biến) được chọn thay vì một tên kiểu (lớp Inner) bởi vì họ có cùng tên. Trường hợp chính xác nào được áp dụng ở đây?

Trả lời

13

Paragraph 6.4.2 Đặc tả ngôn ngữ Java có một số thông tin về các quy tắc áp dụng trong trường hợp này.

Tên đơn giản có thể xảy ra trong các ngữ cảnh có thể được hiểu là tên của biến, loại hoặc gói. Trong những tình huống này, các quy tắc của §6.5 chỉ định rằng một biến sẽ được chọn tùy theo loại và rằng một loại sẽ được chọn tùy theo gói. Vì vậy, đôi khi có thể không thể tham khảo một loại có thể nhìn thấy hoặc khai báo gói thông qua tên đơn giản của nó. Chúng tôi nói rằng tuyên bố như vậy là bị che khuất.

Điều này đề cập đến đoạn 6.5 Determining the Meaning of a Name, giải thích chi tiết các quy tắc.

Trong ví dụ của bạn, Outer.Inner có thể tham chiếu đến loại của lớp lồng nhau có tên Inner hoặc biến thành viên tĩnh Inner. Các quy tắc nói biến sẽ được chọn trên loại.

3

Thực ra tên lớp là Outer $ Inner.

Lớp bên trong về cơ bản là bản hack được giới thiệu trong Java 1.1. JVM không thực sự có bất kỳ khái niệm nào về một lớp bên trong, và do đó trình biên dịch phải bóc nó. Trình biên dịch tạo ra lớpB "bên ngoài" của lớpA, nhưng trong cùng gói, và sau đó thêm tổng hợpaccessors/nhà thầu để nó cho phép A để có được quyền truy cập vào nó.

Thanh toán các bài sau:

Java inner class visibility puzzle

+0

+1 một câu trả lời rất hay! – GingerHead

+0

Chăm sóc downvoter để bình luận? – GingerHead

+0

Nó thực sự là một câu trả lời rất hay cho một câu hỏi chưa được hỏi ở đây. – LuGo

2

suy nghĩ của lớp bên đã thực sự có file java của riêng mình. Điều đó sẽ làm cho nó rõ ràng với bạn tại sao nó chọn biến trên lớp Nội.

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