¿Por qué no puede declarar una clase como estática en Java?

459

¿Por qué no puede declarar una clase como estática en Java?

Mariselvam
fuente
72
Contrapregunta: ¿cuál esperarías que sea el efecto si declaras que es una clase de nivel superior static?
Joachim Sauer
3
No, no puedes, excepto para las clases internas estáticas. Pero, ¿qué quieres lograr con eso?
manolowar
6060
@Joachim Sauer: Bueno, C # interpreta las staticclases como abstract final, es decir, no se pueden instanciar y no se pueden extender. Esto significa que solo pueden contener miembros estáticos, lo cual es útil para clases que solo contienen métodos auxiliares.
bcat
30
@bcat esto es cierto para C #, pero una clase java puede ser abstracta o final, no ambas. Para evitar que se instancia una clase, se puede declarar un constructor privado.
Lorenzo Polidori
77
@JoachimSauer Simple, me encantaría forzar a todos los miembros de la clase a estar estáticos (tal vez incluso tengan que declarar en cada método o propiedad).
hmartinezd

Respuestas:

475

Solo las clases anidadas pueden ser estáticas. Al hacerlo, puede usar la clase anidada sin tener una instancia de la clase 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();
}

Fuentes:

Sobre el mismo tema:

Colin Hebert
fuente
3
+1 a pesar de que la primera frase no es exacta. Como dice el tutorial "Las clases anidadas no estáticas se denominan clases internas". (JLS: "Una clase interna es una clase anidada que no se declara estática explícita o implícitamente".)
user85421
74
Ciertamente tienes razón; pero no veo cómo esto responde la pregunta
Joeri Hendrickx
2
@Carlos Heuberger, tienes razón, actualicé la publicación. @Joeri Hendrickx, la pregunta era, "¿por qué una clase no puede declararse como estática ...?", Sí pueden, y [lea mi publicación aquí]. Es una explicación sobre el uso de clases estáticas y por qué tienen que ser clases anidadas.
Colin Hebert
1
La solución dada aquí está bien ... Pero todavía me pregunto si la gente no ha explicado lógicamente que la clase estática no es posible en Java ... algunas explicaciones del concepto de POO serían la respuesta correcta. Lo estoy esperando
Punith Raj
99
Eso es cierto, pero la pregunta en la que está pensando generalmente se resuelve cuando comienza a preguntarse qué sería una "clase estática". En java, un elemento estático significa que puede acceder / invocarlo sin una instancia de la clase adjunta; ¿Qué podría significar eso si aplica la palabra clave a la clase misma? ¿Cuáles son tus intenciones? ¿Qué esperarías? Ahora que tiene una idea de lo que podría ser, estoy bastante seguro de que será "realmente no tiene sentido" o será "descabellado" (tendría sentido, pero al final es solo una elección eso ha sido hecho).
Colin Hebert
39

Las clases de nivel superior son estáticas por defecto. Las clases internas no son estáticas por defecto. Puede cambiar el valor predeterminado para las clases internas marcándolas explícitamente como estáticas. Las clases de nivel superior, en virtud de ser de nivel superior, no pueden tener una semántica no estática porque no puede haber una clase principal a la que hacer referencia. Por lo tanto, no hay forma de cambiar el valor predeterminado para las clases de nivel superior.

nigromante
fuente
14
»Las clases de nivel superior son estáticas por defecto.« Esta es la mejor respuesta. Son estáticos porque no necesita ninguna instancia de nada para referirse a ellos. Se puede consultar desde cualquier lugar. Están en almacenamiento estático (como en las clases de almacenamiento C). - Como otros han notado (Iain Elder en un comentario a otra respuesta), los diseñadores de lenguaje podrían haber permitido que la staticpalabra clave en una clase de nivel superior denotara y aplicara que solo puede contener miembros estáticos y no ser instanciada; Sin embargo, eso podría haber confundido a las personas, ya que statictiene un significado diferente para las clases anidadas.
Lumi
35

Entonces, llego tarde a la fiesta, pero aquí están mis dos centavos, filosóficamente añadiendo a la respuesta de Colin Hebert.

En un nivel alto, su pregunta trata la diferencia entre objetos y tipos. Si bien hay muchos automóviles (objetos), solo hay una clase de automóviles (tipo). Declarar algo como estático significa que está operando en el espacio "tipo". Sólo hay uno. La palabra clave de clase de nivel superior ya define un tipo en el espacio "tipo". Como resultado, el "automóvil de clase estática pública" es redundante.

