2011-10-27 25 views
9

Tôi đã xem qua tính năng "lạ" sau ngày nay - nếu bạn có một tham chiếu đến một đối tượng từ lớp A trong cơ thể của lớp A, bạn có thể truy cập vào các lĩnh vực cá nhân của đối tượng này - ví dụ:Truy cập trường tư nhân Java có thể khi có tham chiếu?

public class Foo{ 
    private int bar; 
    private Foo foo; 
    public void f() 
    { 
     if(foo.bar == bar) // foo.bar is visible here?! 
     { 
      // 
     } 
    } 
} 

Bất cứ ai cũng có một lời giải thích tốt về điều này?

+2

Tính năng này khá hữu ích khi bạn phải viết phương thức 'equals'. –

+2

Câu hỏi tương tự như: http://stackoverflow.com/questions/2126984/why-is-the-access-to-a-private-field-not-forbidden, http://stackoverflow.com/questions/4340129/accessing -private-field-in-java, http://stackoverflow.com/questions/312168/java-private-field-visibility –

Trả lời

19

Công cụ sửa đổi truy cập hoạt động ở cấp lớp, không phải ở cấp độ cá thể: tất cả mã trong cùng một lớp đều có thể truy cập các thành viên riêng tư của tất cả các phiên bản của lớp.

Không có gì đặc biệt lạ về nó.

3

Vì f() là thành viên của Foo, nó có đặc quyền truy cập các thành viên riêng tư của Foo. Tôi không ngạc nhiên.

+0

điều là lý do tại sao chúng ta có thể truy cập foo.bar khi foo là một thể hiện khác của lớp Foo và thanh là một lĩnh vực riêng tư – asenovm

+1

@iLate: Vì đó là cách ngôn ngữ được chỉ định ... –

+0

@iLate: Tôi đoán các nhà thiết kế chỉ cần tuân theo hành vi của C++. – LLS

0

Vì tư nhân không có nghĩa là riêng tư của nó từ bên ngoài đối tượng nhưng riêng tư từ các lớp khác. Bạn đang ở bên trong của Foo, do đó bạn có thể thấy thanh.

Bằng cách đó, các Nhà xây dựng riêng tư hoạt động trong Singletons, v.v.

0

Các từ khóa đó là định hướng lớp, không hướng đối tượng. Vì vậy, nó chỉ trông và nhìn thấy "oh huh, một đối tượng của lớp Foo đang cố gắng truy cập một đối tượng riêng trên Foo. Vâng, đó là tốt".

5

Nó được dự định theo cách này.

Trích dẫn các Java Language Specification:

Một thành viên (lớp, giao diện, lĩnh vực, hoặc phương pháp) của một tài liệu tham khảo (class, interface, hoặc mảng) đánh máy hoặc viết một constructor của một loại lớp có thể truy cập chỉ khi loại có thể truy cập và thành viên hoặc constructor được khai báo cho phép truy cập:

  • ...
  • (nếu không,) nếu hội viên hoặc constructor được khai báo là private, sau đó truy cập được phép khi và chỉ khi nó xảy ra trong vòng cơ thể của cla cấp cao nhất ss (§7.6) kèm theo tuyên bố của thành viên.
  • ...
+2

+1 cho tham chiếu JLS. –

1

Nó có ý nghĩa nếu bạn xem xét ý định của modifier 'tư nhân' để ẩn chi tiết thực hiện.

Hãy thử suy nghĩ về điều này "điều này nên riêng tư đối với lớp này" (trong Java tương đương với "điều này nên riêng tư đối với tệp nguồn này") thay vì "điều này nên riêng tư đối với trường hợp này".

0

@Michael câu trả lời là chính xác. Hành vi này giống nhau đối với .NET cho mã số @asenovm.

Ngoài ra, cũng tương tự cho các lớp bên trong cũng như cho Java. Mặc dù bạn xác định một biến là riêng tư, bạn có thể truy cập nó. Tôi ngạc nhiên khi tôi gặp phải lúc đầu vì nó khác với C#.

public class WrapperClass 
{ 

    public static class NotThreadsafe { 
     private int x = 0; 
     //....   
    } 

    public static void main(String[] args) {   
    final NotThreadsafe nts=new NotThreadsafe(); 
    int x = nts.x ; // !!! THIS IS ACCESSIBLE AS WELL FOR JAVA BUT NOT.NET 
    } 
} 

Điều này không giống với C# các lớp lồng nhau. Nếu bạn dán mã này vào studio trực quan, nó sẽ không hoạt động. Trình biên dịch cho các cấp độ truy cập.

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