Tại sao bạn không thể khai báo một lớp là tĩnh trong Java?


459

Tại sao bạn không thể khai báo một lớp là tĩnh trong Java?


72
Câu hỏi ngược: bạn mong đợi hiệu ứng sẽ như thế nào, nếu bạn tuyên bố một lớp cấp cao nhất sẽ là staticgì?
Joachim Sauer

3
Không, bạn không thể, ngoại trừ các lớp bên trong tĩnh. Nhưng, bạn muốn đạt được điều gì với điều đó?
manolowar

60
@Joachim Sauer: Chà, C # diễn giải staticcác lớp như abstract final, nghĩa là, chúng không thể được khởi tạo và không thể được mở rộng. Điều này có nghĩa là chúng chỉ có thể chứa các thành viên tĩnh, rất hữu ích cho các lớp chỉ chứa các phương thức của trình trợ giúp.
bcat

30
@bcat điều này đúng với C #, nhưng một lớp java có thể là trừu tượng hoặc cuối cùng, không phải cả hai. Để ngăn chặn một lớp được khởi tạo, người ta có thể khai báo một hàm tạo riêng.
Lorenzo Polidori

7
@JoachimSauer Đơn giản, tôi muốn buộc tất cả các thành viên trong lớp phải tĩnh (thậm chí có thể phải khai báo trên mỗi phương thức hoặc thuộc tính).
hmartinezd

Câu trả lời:


475

Chỉ các lớp lồng nhau có thể là tĩnh. Bằng cách làm như vậy, bạn có thể sử dụng lớp lồng mà không cần có một thể hiện của lớp bên ngoài.

class OuterClass{
    public static class StaticNestedClass{
    }

    public class InnerClass{
    }

    public InnerClass getAnInnerClass(){
        return new InnerClass();
    }

    //This method doesn't work
    public static InnerClass getAnInnerClassStatically(){
        return new InnerClass();
    }
}

class OtherClass{
    //Use of a static nested class:
    private OuterClass.StaticNestedClass staticNestedClass = new OuterClass.StaticNestedClass();

    //Doesn't work
    private OuterClass.InnerClass innerClass = new OuterClass.InnerClass();

    //Use of an inner class:
    private OuterClass outerclass= new OuterClass();
    private OuterClass.InnerClass innerClass2 = outerclass.getAnInnerClass();
    private OuterClass.InnerClass innerClass3 = outerclass.new InnerClass();
}

Nguồn:

Cùng chủ đề:


3
+1 mặc dù cụm từ đầu tiên không chính xác. Như hướng dẫn nói "Các lớp lồng không tĩnh được gọi là các lớp bên trong." (JLS: "Một lớp bên trong là một lớp lồng nhau không được khai báo rõ ràng hoặc ngầm định.")
user85421

74
Bạn chắc chắn là đúng; nhưng tôi không thấy cách này trả lời câu hỏi
Joeri Hendrickx

2
@Carlos Heuberger, bạn nói đúng, tôi đã cập nhật bài viết. @Joeri Hendrickx, Câu hỏi là, "tại sao một lớp không thể được tuyên bố là tĩnh ..?", Họ có thể, và [đọc bài viết của tôi ở đây]. Đó là một lời giải thích về việc sử dụng các lớp tĩnh và tại sao chúng phải là các lớp lồng nhau.
Colin Hebert

1
Giải pháp được đưa ra ở đây là ổn ... Nhưng tôi vẫn tự hỏi y ppl đã không giải thích một cách logic rằng lớp tĩnh không thể có trong java..một số giải thích khái niệm OOP sẽ là câu trả lời đúng. Tôi đang chờ đợi nó
Punith Raj

