Статичні класи на Java


947

Чи є щось схоже static classна java?

Яке значення має такий клас. Чи потрібно також використовувати всі методи статичного класу static?

Чи потрібно навпаки, якщо клас містить усі статичні методи, чи клас теж повинен бути статичним?

Для чого хороші статичні класи?


4
Можливо, вас зацікавить stackoverflow.com/questions/3584113/java-static-class
Іштар

Статичні класи в основному використовуються для групування класів разом.
RockingDev

Відповіді:


847

У Java є статичні вкладені класи, але це здається, що ви шукаєте статичний клас вищого рівня. У Java немає можливості зробити статичний клас вищого рівня, але ви можете імітувати статичний клас таким чином:

  • Заявіть про свій клас final- запобігає розширенню класу, оскільки розширення статичного класу не має сенсу
  • Зробити конструктор private- запобігає створення екземплярів за допомогою клієнтського коду, оскільки немає сенсу створювати статичний клас
  • Зробіть всі члени та функції класу static- Оскільки клас не може бути ініційований, жодні методи екземплярів не можуть викликатися або доступними полями екземпляра
  • Зауважте, що компілятор не завадить вам оголосити член (нестатичний) член. Проблема з’явиться лише у випадку спроби викликати члена екземпляра

Простий приклад на пропозиції зверху:

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;
    }
}

Чим хороші статичні класи? Гарне використання статичного класу полягає у визначенні одноразових, корисних та / або бібліотечних класів, де обґрунтування не має сенсу. Чудовий приклад - клас Math, який містить деякі математичні константи, такі як PI і E, і просто забезпечує математичні розрахунки. Вимагати примірника в такому випадку було б зайвим і заплутаним. Дивіться Mathклас та вихідний код . Зауважте, що воно є finalі всі його члени є static. Якби Java дозволяла оголошувати класи вищого рівня, staticто клас Math справді був би статичним.


34
клас Fooз лише staticметодами - це не те саме, щоstatic class Foo
craigb

12
@Evorlor: Якщо клас оголошено остаточним, його методи автоматично (ефективно) є остаточними. Це відбувається тому, що остаточний клас не можна підкласифікувати, і тому його методи не можуть бути замінені (тобто фактично є остаточними). docs.oracle.com/javase/tutorial/java/IandI/final.html
jwayne

30
Ця відповідь, можливо, стосується того, що мав на увазі ОП, але він (наразі) не пояснює статичні класи Java, а значить, взагалі не відповідає на питання! Це дуже погано для людей, які потрапляють сюди, намагаючись зрозуміти, що означає статичний клас на Java.
Том

12
@JBoy: У Java існує таке поняття, як "статичний клас", про що йдеться, але ця відповідь зовсім не пояснює. Натомість, це пояснює, як моделювати на Java те, що відповідь називає "статичним класом" - але що не є "статичним класом" у Java! (Можливо, це називається "статичним класом" якоюсь іншою мовою), але люди, які приїжджають сюди, щоб дізнатися про статичні класи Java, будуть введені в оману і плутаються.)
Том

