Por que você não pode declarar uma classe como estática em Java?

459

Por que você não pode declarar uma classe como estática em Java?

Mariselvam
fonte
72
Contra-pergunta: qual seria o efeito se você declarasse uma classe de nível superior static?
Joachim Sauer
3
Não, você não pode, exceto as classes internas estáticas. Mas, o que você deseja alcançar com isso?
manolowar 27/08/10
60
@Joachim Sauer: Bem, o C # interpreta as staticclasses como abstract final, ou seja, elas não podem ser instanciadas e não podem ser estendidas. Isso significa que eles podem conter apenas membros estáticos, o que é útil para classes que contêm apenas métodos auxiliares.
BCAT
30
@cat é verdade para C #, mas uma classe java pode ser abstrata ou final, não ambas. Para impedir que uma classe seja instanciada, pode-se declarar um construtor privado.
Lorenzo Polidori
7
@JoachimSauer Simples, eu adoraria forçar todos os membros da classe a serem estáticos (talvez com até mesmo que declarar em cada método ou propriedade).
Hmartinezd

Respostas:

475

Somente classes aninhadas podem ser estáticas. Ao fazer isso, você pode usar a classe aninhada sem ter uma instância da classe externa.

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

Fontes :

Sobre o mesmo tópico:

Colin Hebert
fonte
3
+1, apesar de a primeira frase não ser exata. Como o tutorial afirma "Classes aninhadas não estáticas são chamadas de classes internas". (JLS: "Uma classe interna é uma classe aninhada que não é declarada estática de forma explícita ou explícita.")
user85421 27/08/10
74
Você certamente está certo; mas eu não vejo como isso responde à pergunta
Joeri Hendrickx
2
@Carlos Heuberger, você está certo, eu atualizei o post. @Joeri Hendrickx, A pergunta era: "por que uma classe não pode ser declarada como estática ...?", Eles podem e [leia meu post aqui]. É uma explicação sobre o uso de classes estáticas e por que elas precisam ser classes aninhadas.
Colin Hebert
1
A solução dada aqui é boa ... Mas eu ainda me pergunto: ypl não explicaram logicamente que classe estática não é possível em java ... alguma explicação do conceito de OOPs seria a resposta certa. Estou esperando por isso #
Punith Raj
9
Isso é verdade, mas a pergunta em que você está pensando geralmente se resolve quando você começa a se perguntar o que seria uma "classe estática". Em java, um elemento estático significa que você pode acessá-lo / invocá-lo sem uma instância da classe envolvente; o que isso poderia significar se você aplicar a palavra-chave à própria classe? Quais são suas intenções? O que você esperaria? Agora que você tem uma idéia do que poderia ser, tenho certeza de que será "realmente não faz sentido" ou "será muito buscado" (faria sentido, mas no final é apenas uma escolha) que foi feito).
Colin Hebert
39

As classes de nível superior são estáticas por padrão. Classes internas são não estáticas por padrão. Você pode alterar o padrão para classes internas marcando-as explicitamente estáticas. As classes de nível superior, em virtude de serem de nível superior, não podem ter semântica não estática porque não pode haver classe pai a que se referir. Portanto, não há como alterar o padrão para as classes de nível superior.

necromante
fonte
14
»As classes de nível superior são estáticas por padrão.« Esta é a melhor resposta. Eles são estáticos porque você não precisa de nenhuma instância de nada para se referir a eles. Eles podem ser referidos de qualquer lugar. Eles estão no armazenamento estático (como nas classes de armazenamento C). - Como outros observaram (Iain Elder em um comentário a outra resposta), os designers de idiomas poderiam ter permitido que a staticpalavra-chave em uma classe de nível superior denotasse e reforçasse que ela pode conter apenas membros estáticos e não ser instanciada; isso poderia, no entanto, confundir as pessoas, pois statictem um significado diferente para as classes aninhadas.
Lumi
35

Estou chegando atrasado à festa, mas aqui estão meus dois centavos - filosoficamente acrescentando à resposta de Colin Hebert.

Em um nível alto, sua pergunta lida com a diferença entre objetos e tipos. Embora existam muitos carros (objetos), há apenas uma classe de carros (tipo). Declarar algo como estático significa que você está operando no espaço "tipo". Há apenas um. A palavra-chave da classe de nível superior já define um tipo no espaço "type". Como resultado, "a classe estática pública Car" é redundante.

