Почему вы не можете объявить класс статическим в Java?

Почему вы не можете объявить класс статическим в Java?

14 ответов

Решение

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

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

Источники:

На ту же тему:

Классы верхнего уровня являются статическими по умолчанию. Внутренние классы не являются статичными по умолчанию. Вы можете изменить значение по умолчанию для внутренних классов, явно пометив их как статические. Классы верхнего уровня, в силу того, что они являются верхними уровнями, не могут иметь нестатическую семантику, потому что не может быть родительского класса, на который можно ссылаться. Следовательно, нет способа изменить значение по умолчанию для классов верхнего уровня.

Итак, я опаздываю на вечеринку, но вот мои два цента - философски добавляю к ответу Колина Хеберта.

На высоком уровне ваш вопрос касается разницы между объектами и типами. В то время как существует много автомобилей (объектов), существует только один класс (тип) автомобилей. Объявление чего-либо как статического означает, что вы работаете в пространстве типа. Здесь только один. Ключевое слово класса верхнего уровня уже определяет тип в пространстве "type". В результате "общедоступный статический класс Car" является избыточным.

Класс с приватным конструктором является статическим.

Объявите свой класс следующим образом:

public class eOAuth {

    private eOAuth(){}

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

}

и вы можете использовать без инициализации:

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

Вы можете создать служебный класс (который не может создавать экземпляры), объявив тип enum без экземпляров. то есть вы конкретно заявляете, что нет никаких экземпляров.

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

Конечно, они могут, но только внутренние вложенные классы. Там это означает, что экземпляры вложенного класса не требуют включения внешнего класса.

Но для классов верхнего уровня разработчики языка не могли придумать ничего полезного, связанного с ключевым словом, поэтому это запрещено.

public class Outer {
   public static class Inner {}
}

... он может быть объявлен как статический, если он является членом класса.

Из JLS:

Классы-члены могут быть статическими, и в этом случае они не имеют доступа к переменным экземпляра окружающего класса; или они могут быть внутренними классами (§8.1.3).

и здесь:

Ключевое слово static может изменить объявление типа члена C в теле не внутреннего класса T. Его эффект - объявить, что C не является внутренним классом. Так же, как статический метод T не имеет текущего экземпляра T в своем теле, C также не имеет текущего экземпляра T и не имеет каких-либо лексически включающих экземпляров.

Ключевое слово static не имеет никакого смысла для класса верхнего уровня, просто потому, что класс верхнего уровня не имеет вложенного типа.

Как объяснено выше, класс не может быть статичным, если он не является членом другого класса.

Если вы хотите создать класс, "которого не может быть несколько экземпляров", вы можете захотеть взглянуть на шаблон проектирования "Singleton".

Информация для начинающих Singleton здесь.

Предостережение:

Если вы думаете об использовании шаблона синглтона, сопротивляйтесь изо всех сил. Это один из самых простых в понимании DesignPatterns, возможно, самый популярный и, безусловно, наиболее злоупотребляемый. (источник: JavaRanch, как указано выше)

В дополнение к тому, как Java определяет статические внутренние классы, есть еще одно определение статических классов согласно миру C# [1]. Статический класс - это класс, который имеет только статические методы (функции) и предназначен для поддержки процедурного программирования. Такие классы на самом деле не являются классами, так как пользователь класса интересуется только вспомогательными функциями, а не созданием экземпляров класса. Хотя статические классы поддерживаются в C#, в Java такой прямой поддержки не существует. Однако вы можете использовать перечисления для имитации статических классов C# в Java, чтобы пользователь никогда не мог создавать экземпляры данного класса (даже используя отражение) [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();
    }
}

Все, что мы кодируем в Java, входит в класс. Всякий раз, когда мы запускаем класс, JVM создает объект. JVM может создавать несколько объектов, по определению Static означает, что у вас одинаковый набор копий для всех объектов.

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

Если Вы просто заменяете объект каждый раз, когда запускаете его, какой смысл его создавать?

Вот почему Java избавилась от статики для класса верхнего уровня.

Могут быть и более конкретные причины, но для меня это логично.

Единственными классами, которые могут быть статическими, являются внутренние классы. Следующий код работает просто отлично:

public class whatever {
    static class innerclass {
    }
}

Суть статических внутренних классов в том, что они не имеют ссылки на объект внешнего класса.

Можно посмотреть на PlatformUI в Eclipse для класса со статическими методами и приватного конструктора с самим собой быть финальным.

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

Я думаю, что это возможно так же просто, как выпить стакан кофе! Просто взгляните на это. Мы не используем статическое ключевое слово явно при определении класса.

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

Разве это не определение статического класса? Мы просто используем функцию, связанную только с классом. Будьте осторожны, чтобы в этом случае мы могли использовать другой класс из этого вложенного. Посмотри на это:

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

Если преимущество использования статического класса не в том, чтобы создавать экземпляр объекта и использовать метод, тогда просто объявите класс как открытый, а этот метод как статический.

Другие вопросы по тегам