4
ви повинні чітко згадати, що приватний MyStaticClass () {// приватний конструктор myStaticMember = 1; } взагалі не матиме ефекту, оскільки конструктор не буде викликаний. Але це не в цьому справа. Я все ще дуже плутаюсь щодо корисності статичних внутрішніх класів у Java та їх корисності чи додатковій вартості.
moldovean

315

Ну, у Java є "статичні вкладені класи", але вони зовсім не такі, як статичні класи C #, якщо звідки ви родом. Статичний вкладений клас - це лише той, який неявно не має посилання на екземпляр зовнішнього класу.

Статичні вкладені класи можуть мати методи екземпляра та статичні методи.

У Java немає такого поняття, як статичний клас вищого рівня.


12
На Java Чому статичний вкладений клас допускає методи екземплярів? Яке використання методу екземпляра в такому класі?
Geek

19
@Geek: Ви читали мою відповідь? Прочитайте уважно друге речення. Чому б ви не хотіли мати можливість застосувати методи екземплярів статичних класів? Зрештою, ви можете створювати їх екземпляри.
Джон Скіт

17
@Geek: Так, це повністю дозволено. Ваше "розуміння", що статичні класи - це корисні класи, в основному невірно. Це зовсім не те, що означають статичні класи на Java.
Джон Скіт

14
@Geek: Так. Саме так, як я писав у своїй відповіді: "Статичний вкладений клас - це лише той, який не позначається неявно посиланням на екземпляр зовнішнього класу".
Джон Скіт

6
@KhurramAli: Ви маєте на увазі неявно ? Вони, звичайно, не є явно статичними, враховуючи, що ви не використовуєте ключове слово staticпід час їх декларування. Вони неявно статичні в тому, що вам не потрібно посилатися ні на що інше, щоб побудувати його. Особисто я вважаю, що статична / нестатична термінологія все-таки трохи дивна для вкладених класів ... Я думаю, було б простіше говорити про те, що таке поведінка.
Джон Скіт

157

Існує статичний вкладений клас , цьому [статичному вкладеному] класу не потрібен екземпляр класу , що вкладається, щоб самому інстанціюватися.

Ці класи [статичні вкладені] можуть отримати доступ лише до статичних членів класу, що вкладається [оскільки він не має посилання на екземпляри класу, що додається ...]

зразок коду:

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
Тож чи можемо ми сказати, що ми можемо використовувати внутрішні статичні класи для того, щоб їх інстанціювати, не потребуючи оприлюднення?
moldovean

@moldovean Ми використовуємо внутрішні статичні класи для того, щоб придумати їх із статичного контексту (наприклад, основного). Я не думаю, що це стосується наочності.
Майкл Дорст

2
@moldovean статичний / нестатичний є ортогональним для видимості. Ви можете мати будь-який вид видимості з статичною або нестатичною. Справа в тому, чи потрібен вам екземпляр класу, що додається, щоб створити внутрішній?
Аміт

103

Так, у Java є статичний вкладений клас. Коли ви оголошуєте вкладений клас статичним, він автоматично перетворюється на окремий клас, який може бути створений без інстанції зовнішнього класу, до якого він належить.

Приклад:

public class A
{

 public static class B
 {
 }
}

Оскільки class Bце оголошено статичним, ви можете явно створювати інстанцію як:

B b = new B();

Зауважте, якби class Bне було оголошено статичним, щоб зробити його самостійним, виклик об'єкта екземпляра виглядав би так:

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

7
зауважте, що ви можете регулярно B b = new B();створювати нестатичний клас, як, якщо намагаєтесь інстанціювати його від самого класу A.
Мухаммед Рефаат

33

Що відбувається, коли члени всередині а classоголошуються як static..? Доступ до цих членів можна отримати без ініціативи class. Тому робити зовнішній клас (клас вищого рівня) staticне має жодного значення. Тому це не дозволяється.

Але можна встановити внутрішні класи як статичні (Оскільки він є членом класу вищого рівня). Тоді до цього класу можна отримати доступ, не встановлюючи клас верхнього рівня. Розглянемо наступний приклад.

public class A {
    public static class B {

    }
}

Тепер всередині іншого класу можна отримати доступ до класу C, Bне роблячи примірника класу A.

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

staticкласи можуть мати і non-staticчленів. Лише клас стає статичним.

Але якщо staticключове слово видалено з класу B, до нього не можна отримати доступ безпосередньо без створення екземпляра A.

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

Але ми не можемо мати staticчленів у non-staticвнутрішньому класі.


Чи можемо ми створити статичний клас чи це має сенс?
Supun Wijerathne

6
Як і в інших мовах, staticмає лише одне значення у Java. Якщо щось є staticв класі, це означає, що до нього можна отримати доступ без інстанції цього класу. Це нічого не говорить про створення екземплярів чи ні ..
Ramesh-X

Вибачте stackoverflow! Я не можу уникнути сказати спасибі Рамеш-Х у цьому випадку! Ви висвітлювали майже все, що мені було цікаво про статичні внутрішні класи та внутрішні класи.
moldovean

Ви не можете встановити внутрішні класи як статичні. Це суперечність в термінах . Вкладений клас є внутрішнім або статичним.
користувач207421

13

Бачачи, що це найкращий результат в Google для "статичного класу Java", і найкращої відповіді немає тут, я подумав, що додам його. Я інтерпретую питання ОП щодо статичних класів у C #, які в світі Java відомі як одиночні. Для тих, хто не знає, у C # "статичне" ключове слово може бути застосоване до декларації класу, що означає, що отриманий клас ніколи не може бути ініційований.

Уривок з "Ефективна Java - друге видання" Джошуа Блоха (широко вважається одним з найкращих посібників стилю Java):

Станом на версію 1.5 існує третій підхід до впровадження одиночних кнопок. Просто зробіть тип enum з одним елементом:

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

Цей підхід функціонально еквівалентний підходу на публічному полю, за винятком того, що він більш стислий, забезпечує механізм серіалізації безкоштовно та забезпечує гарантію залізобезпеки проти багаторазових інстанцій, навіть за умови складних серіалізаційних або рефлексійних атак. Незважаючи на те, що цей підхід ще не набув широкого поширення, одноелементний тип enum є найкращим способом реалізації синглтона. (акцент авторський)

Блох, Джошуа (2008-05-08). Ефективна Java (серія Java) (стор. 18). Пірсон освіта.

Я думаю, що реалізація та обґрунтування досить зрозумілі.


6
Хороший спосіб втілити синглтон. На жаль, питання не про Singletons, а про статичні класи
David SN

1
У Java є досить унікальна інтерпретація "статичного" ключового слова. Схоже, що ОП походить від C #, де "статичний клас" еквівалент сингтона на Java. Я оновив свою відповідь, щоб зрозуміти таке тлумачення питання.
Беннет Хубер

1
Статичний клас AC # не є одиночним. Екземпляр Singleton є об'єктом і може реалізовувати інтерфейс, що означає, що він може брати участь у введенні залежностей і може бути глузливим. Статичний клас AC # не може реалізувати інтерфейс або будь-яким чином вводити його, і він набагато ближчий лише до групи функцій C, і, звичайно, дозволяє розширити методи.
Новатерата

13

Чи може стати клас статичним на Java?

Відповідь ТАК , ми можемо мати статичний клас у java. У Java ми маємо статичні змінні екземпляра , а також статичні методи, а також статичний блок . Класи також можуть бути статичними на Java.

У Java, ми не можемо зробити статистика верхнього рівня (зовнішня) статичною. Лише вкладені класи можуть бути статичними.

статичний вкладений клас проти нестатичний вкладений клас

1) Вкладений статичний клас не потребує посилання на Зовнішній клас, але для нестатичного вкладеного класу або Внутрішнього класу потрібна посилання на Зовнішній клас.