Eric Jankowski
fuente
1
Si. En otras palabras, las clases de nivel superior son estáticas por defecto, por lo que no hay necesidad de la palabra clave.
Warren Dew
1
Bueno, añadiría a lo que dijo Warren Dew: "las clases de nivel superior son estáticas por defecto cuando acceden a miembros estáticos".
Dexter
1
Respuesta infravalorada. Una nueva palabra clave para forzar que cada método en una clase sea estático y el constructor privado sería bueno. No lo llamaría estático porque eso es confuso.
G_V
@G_V Aunque Java podría crear un monstruo así, Java casi hace todo lo posible para dificultar las cosas estúpidas. La estática es una mala idea en general, las clases estáticas son horribles (peor que los singletons que se consideran un antipatrón). Muchas personas no entienden esto, por lo que darle una palabra clave sería una muy mala idea. En cambio, hacemos las cosas malas difíciles y simplemente lo dejamos así. Tenga en cuenta que tampoco hay una palabra clave "Singleton". y sin palabra clave de propiedad. Todo esto causa un código incorrecto (aunque la gente todavía usa las propiedades tanto que Java también podría admitirlas)
Bill K
29

La clase con constructor privado es estática.

Declara tu clase así:

public class eOAuth {

    private eOAuth(){}

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

}

y puedes usar sin inicialización:

if (value == eOAuth.ECodeOauthInvalidGrant)
    eOAuth.GetSomeStuff();
...
Sergey Vakulenko
fuente
3
No es estático, pero contiene propiedades estáticas. Si escribe public final int ECodeOauthUnknown = 0x10; Ya no es estático.
user1883212
99
En caso de que alguien se pregunte qué está pasando aquí, esto coincide con la definición de C # de una "clase estática": msdn.microsoft.com/en-us/library/79b3xss3%28v=vs.90%29.aspx . Dada la definición de Java de "clase estática", todas las clases no internas son estáticas (ver respuestas de hermanos).
Calum
1
Aparte de @ user1883212 tiene razón, incluso diría que esta respuesta confunde al lector que el constructor privado es de alguna manera importante aquí, mientras que realmente no importa en absoluto.
tlwhitec
En el mundo .NET, si una clase se marca como abstracta y final (el efecto de una static classdeclaración en C #), el compilador ni siquiera permitirá que el código declare variables de ese tipo, ni lo usará como un parámetro de tipo genérico. La mera falta de constructores accesibles en una clase que de otro modo podría ser instanciada o heredada no impediría la declaración de variables de ese tipo, ni su uso como parámetro de tipo genérico.
supercat
Esta respuesta es completamente incorrecta. Los constructores privados no tienen nada que ver con eso. El código es solo un ejemplo de una clase con nada más que atributos y métodos estáticos. No tiene nada que ver con las clases estáticas.
Marqués de Lorne
13

Claro que pueden, pero solo clases anidadas internas . Allí, significa que las instancias de la clase anidada no requieren una instancia de cierre de la clase externa.

Pero para las clases de nivel superior, los diseñadores de idiomas no podían pensar en nada útil que hacer con la palabra clave, por lo que no está permitido.

Michael Borgwardt
fuente
+1 a pesar de que la primera frase no es exacta. Como dice el JLS: "Una clase interna es una clase anidada que no se declara estática explícita o implícitamente". (Solo terminología, lo sé ...)
user85421
77
Aunque no se puede declarar una clase de nivel superior static, a veces tiene sentido poder hacerlo. Por ejemplo, una clase que contiene solo métodos auxiliares estáticos no tiene sentido ser instanciada, pero el lenguaje Java no le impide hacerlo. Puede hacer que la clase no sea instanciable (y prácticamente 'estática') para otras clases declarando el constructor predeterminado private, que prohíbe la creación de instancias porque no hay ningún constructor visible.
Iain Samuel McLean Élder
12

Puede crear una clase de utilidad (que no puede tener instancias creadas) declarando un tipo de enumeración sin instancias. es decir, usted declara específicamente que no hay instancias.

public enum MyUtilities {;
   public static void myMethod();
}
Peter Lawrey
fuente
25
Una enumeración como tipo es una expectativa específica: es un conjunto de elementos enumerados. Usarlo para una "clase de utilidad", cuando de otro modo solo podría tener una clase con un constructor privado, es semánticamente confuso.
Visionary Software Solutions el
55
@VisionarySoftwareSolutions Para mí, esta especificidad dice que no hay instancias de esta clase, en lugar de hacer indirectamente imposible crear instancias de una clase.
Peter Lawrey
8
public class Outer {
   public static class Inner {}
}

... se puede declarar estático, siempre que sea una clase miembro.

De la JLS:

Las clases miembro pueden ser estáticas, en cuyo caso no tienen acceso a las variables de instancia de la clase circundante; o pueden ser clases internas (§8.1.3).

y aquí:

La palabra clave estática puede modificar la declaración de un miembro tipo C dentro del cuerpo de una clase T. no interna. Su efecto es declarar que C no es una clase interna. Del mismo modo que un método estático de T no tiene una instancia actual de T en su cuerpo, C tampoco tiene una instancia actual de T, ni tampoco tiene ninguna instancia léxica.

Una palabra clave estática no tendría ningún sentido para una clase de nivel superior, solo porque una clase de nivel superior no tiene un tipo cerrado.

Andreas Dolk
fuente
Si no es interno, ¿por qué llamarlo Inner? Nestedhabría sido una opción menos confusa.
Marqués de Lorne
5

Como se explicó anteriormente, una clase no puede ser estática a menos que sea miembro de otra clase.

Si está buscando diseñar una clase "de la cual no puede haber múltiples instancias", es posible que desee examinar el patrón de diseño "Singleton".

Principiante Singleton información aquí .

Consideración:

Si está pensando en usar el patrón singleton, resista con todas sus fuerzas. Es uno de los patrones de diseño más fáciles de entender, probablemente el más popular y definitivamente el más abusado. (fuente: JavaRanch como se vincula anteriormente)

S.Jones
fuente
4

Además de cómo Java define las clases internas estáticas, existe otra definición de clases estáticas según el mundo C # [1] . Una clase estática es aquella que solo tiene métodos estáticos (funciones) y está destinada a admitir programación de procedimientos. Tales clases no son realmente clases en el sentido de que el usuario de la clase solo está interesado en las funciones auxiliares y no en crear instancias de la clase. Si bien las clases estáticas son compatibles con C #, no existe tal soporte directo en Java. Sin embargo, puede usar enumeraciones para imitar las clases estáticas de C # en Java para que un usuario nunca pueda crear instancias de una clase determinada (incluso usando la reflexión) [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();
    }
}
farsa
fuente
3