9
Điều đó đúng, nhưng câu hỏi bạn đang suy nghĩ thường tự giải quyết khi bạn bắt đầu tự hỏi "lớp tĩnh" sẽ là gì. Trong java, một phần tử tĩnh có nghĩa là bạn có thể truy cập / gọi nó mà không cần một thể hiện của lớp kèm theo; điều đó có thể có nghĩa gì nếu bạn áp dụng từ khóa cho chính lớp đó? Ý định của bạn là gì? Bạn mong đợi điều gì? Bây giờ bạn đã có ý tưởng về những gì nó có thể, tôi khá chắc chắn rằng nó sẽ "không thực sự có ý nghĩa" hoặc nó sẽ "rất xa vời" (nó sẽ có ý nghĩa, nhưng cuối cùng nó chỉ là một sự lựa chọn điều đó đã được thực hiện).
Colin Hebert

39

Các lớp cấp cao nhất là tĩnh theo mặc định. Các lớp bên trong là không tĩnh theo mặc định. Bạn có thể thay đổi mặc định cho các lớp bên trong bằng cách đánh dấu rõ ràng chúng tĩnh. Các lớp cấp cao nhất, do là cấp cao nhất, không thể có ngữ nghĩa không tĩnh vì không thể có lớp cha để tham khảo. Do đó, không có cách nào để thay đổi mặc định cho các lớp cấp cao nhất.


14
»Các lớp cấp cao nhất là tĩnh theo mặc định.« Đây là câu trả lời tốt nhất. Chúng là tĩnh vì bạn không cần bất kỳ trường hợp nào để đề cập đến chúng. Họ có thể được giới thiệu từ bất cứ nơi nào. Chúng nằm trong bộ lưu trữ tĩnh (như trong các lớp lưu trữ C). - Như những người khác đã lưu ý (Iain Elder trong một bình luận cho câu trả lời khác), các nhà thiết kế ngôn ngữ có thể đã cho phép statictừ khóa trên một lớp cấp cao nhất biểu thị và thực thi rằng nó chỉ có thể chứa các thành viên tĩnh và không được khởi tạo; tuy nhiên, điều đó có thể khiến mọi người nhầm lẫn vì staticcó một ý nghĩa khác cho các lớp lồng nhau.
Lumi

35

Vì vậy, tôi đến bữa tiệc muộn, nhưng đây là hai xu của tôi - về mặt triết học thêm vào câu trả lời của Colin Hebert.

Ở mức độ cao, câu hỏi của bạn liên quan đến sự khác biệt giữa các đối tượng và loại. Trong khi có nhiều ô tô (đối tượng), chỉ có một loại Xe (loại). Khai báo một cái gì đó là tĩnh có nghĩa là bạn đang hoạt động trong không gian "loại". Chỉ có một. Từ khóa lớp cấp cao nhất đã xác định một loại trong không gian "loại". Kết quả là "Xe tĩnh lớp công cộng" là dư thừa.


1
Đúng. Nói cách khác, các lớp cấp cao nhất là tĩnh theo mặc định, do đó không cần từ khóa.
Warren Dew

1
Chà, tôi sẽ thêm vào những gì Warren Dew nói - "các lớp cấp cao nhất là tĩnh theo mặc định khi truy cập các thành viên tĩnh".
Dexter

1
Câu trả lời không nản lòng. Một từ khóa mới để buộc mọi phương thức trong một lớp là tĩnh và hàm tạo riêng sẽ rất tốt. Tôi sẽ không đặt tên cho nó là tĩnh bởi vì điều đó chỉ gây nhầm lẫn.
G_V

@G_V Mặc dù java có thể tạo ra một con quái vật như vậy, Java gần như vượt ra khỏi nó để làm cho những điều ngu ngốc trở nên khó khăn. Statics là một ý tưởng tồi nói chung, các lớp tĩnh là khủng khiếp (Tệ hơn cả các singletons mà bản thân chúng được coi là một mô hình chống). Nhiều người không hiểu điều này nên cho nó một từ khóa sẽ là một ý tưởng rất tồi. Thay vào đó chúng tôi làm cho những điều xấu trở nên khó khăn và chỉ để nó ở đó. Lưu ý rằng không có từ khóa "Singleton". và không có từ khóa bất động sản. Tất cả đều gây ra mã xấu (Mặc dù mọi người vẫn sử dụng Thuộc tính nhiều đến mức Java cũng có thể hỗ trợ chúng)
Bill K

