Các lớp tĩnh trong Java


947

Có bất cứ điều gì như static classtrong java?

Ý nghĩa của một lớp học như vậy là gì. Có phải tất cả các phương thức của lớp tĩnh staticcũng vậy?

Có phải nó được yêu cầu theo cách khác, nếu một lớp chứa tất cả các phương thức tĩnh, thì lớp đó cũng sẽ tĩnh?

Các lớp tĩnh tốt cho là gì?


4
Bạn có thể quan tâm đến stackoverflow.com/questions35384113/java-static-
class

Các lớp tĩnh về cơ bản được sử dụng để nhóm các lớp lại với nhau.
RockingDev

Câu trả lời:


847

Java có các lớp lồng nhau tĩnh nhưng có vẻ như bạn đang tìm kiếm một lớp tĩnh cấp cao nhất. Java không có cách nào để tạo một lớp tĩnh cấp cao nhất nhưng bạn có thể mô phỏng một lớp tĩnh như thế này:

  • Khai báo lớp của bạn final- Ngăn chặn việc mở rộng lớp kể từ khi mở rộng một lớp tĩnh không có ý nghĩa
  • Tạo hàm tạo private- Ngăn chặn việc khởi tạo bằng mã máy khách vì nó không có ý nghĩa để khởi tạo một lớp tĩnh
  • Tạo tất cả các thành viên và chức năng của lớp static- Vì lớp không thể được khởi tạo nên không có phương thức cá thể nào có thể được gọi hoặc các trường đối tượng được truy cập
  • Lưu ý rằng trình biên dịch sẽ không ngăn bạn khai báo một thành viên (không tĩnh). Vấn đề sẽ chỉ hiển thị nếu bạn cố gắng gọi thành viên thể hiện

Ví dụ đơn giản cho mỗi đề xuất từ ​​phía trên:

public class TestMyStaticClass {
     public static void main(String []args){
        MyStaticClass.setMyStaticMember(5);
        System.out.println("Static value: " + MyStaticClass.getMyStaticMember());
        System.out.println("Value squared: " + MyStaticClass.squareMyStaticMember());
        // MyStaticClass x = new MyStaticClass(); // results in compile time error
     }
}

// A top-level Java class mimicking static class behavior
public final class MyStaticClass {
    private MyStaticClass () { // private constructor
        myStaticMember = 1;
    }
    private static int myStaticMember;
    public static void setMyStaticMember(int val) {
        myStaticMember = val;
    }
    public static int getMyStaticMember() {
        return myStaticMember;
    }
    public static int squareMyStaticMember() {
        return myStaticMember * myStaticMember;
    }
}

Những lớp tốt là gì? Việc sử dụng tốt một lớp tĩnh là trong việc xác định các lớp một lần, tiện ích và / hoặc thư viện trong đó việc khởi tạo sẽ không có ý nghĩa. Một ví dụ tuyệt vời là lớp Math chứa một số hằng số toán học như PI và E và chỉ đơn giản là cung cấp các phép tính toán học. Yêu cầu khởi tạo trong trường hợp như vậy sẽ không cần thiết và khó hiểu. Xem Mathlớp và mã nguồn . Lưu ý rằng nó là finalvà tất cả các thành viên của nó là static. Nếu Java cho phép các lớp cấp cao nhất được khai báo staticthì lớp Math thực sự sẽ là tĩnh.


35
một lớp Foochỉ có staticcác phương thức không giống nhưstatic class Foo
craigb

12
@Evorlor: Nếu một lớp được khai báo là cuối cùng thì các phương thức của nó sẽ tự động (có hiệu quả) cuối cùng. Điều này là do một lớp cuối cùng không thể được phân lớp và do đó các phương thức của nó không thể bị ghi đè (nghĩa là cuối cùng có hiệu quả). docs.oracle.com/javase/tutorial/java/IandI/final.html
jwayne 11/03/2015

30
Câu trả lời này có thể giải quyết ý nghĩa của OP, nhưng nó (hiện tại) không giải thích các lớp tĩnh Java và do đó không trả lời câu hỏi nào cả! Điều này rất tệ cho những người đến đây cố gắng tìm hiểu ý nghĩa của một lớp tĩnh trong Java.
Tom