Eric Jankowski
fonte
1
Sim. Em outras palavras, as classes de nível superior são estáticas por padrão, portanto, não há necessidade da palavra-chave.
Warren Orvalho
1
Bem, eu acrescentaria o que Warren Dew disse: "as classes de nível superior são estáticas por padrão ao acessar membros estáticos".
Dexter
1
Resposta subestimada. Uma nova palavra-chave para forçar todos os métodos de uma classe a serem estáticos e o construtor private seria interessante. Eu não o chamaria de estático, porque isso é apenas confuso.
GDV
@G_V Embora o java possa criar esse monstro, o Java quase se esforça para dificultar as coisas estúpidas. A estática é uma péssima idéia, em geral, as classes estáticas são horríveis (Pior do que os singletons, que são considerados antipadrão). Muitas pessoas não entendem isso, portanto, dar uma palavra-chave seria uma péssima idéia. Em vez disso, dificultamos as coisas ruins e deixamos as coisas assim. Observe que também não há palavra-chave "Singleton". e nenhuma palavra-chave de propriedade. Estes todo o código causa ruim (Embora as pessoas ainda usam propriedades tanto que Java pode também apoiá-los)
Bill K
29

Classe com construtor privado é estática.

Declare sua turma assim:

public class eOAuth {

    private eOAuth(){}

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

}

e você pode usar sem inicialização:

if (value == eOAuth.ECodeOauthInvalidGrant)
    eOAuth.GetSomeStuff();
...
Sergey Vakulenko
fonte
3
Não é estático, mas contém propriedades estáticas. Se você escrever public final int ECodeOauthUnknown = 0x10; não é mais estático.
User1883212
9
Caso alguém esteja se perguntando o que está acontecendo aqui, isso corresponde à definição em C # de uma "classe estática" - msdn.microsoft.com/en-us/library/79b3xss3%28v=vs.90%29.aspx . Dada a definição Java de "classe estática", todas as classes não internas são estáticas (consulte as respostas dos irmãos).
Calum
1
Além de @ user1883212 estar certo, eu diria que essa resposta confunde o leitor de que o construtor privado é de alguma forma importante aqui, embora realmente não importe nada.
Tlwhitec
No mundo .NET, se uma classe for marcada como abstrata e final (o efeito de uma static classdeclaração em C #), o compilador nem permitirá que o código declare variáveis ​​desse tipo, nem a use como parâmetro de tipo genérico. Uma mera falta de construtores acessíveis em uma classe que poderia ser instanciada ou herdada não impediria a declaração de variáveis ​​desse tipo, nem seu uso como parâmetro de tipo genérico.
Supercat
Esta resposta está completamente incorreta. Construtores privados não têm nada a ver com isso. O código é apenas um exemplo de uma classe com nada além de atributos e métodos estáticos. Não tem nada a ver com classes estáticas.
Marquês de Lorne
13

Claro que podem, mas apenas classes internas aninhadas. Lá, isso significa que as instâncias da classe aninhada não requerem uma instância anexa da classe externa.

Porém, para as classes de nível superior, os designers de idiomas não conseguiram pensar em nada útil para fazer com a palavra-chave, portanto, não é permitido.

Michael Borgwardt
fonte
+1, apesar de a primeira frase não ser exata. Como o JLS afirma: "Uma classe interna é uma classe aninhada que não é declarada estática explícita ou implicitamente." (Just terminologia, eu sei ...)
user85421
7
Embora uma classe de nível superior não possa ser declarada static, às vezes faria sentido poder. Por exemplo, uma classe que contém apenas métodos auxiliares estáticos não faz sentido para ser instanciada, mas a linguagem Java não impede você de fazê-lo. Você pode tornar a classe não instável (e praticamente 'estática') para outras classes declarando o construtor padrão private, que proíbe a instanciação porque nenhum construtor está visível.
Iain Samuel McLean Elder
12

Você pode criar uma classe de utilitário (que não pode ter instâncias criadas) declarando um tipo de enum sem instâncias. ou seja, você está declarando especificamente que não há instâncias.

public enum MyUtilities {;
   public static void myMethod();
}
Peter Lawrey
fonte
25
uma enumeração como um tipo é uma expectativa específica: é um conjunto enumerado de itens. Usá-lo para uma "classe de utilitário", quando você poderia apenas ter uma classe com um construtor privado, é semanticamente confuso.
Visionary Software Solutions
5
@VisionarySoftwareSolutions Para mim, essa especificidade diz que não há instâncias dessa classe, em vez de indiretamente tornar impossível criar instâncias de uma classe.
precisa saber é o seguinte
8
public class Outer {
   public static class Inner {}
}

... pode ser declarado estático - desde que seja uma classe membro.

Do JLS:

As classes membro podem ser estáticas, caso em que não têm acesso às variáveis ​​de instância da classe circundante; ou eles podem ser classes internas (§8.1.3).

e aqui:

A palavra-chave estática pode modificar a declaração de um membro do tipo C dentro do corpo de uma classe não interna T. Seu efeito é declarar que C não é uma classe interna. Assim como um método estático de T não possui instância atual de T em seu corpo, C também não possui instância atual de T, nem possui instâncias lexicamente fechadas.

Uma palavra-chave estática não faria sentido para uma classe de nível superior, apenas porque uma classe de nível superior não possui um tipo de anexo.

Andreas Dolk
fonte
Se não é interior, por que chamá-lo Inner? Nestedteria sido uma escolha menos confusa.
Marquês de Lorne
5

Como explicado acima, uma classe não pode ser estática, a menos que seja membro de outra classe.

Se você deseja criar uma classe "da qual não pode haver várias instâncias", convém examinar o padrão de design "Singleton".

Informações sobre Singleton para iniciantes aqui .

Embargo:

Se você está pensando em usar o padrão singleton, resista com todas as suas forças. É um dos DesignPatterns mais fáceis de entender, provavelmente o mais popular e, definitivamente, o mais abusado. (fonte: JavaRanch como link acima)

S.Jones
fonte
4

Além de como o Java define classes internas estáticas, há outra definição de classes estáticas conforme o mundo C # [1] . Uma classe estática é aquela que possui apenas métodos estáticos (funções) e destina-se a oferecer suporte a programação procedural. Essas classes não são realmente classes, pois o usuário da classe está interessado apenas nas funções auxiliares e não na criação de instâncias da classe. Embora as classes estáticas sejam suportadas em C #, não existe esse suporte direto em Java. No entanto, você pode usar enumerações para imitar classes estáticas de C # em Java, para que um usuário nunca possa criar instâncias de uma determinada classe (mesmo usando reflexão) [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();
    }
}
shams
fonte
3