29

Lớp với constructor riêng là tĩnh.

Khai báo lớp của bạn như thế này:

public class eOAuth {

    private eOAuth(){}

    public final static int    ECodeOauthInvalidGrant = 0x1;
    public final static int    ECodeOauthUnknown       = 0x10;
    public static GetSomeStuff(){}

}

và bạn có thể sử dụng mà không cần khởi tạo:

if (value == eOAuth.ECodeOauthInvalidGrant)
    eOAuth.GetSomeStuff();
...

3
Nó không tĩnh, nhưng chứa các thuộc tính tĩnh. Nếu bạn viết chung kết int ECodeOauthUn Unknown = 0x10; nó không tĩnh nữa.
dùng1883212

9
Trong trường hợp bất cứ ai đang tự hỏi điều gì đang xảy ra ở đây, thì điều này phù hợp với định nghĩa C # của một "lớp tĩnh" - msdn.microsoft.com/en-us/l Library / 79b3xss3% 28v = vs.90% 29.aspx . Đưa ra định nghĩa Java về "lớp tĩnh", tất cả các lớp không bên trong là tĩnh (xem câu trả lời của anh chị em).
Calum

1
Ngoài @ user1883212 là đúng, tôi thậm chí còn nói rằng câu trả lời này khiến người đọc nhầm lẫn rằng nhà xây dựng riêng tư bằng cách nào đó quan trọng ở đây, trong khi nó thực sự không quan trọng.
tlwhitec