12
@JBoy: Có một thứ gọi là "lớp tĩnh" trong Java, đó là những gì câu hỏi nói về, nhưng câu trả lời này hoàn toàn không giải thích. Thay vào đó, nó giải thích cách mô phỏng trong Java, câu trả lời gọi là "lớp tĩnh" - nhưng đó không phải là "lớp tĩnh" trong Java là gì! (Có thể đó là thứ gọi là "lớp tĩnh" trong một số ngôn ngữ khác, nhưng những người đến đây để tìm hiểu về các lớp tĩnh Java sẽ bị nhầm lẫn và nhầm lẫn.)
Tom

4
bạn nên đề cập rõ ràng rằng MyStaticClass () {// constructor private myStaticMember = 1; } sẽ hoàn toàn KHÔNG có hiệu lực vì hàm tạo sẽ không được gọi. Nhưng đây không phải vấn đề. Tôi vẫn còn rất bối rối về tiện ích của các lớp bên trong tĩnh trong Java và tiện ích hoặc giá trị gia tăng của chúng.
moldovean 23/2/2017

316

Chà, Java có "các lớp lồng nhau tĩnh", nhưng chúng hoàn toàn không giống với các lớp tĩnh của C #, nếu đó là nơi bạn đến. Một lớp lồng tĩnh chỉ là một lớp không hoàn toàn có một tham chiếu đến một thể hiện của lớp bên ngoài.

Các lớp lồng nhau tĩnh có thể có các phương thức cá thể và phương thức tĩnh.

Không có thứ gọi là lớp tĩnh cấp cao nhất trong Java.


12
Trong Java Tại sao lớp lồng nhau tĩnh cho phép các phương thức cá thể? Việc sử dụng một phương thức cá thể trong một lớp như vậy là gì?
Geek

19
@Geek: Bạn đã đọc câu trả lời của tôi? Đọc câu thứ hai cẩn thận. Tại sao bạn không muốn có các phương thức cá thể của các lớp tĩnh? Bạn có thể tạo ra các trường hợp của chúng, sau khi tất cả.
Jon Skeet

17
@Geek: Vâng, nó hoàn toàn được phép. Về cơ bản, "sự hiểu biết" của bạn rằng các lớp tĩnh là các lớp tiện ích là không chính xác. Đó hoàn toàn không phải là các lớp tĩnh trong Java.
Jon Skeet

14
@Geek: Vâng. Chính xác như tôi đã viết trong câu trả lời của mình: "Một lớp lồng tĩnh chỉ là một lớp không hoàn toàn có một tham chiếu đến một thể hiện của lớp bên ngoài."
Jon Skeet

6
@KhurramAli: Ý bạn là ngầm ? Họ chắc chắn không phải một cách rõ ràng tĩnh, cho rằng bạn không sử dụng từ khóa statickhi tuyên bố họ. Họ hoàn toàn tĩnh tại chỗ bạn không cần tham chiếu đến bất cứ điều gì khác để xây dựng nó. Cá nhân tôi thấy thuật ngữ tĩnh / không tĩnh hơi kỳ lạ đối với các lớp lồng nhau ... Tôi nghĩ rằng sẽ đơn giản hơn để nói về hành vi đó là gì.
Jon Skeet

157

Có một lớp lồng tĩnh , lớp [lồng nhau tĩnh] này không cần một thể hiện của lớp kèm theo để được khởi tạo chính nó.

Các lớp này [các lớp lồng nhau tĩnh] chỉ có thể truy cập các thành viên tĩnh của lớp kèm theo [vì nó không có bất kỳ tham chiếu nào đến các thể hiện của lớp kèm theo ...]

mẫu mã:

public class Test { 
  class A { } 
  static class B { }
  public static void main(String[] args) { 
    /*will fail - compilation error, you need an instance of Test to instantiate A*/
    A a = new A(); 
    /*will compile successfully, not instance of Test is needed to instantiate B */
    B b = new B(); 
  }
}

1
Vì vậy, chúng ta có thể nói rằng chúng ta có thể sử dụng các lớp tĩnh bên trong để khởi tạo chúng mà không cần phải công khai chúng không?
moldovean

@moldovean Chúng tôi sử dụng các lớp tĩnh bên trong để khởi tạo chúng từ một bối cảnh tĩnh (chẳng hạn như chính). Tôi không nghĩ nó có liên quan gì đến tầm nhìn.
Michael Dorst

2
@moldovean tĩnh / không tĩnh là trực giao với khả năng hiển thị. Bạn có thể có bất kỳ loại khả năng hiển thị nào với tĩnh hoặc không tĩnh. Vấn đề là, bạn có cần một thể hiện của lớp kèm theo, để tạo lớp bên trong không?
amit

103

Có một lớp lồng nhau tĩnh trong java. Khi bạn khai báo một lớp tĩnh lồng nhau, nó sẽ tự động trở thành một lớp độc lập có thể được khởi tạo mà không cần phải khởi tạo lớp bên ngoài mà nó thuộc về.

Thí dụ:

public class A
{

 public static class B
 {
 }
}

Bởi vì class Bđược khai báo tĩnh, bạn có thể khởi tạo một cách rõ ràng là:

B b = new B();

Lưu ý nếu class Bkhông được khai báo tĩnh để làm cho nó độc lập, một cuộc gọi đối tượng thể hiện sẽ giống như thế này:

A a= new A();
B b = a.new B();

7
lưu ý rằng bạn có thể khởi tạo lớp không tĩnh thường xuyên như B b = new B();nếu bạn đang cố gắng khởi tạo nó từ Achính Lớp đó.
Muhammed Refaat

33

Điều gì xảy ra khi một thành viên trong a classđược tuyên bố là static..? Các thành viên có thể được truy cập mà không cần khởi tạo class. Do đó làm cho lớp bên ngoài (lớp cấp cao nhất) statickhông có ý nghĩa. Do đó, nó không được phép.

Nhưng bạn có thể đặt các lớp bên trong là tĩnh (Vì nó là thành viên của lớp cấp cao nhất). Sau đó, lớp đó có thể được truy cập mà không cần khởi tạo lớp cấp cao nhất. Hãy xem xét ví dụ sau.

public class A {
    public static class B {

    }
}

Bây giờ, bên trong một lớp khác C, lớp Bcó thể được truy cập mà không cần tạo một thể hiện của lớp A.

public class C {
    A.B ab = new A.B();
}

staticCác lớp học cũng có thể có non-staticthành viên. Chỉ có lớp được tĩnh.

Nhưng nếu statictừ khóa bị xóa khỏi lớp B, nó không thể được truy cập trực tiếp mà không cần tạo một thể hiện của A.

public class C {
    A a = new A();
    A.B ab = a. new B();
}

Nhưng chúng ta không thể có staticcác thành viên trong một non-staticlớp bên trong.


Chúng ta có thể khởi tạo một lớp tĩnh hay nó có ý nghĩa?
Supun Wijerathne

6
Không giống như trong các ngôn ngữ khác, staticchỉ có một ý nghĩa trong java. Nếu một cái gì đó statictrong một lớp có nghĩa là thứ đó có thể được truy cập mà không cần khởi tạo lớp đó. Nó không nói bất cứ điều gì liên quan đến việc tạo ra các trường hợp hay không ..
Ramesh-X

Xin lỗi stackoverflow! Tôi không thể tránh nói Cảm ơn Ramesh-X trong trường hợp này! Bạn bao quát hầu hết mọi thứ tôi tự hỏi về các lớp bên trong tĩnh và các lớp bên trong.
moldovean

Bạn không thể 'đặt các lớp bên trong là tĩnh'. Đây là một mâu thuẫn trong điều khoản . Một lớp lồng nhau là bên trong hoặc tĩnh.
Hầu tước Lorne

13

Xem như đây là kết quả hàng đầu trên Google cho "java lớp tĩnh" và câu trả lời tốt nhất không có ở đây tôi nghĩ rằng tôi đã thêm nó. Tôi đang giải thích câu hỏi của OP liên quan đến các lớp tĩnh trong C #, được gọi là singletons trong thế giới Java. Đối với những người không biết, trong C #, từ khóa "tĩnh" có thể được áp dụng cho khai báo lớp, có nghĩa là lớp kết quả không bao giờ có thể được khởi tạo.

Trích từ "Java hiệu quả - Ấn bản thứ hai" của Joshua Bloch (được coi rộng rãi là một trong những hướng dẫn phong cách Java tốt nhất hiện có):

Kể từ phiên bản 1.5, có một cách tiếp cận thứ ba để thực hiện các singletons. Chỉ cần tạo một kiểu enum với một phần tử:

// Enum singleton - the preferred approach
public enum Elvis {
    INSTANCE;
    public void leaveTheBuilding() { ... }
}

Cách tiếp cận này có chức năng tương đương với cách tiếp cận lĩnh vực công cộng, ngoại trừ nó ngắn gọn hơn, cung cấp máy móc tuần tự hóa miễn phí và cung cấp bảo đảm bằng sắt chống lại nhiều lần khởi tạo, ngay cả khi đối mặt với các cuộc tấn công tuần tự hoặc phản xạ tinh vi. Trong khi phương pháp này vẫn chưa được áp dụng rộng rãi, một loại enum đơn yếu tố là cách tốt nhất để thực hiện một singleton. (tác giả nhấn mạnh)

Bloch, Joshua (2008-05-08). Java hiệu quả (Sê-ri Java) (trang 18). Giáo dục Pearson.

Tôi nghĩ rằng việc thực hiện và biện minh là khá tự giải thích.


6
Một cách tốt để thực hiện một Singleton. Thật không may, câu hỏi không phải là về Singletons, mà là về các lớp tĩnh
David SN

1
Java có một cách giải thích khá độc đáo về từ khóa "tĩnh". Có vẻ như OP đến từ C # trong đó "lớp tĩnh" tương đương với một đơn vị trong Java. Tôi đã cập nhật câu trả lời của mình để giải thích rõ ràng câu hỏi này.
Bennet Huber

1
Lớp tĩnh AC # không phải là Singleton. Một cá thể Singleton là một đối tượng và có thể thực hiện một giao diện có nghĩa là nó có thể tham gia vào quá trình tiêm phụ thuộc và có thể bị chế giễu. Lớp tĩnh AC # không thể thực hiện giao diện hoặc được chèn theo bất kỳ cách nào, và gần hơn rất nhiều với chỉ một hàm các hàm C, và tất nhiên cho phép các phương thức mở rộng.
Novaterata

13

Một lớp có thể tĩnh trong Java không?

Câu trả lời là , chúng ta có thể có lớp tĩnh trong java. Trong java, chúng ta có các biến đối tượng tĩnh cũng như các phương thức tĩnh và cả khối tĩnh . Các lớp cũng có thể được tạo tĩnh trong Java.

Trong java, chúng ta không thể làm cho lớp cấp cao nhất (bên ngoài) tĩnh. Chỉ các lớp lồng nhau có thể là tĩnh.

lớp lồng tĩnh vs lớp lồng không tĩnh

1) Lớp tĩnh lồng nhau không cần tham chiếu của lớp ngoài, nhưng lớp lồng không tĩnh hoặc lớp bên trong yêu cầu tham chiếu lớp ngoài.