Todo lo que codificamos en Java entra en una clase. Cada vez que ejecutamos una clase, JVM crea una instancia de un objeto. JVM puede crear varios objetos, por definición Estático significa que tiene el mismo conjunto de copias para todos los objetos.

Por lo tanto, si Java hubiera permitido que la clase superior fuera estática cada vez que ejecute un programa, crea un Objeto y continúa anulando en la misma Ubicación de memoria.

Si solo reemplaza el objeto cada vez que lo ejecuta, ¿cuál es el punto de crearlo?

Esa es la razón por la que Java se deshizo de la estática para la clase de nivel superior.

Puede haber razones más concretas, pero esto tiene mucho sentido lógico para mí.

usuario2626445
fuente
3
Las clases internas están asociadas con las clases externas y esa es la razón por la que pueden ser estáticas, ya que tiene un objeto diferente del que depender.
user2626445
1
Quiere decir 'esa es la razón por la que no pueden ser estáticos'.
Marqués de Lorne
2

Las únicas clases que pueden ser estáticas son las clases internas. El siguiente código funciona bien:

public class whatever {
    static class innerclass {
    }
}

El punto de las clases internas estáticas es que no tienen una referencia al objeto de la clase externa.

usuario2645256
fuente
1
'estático interno' es una contradicción en los términos. 'static' e 'inner' son mutuamente excluyentes. La palabra que está buscando es 'anidada', no 'interna'.
Marqués de Lorne
1

¡Creo que esto es posible tan fácil como tomar un vaso de café !. Solo mira esto. No usamos palabras clave estáticas explícitamente al definir la clase.

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

¿No es eso una definición de clase estática? Solo usamos una función ligada a solo una clase. Tenga cuidado de que en este caso podamos usar otra clase en esa anidada. Mira esto:

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
fuente
Creo que podemos considerar tales clases como clases estáticas al referirnos a la definición de clase estática, no simplemente usando la palabra clave static como calificador.
Erfankam
Asegúrese de crear un constructor privado, de lo contrario podría decirlo new StaticClass()y eso no tiene mucho sentido. Con un constructor privado no permitiría instancias de este.
grinch
1

En PlatformUIEclipse se puede ver una clase con métodos estáticos y un constructor privado en sí mismo que es final.

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

Si el beneficio de usar una clase estática no es crear una instancia de un objeto y usar un método, entonces simplemente declare la clase como pública y este método como estático.

eeadev
fuente