2) Внутрішній клас (або нестатичний вкладений клас) може отримати доступ як до статичних, так і до нестатичних членів Зовнішнього класу. Статичний клас не може отримати доступ до нестатичних членів Зовнішнього класу. Він може отримати доступ лише до статичних членів Зовнішнього класу.

дивіться тут: https://docs.oracle.com/javase/tutorial/java/javaOO/nested.html


також внутрішні "нестатичні" класи не можуть оголосити статичні поля чи методи
Mr.Cat

8

Зовнішні класи не можуть бути статичними, але можуть бути вкладені / внутрішні класи. Це в основному допомагає вам використовувати вкладений / внутрішній клас без створення екземпляра зовнішнього класу.



2

Простіше кажучи, Java підтримує оголошення класу статичним лише для внутрішніх класів, але не для класів вищого рівня.

класи вищого рівня: Проект java може містити більше одного класу верхнього рівня у кожному вихідному файлі java, один з класів має ім'я файлу. Перед класами вищого рівня доступні лише три варіанти або ключові слова, загальнодоступні, реферативні та заключні .

Внутрішні класи: класи, що знаходяться всередині класу вищого рівня, називаються внутрішніми класами, що в основному є концепцією вкладених класів. Внутрішні класи можуть бути статичними . Ідея, що робить внутрішні класи статичними, полягає в тому, щоб скористатися перевагою інстанцізації об'єктів внутрішніх класів без інстанції об'єкта класу вищого рівня. Це точно так само, як статичні методи та змінні працюють у класі вищого рівня.

Отже, Java підтримує статичні класи на рівні внутрішнього класу (у вкладених класах)

І Java не підтримує статичні класи на класах вищого рівня.

Я сподіваюся, що це дає простіше рішення питання для основного розуміння статичних класів на Java.



0

У Java є статичні методи, пов'язані з класами (наприклад, java.lang.Math має лише статичні методи), але сам клас не є статичним.


0

Ви не можете використовувати статичне ключове слово з класом, якщо це не внутрішній клас. Статичний внутрішній клас - це вкладений клас, який є статичним членом зовнішнього класу. Доступ до нього можна отримати без екземплярів зовнішнього класу, використовуючи інші статичні елементи. Як і статичні члени, статичний вкладений клас не має доступу до змінних екземплярів та методів зовнішнього класу.

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();
   }
}

Ви не можете використовувати staticключове слово з класом, якщо це не вкладений клас. "Статичний внутрішній" - це протиріччя в термінах .
користувач207421

0

Статичний метод означає, що до нього можна отримати доступ, не створюючи об’єкт класу, на відміну від public:

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
  }
}

Не відповідає на запитання.
користувач207421

-1

Усі добрі відповіді, але я не бачив посилання на java.util.Collections, який використовує тонни статичного внутрішнього класу для своїх методів статичного фактора. Тож додавши те саме.

Додаємо приклад з java.util.Collections, який має кілька статичних внутрішніх класів. Внутрішні класи корисні для групового коду, до якого потрібно отримати доступ через зовнішній клас.

/**
 * @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();}
}

Ось метод статичного фактора в класі java.util.Collections

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


Не отримали ваш коментар? Чи можете ви докладно? Намагаюся зрозуміти ваш коментар.
Джей Раджпут
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.