2) Lớp bên trong (hoặc lớp lồng không tĩnh) có thể truy cập cả thành viên tĩnh và không tĩnh của lớp ngoài. Một lớp tĩnh không thể truy cập các thành viên không tĩnh của lớp Ngoài. Nó chỉ có thể truy cập các thành viên tĩnh của lớp ngoài.

xem tại đây: https://docs.oracle.com/javase/tutorial/java/javaOO/nested.html


các lớp 'không tĩnh' bên trong cũng không thể khai báo các trường hoặc phương thức tĩnh
Mr.Cat


2

Nói một cách đơn giản, Java hỗ trợ khai báo một lớp chỉ tĩnh đối với các lớp bên trong chứ không phải cho các lớp cấp cao nhất.

các lớp cấp cao nhất: Một dự án java có thể chứa nhiều hơn một lớp cấp cao nhất trong mỗi tệp nguồn java, một trong các lớp được đặt tên theo tên tệp. Chỉ có ba tùy chọn hoặc từ khóa được phép trước các lớp cấp cao nhất, công khai, trừu tượng và cuối cùng .

Các lớp bên trong: các lớp bên trong một lớp cấp cao nhất được gọi là các lớp bên trong, về cơ bản là khái niệm của các lớp lồng nhau. Các lớp bên trong có thể là tĩnh . Ý tưởng làm cho các lớp bên trong tĩnh, là tận dụng lợi thế của việc khởi tạo các đối tượng của các lớp bên trong mà không cần khởi tạo đối tượng của lớp cấp cao nhất. Điều này chính xác giống như các phương thức tĩnh và các biến hoạt động bên trong một lớp cấp cao nhất.

