Tại sao chúng ta không thể có phương thức tĩnh trong lớp bên trong (không tĩnh)?


142

Tại sao chúng ta không thể có phương thức tĩnh trong một lớp bên trong không tĩnh?

Nếu tôi làm cho lớp bên trong tĩnh nó hoạt động. Tại sao?


4
Bởi vì bây giờ Java là COBOL cũ :)
SES

Điểm mấu chốt là: vì họ chưa thực hiện nó.
intrepidis

1
"Nội tâm không tĩnh" là một tautology.
Hầu tước Lorne

Nếu bạn không muốn hiển thị lớp bên trong của mình cho người khác và hy vọng nó chứa các phương thức tĩnh, bạn có thể đặt các bộ sửa đổi cả "riêng tư" và "tĩnh" trên lớp bên trong.
Willie Z

Một lớp bên trong là theo định nghĩa không tĩnh. Bạn có thể có một lớp thành viên / lồng nhau tĩnh và một lớp thành viên / lồng không tĩnh. Thứ hai cũng được gọi là một lớp bên trong. (Tham khảo: phần 8.1.3 của JLS nói " Lớp bên trong là lớp lồng nhau không được khai báo rõ ràng hoặc ngầm định static.")
Erwin Bolwidt

Câu trả lời:


111

Bởi vì một thể hiện của một lớp bên trong được liên kết ngầm với một thể hiện của lớp bên ngoài của nó, nó không thể định nghĩa bất kỳ phương thức tĩnh nào. Do một lớp lồng tĩnh không thể tham chiếu trực tiếp đến các biến thể hiện hoặc các phương thức được định nghĩa trong lớp kèm theo của nó, nên nó chỉ có thể sử dụng chúng thông qua một tham chiếu đối tượng, nên việc khai báo các phương thức tĩnh trong một lớp lồng tĩnh là an toàn.


7
Tôi biết một lớp bên trong được liên kết với một thể hiện của lớp bên ngoài và tôi biết rằng thật vô ích khi chúng ta có thể khai báo các thành viên tĩnh trong một lớp bên trong nhưng tôi vẫn hỏi tại sao một lớp bên trong không thể khai báo các thành viên tĩnh?
Kareem

15
Trong C ++ bạn có thể có, vì vậy đây là một lỗi trong ngôn ngữ Java.
Thuốc chống trầm cảm công nghiệp

39
Lỗi từ ... Tôi không nghĩ từ đó có nghĩa là những gì bạn nghĩ nó có nghĩa.
Seth Nelson

