Статические классы в Java

947

Есть ли что-нибудь, как static classв Java?

В чем смысл такого класса. Все ли методы статического класса должны бытьstatic тоже ?

Требуется ли наоборот, если класс содержит все статические методы, должен ли класс быть статическим?

Для чего нужны статические классы?

Kraken
источник
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 действительно был бы статическим.

Пол Сасик
источник
35
класс Fooтолько с staticметодами не совпадает сstatic class Foo
craigb
12
@Evorlor: если класс объявлен как final, то его методы автоматически (эффективно) являются финальными. Это связано с тем, что последний класс не может быть разделен на подклассы, и, следовательно, его методы не могут быть переопределены (то есть фактически являются окончательными). docs.oracle.com/javase/tutorial/java/IandI/final.html
jwayne
30
Этот ответ может быть связан с тем, что имел в виду OP, но он (в настоящее время) не объясняет статические классы Java и поэтому не отвечает на вопрос вообще! Это очень плохо для людей, которые пытаются понять, что означает статический класс в Java.
Том
12
@JBoy: В Java есть такая вещь, как «статический класс», о чем вопрос, но этот ответ совсем не объясняет. Вместо этого он объясняет, как имитировать в Java то, что ответ называет «статическим классом», но это не то, что «статический класс» в Java! (Может быть, это то, что называется «статическим классом» на некоторых других языках, но люди, приходящие сюда, чтобы узнать о статических классах Java, будут сбиты с толку и сбиты с толку.)
Том
4
Вы должны явно указать, что private MyStaticClass () {// приватный конструктор myStaticMember = 1; } не будет иметь никакого эффекта вообще, так как конструктор не будет вызван. Но это не главное. Я все еще очень озадачен полезностью статических внутренних классов в Java и их полезностью или добавленной стоимостью.
moldovean
316

Ну, у Java есть «статические вложенные классы», но они совсем не похожи на статические классы C #, если вы туда пришли. Статический вложенный класс - это просто класс, который неявно не имеет ссылки на экземпляр внешнего класса.

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

В Java нет такого понятия, как статический класс верхнего уровня.

Джон Скит
источник
12
В Java Почему статический вложенный класс допускает методы экземпляра? Какая польза от метода экземпляра в таком классе?
Компьютерщик
19
@ Geek: ты читал мой ответ? Прочитайте второе предложение внимательно. Почему бы вам не захотеть иметь методы экземпляров статических классов? В конце концов, вы можете создавать их экземпляры.
Джон Скит
17
@ Geek: Да, это вполне допустимо. Ваше «понимание», что статические классы являются служебными классами, в основном неверно. Это совсем не то, что означают статические классы в Java.
Джон Скит
14
@ Гик: Да. Точно так же, как я написал в своем ответе: «Статический вложенный класс - это всего лишь тот, который неявно не имеет ссылки на экземпляр внешнего класса».
Джон Скит
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 Мы используем внутренние статические классы, чтобы создавать их экземпляры из статического контекста (такого как main). Я не думаю, что это имеет какое-либо отношение к видимости.
Майкл Дорст
2
@moldovean static / non static ортогонален видимости. Вы можете иметь любой вид видимости со статическим или не статичным. Дело в том, нужен ли вам экземпляр окружающего класса, чтобы создать внутренний?
Амит
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внутреннего класса.

Рамеш-X
источник
Можем ли мы создать экземпляр статического класса или это имеет смысл?
Супун Вийератн
6
Не как в других языках, staticимеет только одно значение в Java. Если что-то находится staticв классе, это означает, что к нему можно получить доступ без создания экземпляра этого класса. Это ничего не говорит о создании экземпляров или нет ..
Рамеш-X
Извините, переполнение стека! Я не могу не сказать спасибо Рамеш-X в этом случае! Вы покрыли почти все, что я задавался вопросом о статических внутренних классах и внутренних классах.
moldovean
Вы не можете «установить внутренние классы как статические». Это противоречие в терминах . Вложенный класс является внутренним или статическим.
Маркиз Лорн
13

Видя, что это лучший результат в Google для "статического класса java", и лучший ответ здесь не здесь, я решил добавить его. Я интерпретирую вопрос OP относительно статических классов в C #, которые известны как синглтоны в мире Java. Для тех, кто не знает, в C # ключевое слово «static» может быть применено к объявлению класса, что означает, что результирующий класс никогда не может быть создан.

Отрывок из «Эффективного Java - Второе издание» Джошуа Блоха (широко считается одним из лучших доступных руководств по стилю Java):

Начиная с версии 1.5, существует третий подход к реализации синглетонов. Просто создайте тип enum с одним элементом:

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

Этот подход функционально эквивалентен общедоступному полевому подходу, за исключением того, что он более лаконичен, предоставляет механизм сериализации бесплатно и обеспечивает железную гарантию от множественных экземпляров, даже перед сложными атаками сериализации или отражения. Хотя этот подход еще не получил широкого распространения, одноэлементный тип перечисления является лучшим способом реализации синглтона. (выделение автора)

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

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

Беннет Хубер
источник
6
Хороший способ реализовать Singleton. К сожалению, вопрос не о синглетонах, а о статических классах
Дэвид С.Н.
1
У Java довольно уникальная интерпретация «статического» ключевого слова. Похоже, что OP исходит из C #, где «статический класс» является эквивалентом синглтона в Java. Я обновил свой ответ, чтобы прояснить эту интерпретацию вопроса.
Беннет Хубер
1
Статический класс AC # не является Singleton. Экземпляр Singleton - это объект, который может реализовывать интерфейс, что означает, что он может участвовать в внедрении зависимостей и может быть имитирован. Статический класс AC # не может реализовывать интерфейс или вводиться каким-либо образом, и гораздо ближе к просто группе функций C, и, конечно, допускает методы расширения.
Новатерата
13

Может ли класс быть статическим в Java?

Ответ ДА , у нас может быть статический класс в Java. В Java у нас есть статические переменные экземпляра, а также статические методы, а также статический блок . Классы также можно сделать статическими в Java.

В Java мы не можем сделать класс верхнего уровня (внешний) статическим. Только вложенные классы могут быть статическими.

статический вложенный класс против нестатического вложенного класса

1) Вложенный статический класс не нуждается в ссылке на внешний класс, но нестатический вложенный класс или внутренний класс требует ссылки на внешний класс.