Do đó Java hỗ trợ các lớp tĩnh ở cấp độ bên trong (trong các lớp lồng nhau)

Và Java không hỗ trợ các lớp tĩnh ở các lớp cấp cao nhất.

Tôi hy vọng điều này mang lại một giải pháp đơn giản hơn cho câu hỏi để hiểu cơ bản về các lớp tĩnh trong Java.



0

Java có các phương thức tĩnh được liên kết với các lớp (ví dụ java.lang.Math chỉ có các phương thức tĩnh), nhưng bản thân lớp này không tĩnh.


0

Bạn không thể sử dụng từ khóa tĩnh với một lớp trừ khi đó là lớp bên trong. Một lớp bên trong tĩnh là một lớp lồng nhau là một thành viên tĩnh của lớp bên ngoài. Nó có thể được truy cập mà không cần khởi tạo lớp bên ngoài, sử dụng các thành viên tĩnh khác. Cũng giống như các thành viên tĩnh, một lớp lồng tĩnh không có quyền truy cập vào các biến và phương thức của lớp bên ngoài.

public class Outer {
   static class Nested_Demo {
      public void my_method() {
          System.out.println("This is my nested class");
      }
   }
public static void main(String args[]) {
      Outer.Nested_Demo nested = new Outer.Nested_Demo();
      nested.my_method();
   }
}