24
Một cụm từ thích hợp hơn sẽ là 'gây phiền nhiễu như một người mẹ'. Không hiểu tại sao Java không cho phép điều này. Đôi khi, tôi muốn một lớp bên trong sử dụng các thuộc tính của lớp cha, nhưng giữ các phương thức tĩnh để không gian tên tốt hơn. Có một cái gì đó vốn đã sai với điều này? :(
Angad

6
Chính xác. Tôi muốn viết một lớp bên trong tiện ích. Một số phương thức của nó sẽ có lợi khi truy cập vào lớp bên ngoài, vì vậy tôi không thể làm cho nó tĩnh, nhưng một số phương thức của nó chỉ là các hàm tiện ích. Tại sao tôi không thể gọi A.B.sync(X)hoặc thậm chí (từ trong A) B.sync(x)?
Edward Falk

44

Không có nhiều điểm để cho phép một phương thức tĩnh trong lớp bên trong không tĩnh; Làm thế nào bạn sẽ truy cập nó? Bạn không thể truy cập (ít nhất là ban đầu) một thể hiện của lớp bên trong không tĩnh mà không thông qua một thể hiện của lớp bên ngoài. Không có cách hoàn toàn tĩnh để tạo một lớp bên trong không tĩnh.

Đối với một lớp bên ngoài Outer, bạn có thể truy cập một phương thức tĩnh test()như thế này:

Outer.test();

Đối với một lớp bên trong tĩnh Inner, bạn có thể truy cập phương thức tĩnh của nó innerTest()như sau:

Outer.Inner.innerTest();

Tuy nhiên, nếu Innerkhông phải là tĩnh, bây giờ không có cách hoàn toàn tĩnh để tham chiếu phương thức innertest. Các lớp bên trong không tĩnh được gắn với một thể hiện cụ thể của lớp bên ngoài của chúng. Một hàm khác với một hằng số, trong đó một tham chiếu đến Outer.Inner.CONSTANTđược đảm bảo không rõ ràng theo cách mà một hàm gọi Outer.Inner.staticFunction();không phải là. Giả sử bạn có Inner.staticFunction()cuộc gọi getState()đó, được xác định trong Outer. Nếu bạn cố gắng gọi hàm tĩnh đó, bây giờ bạn có một tham chiếu mơ hồ đến lớp bên trong. Đó là, trong trường hợp nào của lớp bên trong, bạn gọi hàm tĩnh? Nó quan trọng. Xem, không có cách thực sự tĩnh để tham chiếu phương thức tĩnh đó, do tham chiếu ngầm đến đối tượng bên ngoài.

Paul Bellora là chính xác rằng các nhà thiết kế ngôn ngữ có thể đã cho phép điều này. Sau đó, họ sẽ phải không cho phép bất kỳ quyền truy cập nào vào tham chiếu ngầm đến lớp bên ngoài trong các phương thức tĩnh của lớp bên trong không tĩnh. Tại thời điểm này, giá trị của lớp này là gì nếu bạn không thể tham chiếu lớp bên ngoài, ngoại trừ tĩnh? Và nếu truy cập tĩnh là tốt, thì tại sao không khai báo toàn bộ lớp tĩnh bên trong? Nếu bạn chỉ đơn giản làm cho lớp bên trong tĩnh, thì bạn không có tham chiếu ngầm đến lớp bên ngoài và bạn không còn có sự mơ hồ này nữa.

Nếu bạn thực sự cần các phương thức tĩnh trên một lớp bên trong không tĩnh, thì có lẽ bạn cần phải suy nghĩ lại về thiết kế của mình.


6
-1 Tôi phải không đồng ý với góc bạn chụp ở đây. Chắc chắn chúng ta có thể tham chiếu một loại lớp bên trong, ví dụ Outer.Inner i = new Outer().new Inner();Ngoài ra, các lớp bên trong được phép khai báo các hằng số tĩnh theo JLS §15.28.
Paul Bellora

2
Có, các lớp bên trong có thể khai báo hằng số tĩnh . Điều đó không có gì để làm với các phương thức tĩnh! Mặc dù bạn có thể tham khảo một phương thức tĩnh không tĩnh, nhưng điều này không được khuyến khích. Tất cả các công cụ chất lượng mã phàn nàn ở loại tham chiếu đó và vì lý do tốt. Và bạn đã bỏ lỡ quan điểm của tôi. Tôi không bao giờ nói không có cách nào để tham chiếu một lớp bên trong tĩnh. Tôi đã nói rằng không có cách STATIC để tham chiếu phương thức tĩnh của một lớp bên trong của lớp bên ngoài không tĩnh. Vì vậy, không có cách PROPER để tham chiếu nó.
Eddie

25
"Không có nhiều điểm để cho phép một phương thức tĩnh trong lớp bên trong không tĩnh; bạn sẽ truy cập nó như thế nào?" Bạn sẽ gọi Outer.Inner.staticMethod()giống như bạn có thể truy cập Outer.Inner.CONSTANT. "Bạn không thể truy cập ... một thể hiện của lớp bên trong không tĩnh mà không thông qua một thể hiện của lớp bên ngoài." Tại sao bạn cần một ví dụ? Bạn không cần một ví dụ Outerđể gọi Outer.staticMethod(). Tôi biết điều này thật đáng ghét nhưng quan điểm của tôi là không có ý nghĩa gì khi đóng khung câu trả lời của bạn theo cách này. IMHO các nhà thiết kế ngôn ngữ có thể cho phép nó nếu họ muốn.
Paul Bellora

1
Sự khác biệt giữa Outer.Inner.CONSTANTOuter.Inner.staticMethod()là một tham chiếu đến một hằng số không có cơ hội mặc nhiên tham khảo trường hợp của Outertrong đó Innerđã được khởi tạo. Tất cả các tài liệu tham khảo để Outer.staticMethod()chia sẻ cùng một trạng thái chính xác. Tất cả các tài liệu tham khảo để Outer.Inner.CONSTANTchia sẻ cùng một trạng thái chính xác. Tuy nhiên, các tham chiếu đến Outer.Inner.staticMethod()không rõ ràng: Trạng thái "tĩnh" không thực sự tĩnh, do tham chiếu ngầm đến lớp bên ngoài trong mỗi trường hợp của Inner. Không có một cách thực sự rõ ràng, tĩnh để truy cập nó.
Eddie

3
@Eddie Bạn không thể tham khảo các trường đối tượng trong một phương thức tĩnh, do đó không có xung đột liên quan đến việc không thể tham chiếu đến trường đối tượng ẩn Outer.this. Tôi đồng ý với các nhà thiết kế ngôn ngữ Java rằng không có lý do nào để cho phép các phương thức tĩnh hoặc các trường tĩnh không phải là cuối cùng trong các lớp bên trong, bởi vì mọi thứ trong một lớp bên trong phải nằm trong ngữ cảnh của lớp kèm theo.
Theodore Murdock

20

Tôi có một lý thuyết, có thể đúng hoặc không đúng.

Trước tiên, bạn nên biết một số điều về cách các lớp bên trong được triển khai trong Java. Giả sử bạn đã có lớp học này:

class Outer {
    private int foo = 0;
    class Inner implements Runnable {
        public void run(){ foo++; }
    }
    public Runnable newFooIncrementer(){ return new Inner(); }
}

Khi bạn biên dịch nó, mã byte được tạo sẽ trông như thể bạn đã viết một cái gì đó như thế này:

class Outer {
    private int foo = 0;
    static class Inner implements Runnable {
        private final Outer this$0;
        public Inner(Outer outer){
            this$0 = outer;
        }
        public void run(){ this$0.foo++; }
    }
    public Runnable newFooIncrementer(){ return new Inner(this); }
}

Bây giờ, nếu chúng ta đã cho phép các phương thức tĩnh trong các lớp bên trong không tĩnh, bạn có thể muốn làm một cái gì đó như thế này.

class Outer {
    private int foo = 0;
    class Inner {
        public static void incrFoo(){ foo++; }
    }
}

... có vẻ khá hợp lý, vì Innerlớp dường như có một hóa thân mỗi Outertrường hợp. Nhưng như chúng ta đã thấy ở trên, các lớp bên trong không tĩnh thực sự chỉ là đường cú pháp cho các lớp "bên trong" tĩnh, vì vậy ví dụ cuối cùng sẽ tương đương với:

class Outer {
    private int foo = 0;
    static class Inner {
        private final Outer this$0;
        public Inner(Outer outer){
            this$0 = outer;
        }
        public static void incrFoo(){ this$0.foo++; }
    }
}

... mà rõ ràng sẽ không hoạt động, vì this$0là không tĩnh. Kiểu này giải thích tại sao các phương thức tĩnh không được phép (mặc dù bạn có thể đưa ra lập luận rằng bạn có thể cho phép các phương thức tĩnh miễn là chúng không tham chiếu đến đối tượng kèm theo) và tại sao bạn không thể có các trường tĩnh không phải là cuối cùng ( nó sẽ phản trực giác nếu các thể hiện của các lớp bên trong không tĩnh từ các đối tượng khác nhau được chia sẻ "trạng thái tĩnh"). Nó cũng giải thích tại sao các trường cuối cùng được cho phép (miễn là chúng không tham chiếu đến đối tượng kèm theo).


7
Nhưng đó chỉ là một lỗi "cố gắng truy cập biến không tĩnh từ ngữ cảnh tĩnh" thông thường - không khác gì nếu một phương thức tĩnh cấp cao nhất cố gắng truy cập biến đối tượng của lớp đó.
Lawrence Dol

2
Tôi thích anwser này bởi vì nó thực sự giải thích tại sao nó không thể về mặt kỹ thuật, mặc dù nó có vẻ như có thể về mặt cú pháp.
LoPoBo

@gustafc, tôi nghĩ đó là một lời giải thích tuyệt vời. Nhưng như Lawrence chỉ ra, đó chỉ là một thất bại vì liên quan đến foo, không phải là tĩnh. Nhưng nếu tôi muốn viết public static double sinDeg(double theta) { ... }một lớp tiện ích toán học bên trong thì sao?
Edward Falk

6

Lý do duy nhất là "không bắt buộc", vậy tại sao phải bận tâm hỗ trợ nó?

Về mặt cú pháp, không có lý do gì để cấm một lớp bên trong có các thành viên tĩnh. Mặc dù một ví dụ vềInner hiện được liên kết với một thể hiện của Outer, nhưng vẫn có thể sử dụng Outer.Inner.myStaticđể giới thiệu một thành viên tĩnh Innernếu java quyết định làm như vậy.

Nếu bạn cần chia sẻ một cái gì đó trong số tất cả các trường hợp Inner, bạn có thể đặt chúng vàoOuter các thành viên tĩnh. Điều này không tệ hơn việc bạn sử dụng các thành viên tĩnh trong đó Inner, nơi Outervẫn có thể truy cập bất kỳ thành viên riêng Innernào (không cải thiện việc đóng gói).

Nếu bạn cần chia sẻ một cái gì đó trong số tất cả các trường hợp của Inner được tạo bởi một outerđối tượng, sẽ có ý nghĩa hơn khi đưa chúng vào Outerlớp như các thành viên bình thường.

Tôi không đồng ý với ý kiến ​​rằng "một lớp lồng tĩnh gần như chỉ là một lớp cấp cao nhất". Tôi nghĩ tốt hơn là thực sự coi một lớp / lớp bên trong tĩnh là một phần của lớp bên ngoài, bởi vì họ có thể truy cập các thành viên riêng của lớp bên ngoài. Và các thành viên của lớp bên ngoài cũng là "thành viên của lớp bên trong". Vì vậy, không cần phải hỗ trợ thành viên tĩnh trong lớp bên trong. Một thành viên bình thường / tĩnh trong lớp bên ngoài sẽ đủ.


Các lớp bên trong cũng không phải là "phải". Tuy nhiên, vì ngôn ngữ không cung cấp các lớp bên trong, nên nó cung cấp một triển khai đầy đủ và có ý nghĩa đối với chúng.
intrepidis

4

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

Như với các phương thức và biến đối tượng, một lớp bên trong được liên kết với một thể hiện của lớp kèm theo của nó và có quyền truy cập trực tiếp vào các phương thức và trường của đối tượng đó. Ngoài ra, vì một lớp bên trong được liên kết với một thể hiện, nó không thể định nghĩa bất kỳ thành viên tĩnh nào.

Giải thích của Oracle là hời hợt và đẹp mắt. Do không có lý do kỹ thuật hoặc cú pháp để ưu tiên các thành viên tĩnh trong một lớp bên trong (nó được cho phép trong các ngôn ngữ khác như C #), động lực của các nhà thiết kế Java có thể là hương vị khái niệm và / hoặc vấn đề thuận tiện kỹ thuật.

Đây là suy đoán của tôi:

Không giống như các lớp cấp cao nhất, các lớp bên trong phụ thuộc vào thể hiện: một thể hiện của lớp bên trong được liên kết với một thể hiện của mỗi một lớp bên ngoài của nó và có quyền truy cập trực tiếp vào các thành viên của chúng. Đây là động lực chính để có chúng trong Java. Thể hiện theo một cách khác: một lớp bên trong có nghĩa là để khởi tạo trong ngữ cảnh của một thể hiện của lớp bên ngoài. Không có một thể hiện của lớp bên ngoài, một lớp bên trong sẽ không thể sử dụng được nhiều hơn các thành viên thể hiện khác của lớp bên ngoài. Hãy coi điều này là tinh thần phụ thuộc cá thể của các lớp bên trong.

Bản chất của các thành viên tĩnh (không phải là hướng đối tượng) đụng độ với phụ thuộc thể hiện tinh thần của các lớp bên trong (mà hướng đối tượng IS) bởi vì bạn có thể tham chiếu / gọi một thành viên tĩnh của lớp bên trong mà không cần một thể hiện lớp bên ngoài sử dụng tên lớp bên trong đủ điều kiện.

Các biến tĩnh đặc biệt có thể vi phạm theo một cách khác: hai trường hợp của một lớp bên trong được liên kết với các thể hiện khác nhau của lớp bên ngoài sẽ chia sẻ các biến tĩnh. Vì các biến là một thành phần của trạng thái, nên trong thực tế, hai trường hợp lớp bên trong sẽ chia sẻ trạng thái độc lập với các thể hiện của lớp bên ngoài mà chúng được liên kết. Không phải là không thể chấp nhận được rằng các biến tĩnh hoạt động theo cách này (chúng tôi chấp nhận chúng trong Java như một sự thỏa hiệp hợp lý với độ tinh khiết OOP), nhưng có thể cho rằng có một sự vi phạm sâu sắc hơn bằng cách cho phép chúng trong các lớp bên trong có các thể hiện bên ngoài được ghép nối với các thể hiện của lớp bên ngoài thiết kế bởi. Cấm các thành viên tĩnh trong các lớp bên trong ủng hộ tinh thần phụ thuộc cá thể gặt hái thêm phần thưởng cho việc ngăn chặn hành vi phạm tội OOP sâu hơn này.

Mặt khác, không có hành vi phạm tội như vậy được đòi hỏi bởi các hằng số tĩnh, không có ý nghĩa cấu thành trạng thái và vì vậy những điều này được cho phép. Tại sao không cấm các hằng số tĩnh để có sự thống nhất tối đa với tinh thần phụ thuộc thể hiện ? Có lẽ bởi vì các hằng số không cần chiếm nhiều bộ nhớ hơn mức cần thiết (nếu chúng bị buộc phải không tĩnh thì chúng được sao chép vào mọi thể hiện của lớp bên trong có khả năng gây lãng phí). Nếu không, tôi không thể tưởng tượng lý do cho ngoại lệ.

Nó có thể không phải là lý luận vững chắc, nhưng IMO nó có ý nghĩa nhất về nhận xét khó hiểu của Oracle về vấn đề này.


3

Câu trả lời ngắn: Mô hình tinh thần mà hầu hết các lập trình viên có về cách hoạt động của phạm vi không phải là mô hình được sử dụng bởi javac. Phù hợp với mô hình trực quan hơn sẽ đòi hỏi một sự thay đổi lớn đối với cách javac hoạt động.

Lý do chính mà các thành viên tĩnh trong các lớp bên trong mong muốn là vì sự sạch sẽ của mã - một thành viên tĩnh chỉ được sử dụng bởi một lớp bên trong phải sống bên trong nó, thay vì phải được đặt ở lớp bên ngoài. Xem xét:

class Outer {
   int outID;

   class Inner {
      static int nextID;
      int id = nextID++;

      String getID() {
         return outID + ":" + id;
      }
   }
}

Hãy xem xét những gì đang xảy ra trong getID () khi tôi sử dụng mã định danh không đủ tiêu chuẩn "outID". Phạm vi mà số nhận dạng này xuất hiện trông giống như:

Outer -> Inner -> getID()

Ở đây, một lần nữa bởi vì đây chỉ là cách javac hoạt động, mức độ "Bên ngoài" của phạm vi bao gồm cả các thành viên tĩnh và cá thể của Outer. Điều này gây nhầm lẫn bởi vì chúng ta thường được cho là nghĩ về phần tĩnh của một lớp là một cấp độ khác của phạm vi:

Outer static -> Outer instance -> instanceMethod()
         \----> staticMethod()

Theo cách nghĩ này, tất nhiên staticMethod () chỉ có thể thấy các thành viên tĩnh của Outer. Nhưng nếu đó là cách javac hoạt động, thì việc tham chiếu một biến thể hiện trong một phương thức tĩnh sẽ dẫn đến lỗi "tên không thể được giải quyết". Điều thực sự xảy ra là tên được tìm thấy trong phạm vi, nhưng sau đó, một mức độ kiểm tra bổ sung bắt đầu và chỉ ra rằng tên đó đã được khai báo trong một bối cảnh thể hiện và được tham chiếu từ ngữ cảnh tĩnh.

OK, làm thế nào điều này liên quan đến các lớp bên trong? Ngây thơ, chúng tôi nghĩ rằng không có lý do gì các lớp bên trong không thể có phạm vi tĩnh, bởi vì chúng tôi đang hình dung phạm vi hoạt động như thế này:

Outer static -> Outer instance -> Inner instance -> getID()
         \------ Inner static ------^

Nói cách khác, các khai báo tĩnh trong lớp bên trong và khai báo thể hiện ở lớp bên ngoài đều nằm trong phạm vi trong bối cảnh thể hiện của lớp bên trong, nhưng cả hai đều không thực sự được lồng vào nhau; cả hai thay vào đó được lồng trong phạm vi tĩnh của Bên ngoài.

Đó không chỉ là cách javac hoạt động - có một cấp phạm vi duy nhất cho cả thành viên tĩnh và cá thể và phạm vi luôn luôn nghiêm ngặt lồng nhau. Ngay cả sự kế thừa cũng được thực hiện bằng cách sao chép các khai báo vào lớp con thay vì phân nhánh và tìm kiếm phạm vi siêu lớp.

Để hỗ trợ các thành viên tĩnh của các lớp bên trong, javac sẽ phải phân chia phạm vi tĩnh và cá thể hỗ trợ phân cấp phạm vi phân nhánh và nối lại, hoặc nó sẽ phải mở rộng ý tưởng "bối cảnh tĩnh" đơn giản của nó để thay đổi để theo dõi loại bối cảnh ở mọi cấp độ của lớp lồng nhau trong phạm vi hiện tại.


Tôi nghĩ rằng một khó khăn cơ bản hơn với việc cho phép các lớp bên trong không tĩnh có các thành viên tĩnh không cố định là các lập trình viên tuyên bố các thành viên đó có thể có ý định ràng buộc họ với các thể hiện của lớp bên ngoài hoặc để họ thực sự tĩnh. Trong trường hợp một cấu trúc - nếu hợp pháp - có thể được xác định một cách hợp lý là có nghĩa là một trong hai điều khác nhau và trong đó cả hai điều đó có thể được thể hiện theo những cách rõ ràng khác, việc xác định rằng cấu trúc đó là bất hợp pháp thường tốt hơn là chỉ định nó là có ý nghĩa
supercat

3

Tại sao chúng ta không thể có phương thức tĩnh trong một lớp bên trong không tĩnh?

Lưu ý: Một lớp lồng không tĩnh được gọi là lớp bên trong nên bạn không có non-static inner classnhư vậy.

Một thể hiện của lớp bên trong không có sự tồn tại mà không có một thể hiện tương ứng của lớp bên ngoài. Một lớp bên trong không thể khai báo các thành viên tĩnh ngoài các hằng số thời gian biên dịch. Nếu nó được cho phép thì sẽ có sự mơ hồ về ý nghĩa của static. Trong trường hợp đó, đã có những nhầm lẫn nhất định:

  1. Có nghĩa là chỉ có một phiên bản trong VM?
  2. Hoặc chỉ một trường hợp cho mỗi đối tượng bên ngoài?

Đó là lý do tại sao các nhà thiết kế có thể đã quyết định không xử lý vấn đề này.

Nếu tôi làm cho lớp bên trong tĩnh nó hoạt động. Tại sao ?

Một lần nữa, bạn không thể tạo một lớp bên trong tĩnh thay vì bạn có thể khai báo một lớp tĩnh là lồng nhau. Trong trường hợp đó, lớp lồng này thực sự là một phần của lớp bên ngoài và có thể có các thành viên tĩnh mà không có vấn đề gì.


3

Chủ đề này đã thu hút được sự chú ý từ nhiều người, tôi vẫn sẽ cố gắng giải thích bằng những thuật ngữ đơn giản nhất.

Đầu tiên, với tham chiếu đến http://docs.oracle.com/javase/specs/jls/se7/html/jls-12.html#jls-12.4.1 , một lớp hoặc giao diện được khởi tạo ngay lập tức trước khi xảy ra / gọi đầu tiên của bất kỳ thành viên nào được đặt trước bởi từ khóa tĩnh.

  1. Vì vậy, nếu chúng ta đưa ra một thành viên tĩnh trong một lớp bên trong, nó sẽ dẫn đến việc khởi tạo lớp bên trong, không nhất thiết là lớp bên ngoài / bao vây. Vì vậy, chúng tôi cản trở trình tự khởi tạo lớp.

  2. Cũng xem xét thực tế rằng một lớp bên trong không tĩnh được liên kết với thể hiện của một lớp bao quanh / lớp ngoài. Vì vậy, liên kết với một thể hiện sẽ có nghĩa là lớp bên trong sẽ tồn tại bên trong một thể hiện của lớp ngoài và sẽ khác nhau giữa các thể hiện.

Đơn giản hóa điểm, để truy cập thành viên tĩnh, chúng ta cần một thể hiện của lớp Ngoài, từ đó chúng ta sẽ lại cần tạo một thể hiện của lớp bên trong không tĩnh. Các thành viên tĩnh không bị ràng buộc với các thể hiện và do đó bạn nhận được lỗi biên dịch.


2

Một lớp bên trong là một cái gì đó hoàn toàn khác với một lớp lồng tĩnh mặc dù cả hai đều giống nhau về cú pháp. Các lớp lồng nhau tĩnh chỉ là một phương tiện để nhóm trong khi các lớp bên trong có một liên kết mạnh mẽ - và truy cập vào tất cả các giá trị của - lớp bên ngoài của chúng. Bạn nên chắc chắn lý do tại sao bạn muốn sử dụng một lớp bên trong và sau đó nó sẽ trở nên khá tự nhiên mà bạn phải sử dụng. Nếu bạn cần khai báo một phương thức tĩnh thì có lẽ đó là một lớp lồng tĩnh mà bạn muốn.


Benedikt, ý bạn là gì khi bạn nói "các lớp lồng tĩnh chỉ là một phương tiện để nhóm"?
Ankur

0

giả sử có hai trường hợp của lớp bên ngoài và cả hai đều có lớp bên trong được khởi tạo. Bây giờ nếu lớp bên trong có một thành viên tĩnh thì nó sẽ chỉ giữ một bản sao của thành viên đó trong vùng heap. Trong trường hợp này cả hai đối tượng của lớp bên ngoài sẽ đề cập đến điều này một bản sao duy nhất và họ có thể thay đổi nó cùng nhau. Điều này có thể gây ra tình huống "Đọc bẩn" do đó để ngăn chặn Java này đã áp dụng hạn chế này. Điểm mạnh khác để hỗ trợ cho lập luận này là java cho phép các thành viên tĩnh cuối cùng ở đây, những người có giá trị không thể thay đổi từ một trong các đối tượng lớp bên ngoài. Xin vui lòng cho tôi nếu tôi sai.


0

Trước hết tại sao ai đó muốn xác định thành viên tĩnh trong một lớp bên trong không tĩnh? Câu trả lời là, để thành viên lớp bên ngoài có thể sử dụng các thành viên tĩnh đó chỉ với tên lớp bên trong, phải không?

Nhưng đối với trường hợp này, chúng ta có thể định nghĩa trực tiếp thành viên trong lớp bên ngoài. sẽ được liên kết với tất cả các đối tượng của lớp bên trong, bên trong thể hiện của lớp bên ngoài.

như mã dưới đây,

public class Outer {

  class Inner {

    public static void method() {

    }

  }

}

có thể được viết như thế này

public class Outer {

  void method() {

   }

   class Inner {


  }

}

Vì vậy, theo tôi, không làm phức tạp mã java mà nhà thiết kế không cho phép chức năng này hoặc chúng ta có thể thấy chức năng này trong các bản phát hành trong tương lai với một số tính năng khác.


0

Hãy cố gắng coi lớp học như một lĩnh vực bình thường, sau đó bạn sẽ hiểu.

//something must be static. Suppose something is an inner class, then it has static keyword which means it's a static class
Outer.something 

-1

Thật vô ích khi có các thành viên trong lớp là tĩnh vì bạn sẽ không thể truy cập chúng ngay từ đầu.

Hãy suy nghĩ về điều này, để truy cập một thành viên tĩnh, bạn sử dụng className.memberName ,, trong trường hợp của chúng tôi, nó phải là một cái gì đó giống như ngoài className.innerclassName.memberName ,,, bây giờ bạn có thấy tại sao innerclass phải tĩnh ....


-2

Bạn được phép các phương thức tĩnh trên các lớp lồng nhau tĩnh. Ví dụ

public class Outer {

  public static class Inner {

    public static void method() {

    }
  }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.