Trong thế giới .NET, nếu một lớp được đánh dấu cả trừu tượng và cuối cùng (hiệu ứng của một static classkhai báo trong C #), trình biên dịch thậm chí sẽ không cho phép mã khai báo các biến của loại đó, cũng không sử dụng nó làm tham số loại chung. Việc thiếu các hàm tạo có thể truy cập trong một lớp có thể được khởi tạo hoặc kế thừa theo cách khác sẽ không loại trừ việc khai báo các biến của loại đó, cũng không sử dụng nó làm tham số kiểu chung.
supercat

Câu trả lời này là hoàn toàn không chính xác. Các nhà xây dựng tư nhân không có gì để làm với nó. Mã này chỉ là một ví dụ về một lớp không có gì ngoài các thuộc tính và phương thức tĩnh. Nó không có gì để làm với các lớp tĩnh.
Hầu tước Lorne

13

Chắc chắn họ có thể, nhưng chỉ các lớp lồng bên trong . Ở đó, nó có nghĩa là các thể hiện của lớp lồng nhau không yêu cầu một thể hiện kèm theo của lớp bên ngoài.

Nhưng đối với các lớp cấp cao nhất, các nhà thiết kế ngôn ngữ không thể nghĩ ra bất cứ điều gì hữu ích để làm với từ khóa, vì vậy nó không được phép.


+1 mặc dù cụm từ đầu tiên không chính xác. Như JLS tuyên bố: "Một lớp bên trong là một lớp lồng nhau không được khai báo rõ ràng hoặc ngầm định." (Chỉ cần thuật ngữ, tôi biết ...)
user85421

7
Mặc dù một lớp cấp cao nhất không thể được khai báo static, đôi khi nó có thể có ý nghĩa. Ví dụ, một lớp chỉ chứa các phương thức trợ giúp tĩnh không có nghĩa là được khởi tạo, nhưng ngôn ngữ Java không ngăn bạn thực hiện nó. Bạn có thể làm cho lớp không thể thực hiện được (và thực tế là 'tĩnh') cho các lớp khác bằng cách khai báo hàm tạo mặc định private, điều này cấm khởi tạo bởi vì không có hàm tạo nào hiển thị.
Iain Samuel McLean Elder

12

Bạn có thể tạo một lớp tiện ích (không thể có các thể hiện được tạo) bằng cách khai báo một kiểu enum không có cá thể. tức là bạn đang tuyên bố cụ thể rằng không có trường hợp nào.

public enum MyUtilities {;
   public static void myMethod();
}

25
một kiểu liệt kê là một loại kỳ vọng cụ thể: đó là một tập hợp các mục. Sử dụng nó cho một "lớp tiện ích", khi bạn có thể có một lớp với một hàm tạo riêng, thì thật khó hiểu về mặt ngữ nghĩa.
Giải pháp phần mềm có tầm nhìn

5
@VisionarySoftwareSolutions Đối với tôi, tính đặc hiệu này nói rằng không có trường hợp nào của lớp này, thay vì gián tiếp làm cho không thể tạo các thể hiện của một lớp.
Peter Lawrey

8
public class Outer {
   public static class Inner {}
}

... nó có thể được khai báo tĩnh - miễn là nó là một lớp thành viên.

Từ JLS:

Các lớp thành viên có thể là tĩnh, trong trường hợp đó, chúng không có quyền truy cập vào các biến thể hiện của lớp xung quanh; hoặc chúng có thể là các lớp bên trong (§8.1.3).

và đây:

Từ khóa tĩnh có thể sửa đổi khai báo của một loại thành viên C trong cơ thể của một lớp không bên trong T. Tác dụng của nó là tuyên bố rằng C không phải là một lớp bên trong. Giống như một phương thức tĩnh của T không có phiên bản hiện tại của T trong cơ thể, C cũng không có phiên bản hiện tại của T, và cũng không có bất kỳ trường hợp bao quanh từ vựng nào.

Một từ khóa tĩnh sẽ không có ý nghĩa gì đối với một lớp cấp cao nhất, chỉ vì một lớp cấp cao nhất không có loại kèm theo.


Nếu nó không bên trong tại sao gọi nó Inner? Nestedsẽ là một lựa chọn ít khó hiểu hơn.
Hầu tước Lorne

5

Như đã giải thích ở trên, một Class không thể tĩnh trừ khi nó là thành viên của Class khác.

Nếu bạn đang tìm cách thiết kế một lớp "trong đó không thể có nhiều trường hợp", bạn có thể muốn xem xét mẫu thiết kế "Singleton".

Thông tin Singleton mới bắt đầu ở đây .

Hãy cẩn thận:

Nếu bạn đang nghĩ đến việc sử dụng mẫu singleton, hãy kháng cự với tất cả khả năng của bạn. Đây là một trong những DesignPotype dễ hiểu nhất, có thể là phổ biến nhất và chắc chắn bị lạm dụng nhất. (nguồn: JavaRanch như được liên kết ở trên)


4

Ngoài cách Java định nghĩa các lớp bên trong tĩnh, còn có một định nghĩa khác về các lớp tĩnh theo thế giới C # [1] . Một lớp tĩnh là một lớp chỉ có các phương thức tĩnh (hàm) và nó có nghĩa là để hỗ trợ lập trình thủ tục. Các lớp như vậy không thực sự là các lớp trong đó người dùng của lớp chỉ quan tâm đến các hàm trợ giúp và không tạo ra các thể hiện của lớp. Mặc dù các lớp tĩnh được hỗ trợ trong C #, không có hỗ trợ trực tiếp nào như vậy tồn tại trong Java. Tuy nhiên, bạn có thể sử dụng enums để bắt chước các lớp tĩnh C # trong Java để người dùng không bao giờ có thể tạo các thể hiện của một lớp nhất định (thậm chí sử dụng sự phản chiếu) [2] :

public enum StaticClass2 {
    // Empty enum trick to avoid instance creation
    ; // this semi-colon is important

    public static boolean isEmpty(final String s) {
        return s == null || s.isEmpty();
    }
}

3

Tất cả mọi thứ chúng tôi mã trong java đi vào một lớp. Bất cứ khi nào chúng ta chạy một lớp JVM sẽ khởi tạo một đối tượng. JVM có thể tạo một số đối tượng, theo định nghĩa Tĩnh có nghĩa là bạn có cùng một bộ bản sao cho tất cả các đối tượng.

Vì vậy, nếu Java sẽ cho phép lớp trên cùng tĩnh bất cứ khi nào bạn chạy một chương trình, thì nó sẽ tạo một Object và tiếp tục ghi đè lên cùng một Vị trí bộ nhớ.

Nếu bạn chỉ thay thế đối tượng mỗi khi bạn chạy nó thì điểm tạo ra nó là gì?

Vì vậy, đó là lý do Java thoát khỏi trạng thái tĩnh đối với Lớp cấp cao nhất.

Có thể có nhiều lý do cụ thể hơn nhưng điều này có ý nghĩa logic với tôi.


3
Các lớp bên trong được liên kết với các lớp bên ngoài và đó là lý do chúng có thể tĩnh, vì bạn có một đối tượng khác để phụ thuộc.
dùng2626445

1
Bạn có nghĩa là 'đó là lý do họ không thể tĩnh'.
Hầu tước Lorne

2

Các lớp duy nhất có thể tĩnh là các lớp bên trong. Các mã sau hoạt động tốt:

public class whatever {
    static class innerclass {
    }
}

Điểm của các lớp bên trong tĩnh là chúng không có tham chiếu đến đối tượng lớp bên ngoài.


1
"Nội tĩnh" là một mâu thuẫn trong các điều khoản. 'tĩnh' và 'bên trong' là loại trừ lẫn nhau. Từ bạn đang tìm kiếm là 'lồng nhau', không phải 'bên trong'.
Hầu tước Lorne

1

Tôi nghĩ rằng điều này có thể dễ dàng như uống một ly cà phê!. Chỉ cần nhìn vào điều này. Chúng tôi không sử dụng từ khóa tĩnh trong khi xác định lớp.

public class StaticClass {

    static private int me = 3;
    public static void printHelloWorld() {
       System.out.println("Hello World");
    }



    public static void main(String[] args) {
        StaticClass.printHelloWorld();
        System.out.println(StaticClass.me);
    }
}

Đó không phải là một định nghĩa của lớp tĩnh sao? Chúng ta chỉ sử dụng một hàm liên kết với chỉ một lớp. Hãy cẩn thận rằng trong trường hợp này chúng ta có thể sử dụng một lớp khác trong đó lồng nhau. Nhìn vào cái này

class StaticClass1 {

    public static int yum = 4;

    static void  printHowAreYou() {
        System.out.println("How are you?");
    }
}

public class StaticClass {

    static int me = 3; 
    public static void printHelloWorld() {
       System.out.println("Hello World");
       StaticClass1.printHowAreYou();
       System.out.println(StaticClass1.yum);
    }



    public static void main(String[] args) {
        StaticClass.printHelloWorld();
        System.out.println(StaticClass.me);
    }
}

Tôi nghĩ rằng chúng ta có thể coi các lớp như là lớp tĩnh bằng cách tham khảo định nghĩa lớp tĩnh không chỉ bằng cách sử dụng từ khóa tĩnh làm vòng loại.
Erfankam

Hãy chắc chắn tạo một nhà xây dựng riêng, nếu không bạn sẽ có thể nói new StaticClass()và điều đó không thực sự có ý nghĩa nhiều. Với một hàm tạo riêng, nó sẽ không cho phép các thể hiện của nó.
grinch

1

Người ta có thể xem xét PlatformUItrong Eclipse về một lớp với các phương thức tĩnh và hàm tạo riêng với chính nó là cuối cùng.

public final class <class name>
{
   //static constants
   //static memebers
}

0

nếu lợi ích của việc sử dụng lớp tĩnh không phải là khởi tạo một đối tượng và sử dụng một phương thức thì chỉ cần khai báo lớp là công khai và phương thức này là tĩnh.

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.