Bạn không thể sử dụng statictừ khóa với một lớp trừ khi đó là lớp lồng nhau . "Nội tĩnh" là một mâu thuẫn trong các điều khoản .
Hầu tước Lorne

0

Một phương thức tĩnh có nghĩa là nó có thể được truy cập mà không cần tạo một đối tượng của lớp, không giống như công khai:

public class MyClass {
   // Static method
   static void myStaticMethod() {
      System.out.println("Static methods can be called without creating objects");
   }

  // Public method
  public void myPublicMethod() {
      System.out.println("Public methods must be called by creating objects");
   }

  // Main method
  public static void main(String[ ] args) {
      myStaticMethod(); // Call the static method
    // myPublicMethod(); This would output an error

    MyClass myObj = new MyClass(); // Create an object of MyClass
    myObj.myPublicMethod(); // Call the public method
  }
}

Không trả lời câu hỏi.
Hầu tước Lorne

-1

Tất cả các câu trả lời tốt, nhưng tôi không thấy một tài liệu tham khảo nào về java.util.Collections sử dụng hàng tấn lớp bên trong tĩnh cho các phương thức hệ số tĩnh của chúng. Vì vậy, thêm như vậy.

Thêm một ví dụ từ java.util.Collections có nhiều lớp bên trong tĩnh. Các lớp bên trong rất hữu ích cho mã nhóm cần được truy cập thông qua lớp bên ngoài.

/**
 * @serial include
 */
static class UnmodifiableSet<E> extends UnmodifiableCollection<E>
                             implements Set<E>, Serializable {
    private static final long serialVersionUID = -9215047833775013803L;

    UnmodifiableSet(Set<? extends E> s)     {super(s);}
    public boolean equals(Object o) {return o == this || c.equals(o);}
    public int hashCode()           {return c.hashCode();}
}

Đây là phương thức hệ số tĩnh trong lớp java.util.Collections

public static <T> Set<T> unmodifiableSet(Set<? extends T> s) {
    return new UnmodifiableSet<>(s);
}


Không có bình luận của bạn? Bạn có thể xây dựng? Cố gắng để hiểu bình luận của bạn.
Jay Rajput
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.