Tudo o que codificamos em java entra em uma classe. Sempre que executamos uma classe, a JVM instancia um objeto. A JVM pode criar vários objetos, por definição Estático significa que você tem o mesmo conjunto de cópias para todos os objetos.

Portanto, se Java permitiria que a classe superior fosse estática sempre que você executa um programa, ele cria um Objeto e continua substituindo o mesmo local da memória.

Se você está apenas substituindo o objeto toda vez que o executa, qual é o objetivo de criá-lo?

Portanto, esse é o motivo pelo qual o Java se livrou da estática da classe de nível superior.

Pode haver razões mais concretas, mas isso fez muito sentido lógico para mim.

user2626445
fonte
3
Classes internas estão associadas a classes externas e é por isso que elas podem ser estáticas, pois você tem um objeto diferente do qual confiar.
user2626445
1
Você quer dizer 'essa é a razão pela qual eles não podem ser estáticos'.
Marquês de Lorne,
2

As únicas classes que podem ser estáticas são as classes internas. O código a seguir funciona bem:

public class whatever {
    static class innerclass {
    }
}

O objetivo das classes internas estáticas é que elas não têm uma referência ao objeto de classe externa.

user2645256
fonte
1
'interior estático' é uma contradição em termos. 'estático' e 'interno' são mutuamente exclusivos. A palavra que você está procurando é 'aninhada', não 'interior'.
Marquês de Lorne
1

Eu acho que isso é possível tão fácil quanto beber um copo de café! Basta dar uma olhada nisso. Não usamos palavras-chave estáticas explicitamente ao definir classe.

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

Isso não é uma definição de classe estática? Nós apenas usamos uma função ligada a apenas uma classe. Tenha cuidado para que, neste caso, possamos usar outra classe nesse aninhado. Veja isso:

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);
    }
}
Erfankam
fonte
Acho que podemos considerar essas classes como classe estática, referindo-se à definição de classe estática, não apenas usando a palavra-chave estática como um qualificador.
Erfankam
Certifique-se de criar um construtor privado, caso contrário você seria capaz de dizer new StaticClass()e isso realmente não faz muito sentido. Com um construtor privado, não permitiria instâncias dele.
grinch
1

Pode-se observar no PlatformUIEclipse uma classe com métodos estáticos e construtor privado, sendo ele próprio final.

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

se o benefício de usar uma classe estática não era instanciar um objeto e usar um método, basta declarar a classe como pública e esse método como estático.

eeadev
fonte