2) Внутренний класс (или нестатический вложенный класс) может обращаться как к статическим, так и к нестатическим членам класса Outer. Статический класс не может получить доступ к нестатическим членам класса Outer. Он может получить доступ только к статическим членам класса Outer.

смотрите здесь: https://docs.oracle.com/javase/tutorial/java/javaOO/nested.html

roottraveller
источник
также внутренние «не статические» классы не могут объявлять статические поля или методы
Mr.Cat
8

Внешние классы не могут быть статическими, но могут быть вложенные / внутренние классы. Это в основном помогает вам использовать вложенный / внутренний класс без создания экземпляра внешнего класса.

Сакет
источник
2

Проще говоря, Java поддерживает объявление класса статичным только для внутренних классов, но не для классов верхнего уровня.

классы верхнего уровня: проект Java может содержать более одного класса верхнего уровня в каждом исходном файле Java, один из классов назван в честь имени файла. Перед классами верхнего уровня допускаются только три параметра или ключевые слова: public, abstract и final .

Внутренние классы: классы, которые находятся внутри класса верхнего уровня, называются внутренними классами, что в основном является концепцией вложенных классов. Внутренние классы могут быть статичными . Идея сделать статические внутренние классы состоит в том, чтобы воспользоваться преимуществами создания экземпляров объектов внутренних классов без создания экземпляра объекта класса верхнего уровня. Это точно так же, как статические методы и переменные работают внутри класса верхнего уровня.

Следовательно, Java поддерживает статические классы на уровне внутреннего класса (во вложенных классах)

И Java не поддерживает статические классы на классах верхнего уровня.

Я надеюсь, что это дает более простое решение вопроса для базового понимания статических классов в Java.

saichand
источник
0

В Java есть статические методы, которые связаны с классами (например, java.lang.Math имеет только статические методы), но сам класс не является статическим.

duffymo
источник
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ключевое слово с классом, если это не вложенный класс. «Статическое внутреннее» является противоречием в терминах .
Маркиз Лорн
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
  }
}
dJack
источник
Не отвечает на вопрос.
Маркиз Лорн
-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);
}
Джей Раджпут
источник
Не получили ваш комментарий? Можете ли вы уточнить? Пытаюсь понять твой комментарий.
Джей Раджпут