¿Qué hace la palabra clave 'estática' en una clase?

444

Para ser específico, estaba intentando este código:

package hello;

public class Hello {

    Clock clock = new Clock();

    public static void main(String args[]) {
        clock.sayTime();
    }
}

Pero dio el error

No se puede acceder al campo no estático en el método principal estático

Así que cambié la declaración de clocka esto:

static Clock clock = new Clock();

Y funcionó. ¿Qué significa poner esa palabra clave antes de la declaración? ¿Qué hará exactamente y / o restringirá en términos de lo que se puede hacer a ese objeto?

Haga clic en Upvote
fuente
Una vez más, recuerde que hay una instancia de una estática por clase por CLASSLOADER.
Javamann el

Respuestas:

633

static los miembros pertenecen a la clase en lugar de una instancia específica.

Significa que solo staticexiste una instancia de un campo [1] incluso si crea un millón de instancias de la clase o no crea ninguna. Será compartido por todas las instancias.

Dado que los staticmétodos tampoco pertenecen a una instancia específica, no pueden referirse a miembros de la instancia. En el ejemplo dado, mainno sabe a qué instancia de la Helloclase (y, por lo tanto, a qué instancia de la Clockclase) debería referirse. staticlos miembros solo pueden referirse a los staticmiembros. Los miembros de la instancia pueden, por supuesto, acceder a los staticmiembros.

Nota al margen: Por supuesto, los staticmiembros pueden acceder a los miembros de la instancia a través de una referencia de objeto .

Ejemplo:

public class Example {
    private static boolean staticField;
    private boolean instanceField;
    public static void main(String[] args) {
        // a static method can access static fields
        staticField = true;

        // a static method can access instance fields through an object reference
        Example instance = new Example();
        instance.instanceField = true;
    }

[1]: Dependiendo de las características de tiempo de ejecución, puede ser uno por ClassLoader o AppDomain o hilo, pero eso no viene al caso.

Mehrdad Afshari
fuente
55
En .NET, también puede modificar este comportamiento utilizando el atributo [ThreadStatic], que hace que la estática sea local para hilos particulares.
TheSoftwareJedi el
44
Sé que esta es una publicación antigua, pero para principiantes como yo, esto puede ser útil. stackoverflow.com/questions/7026507/…
user3526905
¿No podría acceder a instance.instanceField ya que es una variable privada? ¿O es válido porque instanciaste el objeto dentro de su propia clase? Suena como una pesadilla recursiva para mí, pero soy un novato en Java.
Matt Corby
Si el miembro estático de una clase está referenciado por 2 hilos diferentes, ¿cuántas instancias hay de ese miembro estático? Siento que es 2, pero si desea la misma instancia en todos los subprocesos, debe usarse la palabra clave volátil. ¿Es eso correcto?
Dan
¿Y se conserva el valor si no quedan instancias de la clase?
mckenzm
130

Significa que solo hay una instancia de "reloj" en Hello, no una por cada instancia separada de la clase "Hello", o más, significa que habrá una referencia de "reloj" comúnmente compartida entre todas las instancias de la clase "Hola".

Entonces, si tuviera que hacer un "nuevo Hola" en cualquier parte de su código: A- en el primer escenario (antes del cambio, sin usar "estático"), generaría un nuevo reloj cada vez que se llama un "nuevo Hola", pero B- en el segundo escenario (después del cambio, usando "estático"), cada instancia de "nuevo Hola" aún compartiría y usaría la referencia inicial y la misma "reloj" creada por primera vez.

A menos que necesite "reloj" en algún lugar fuera de main, esto funcionaría igual de bien:

package hello;
public class Hello
{
    public static void main(String args[])
    {
      Clock clock=new Clock();
      clock.sayTime();    
    }
}
Paul Tomblin
fuente
Esta es la forma más habitual de hacerlo. La main()rutina debe ser autónoma.
Jason S
1
En la segunda instancia, crearía una nueva instancia de Clock cada vez que se llama al método principal, ¿verdad?
Haga clic en Upvote el
2
En la segunda instancia, reloj estático, solo lo crearía una vez. En mi ejemplo, donde el reloj está dentro del main, entonces sí, lo crearía nuevo cada vez que se llama al main. Pero normalmente main solo se llama una vez al inicio del programa, y ​​cuando sale, todo es gratuito.
Paul Tomblin el
No puedo entender cómo es posible hacer un nuevo reloj en el método principal. como usted dice, lo crearía nuevo cada vez que se llama a main, pero solo hay un método main. ¿Cómo ese método principal puede referirse a diferentes instancias de reloj? Es un poco difícil entender cómo es posible hacer una nueva instancia de clock en main y usar su método sayTime (), pero no es posible hacer la instancia fuera de main y usar sayTime (). ¿Cómo es todo gratis cuando se llama a main una vez? @PaulTomblin
ShakibaZar
@ user5621266 Solo utilicé el mainmétodo porque el OP lo hizo. Si, en cambio, se trataba de un método público al que se llamó desde otro lugar, y la clase Hello se instanciaba más de una vez, podría crear una instancia de Clock para cada instancia de Hello, a menos que clockfuera estática.
Paul Tomblin
97

La staticpalabra clave significa que algo (un campo, método o clase anidada) está relacionado con el tipo en lugar de cualquier instancia particular del tipo. Entonces, por ejemplo, uno llama Math.sin(...)sin ninguna instancia de la Mathclase, y de hecho no puede crear una instancia de la Mathclase.

Para obtener más información, consulte el fragmento relevante del Tutorial Java de Oracle .


Nota al margen

Desafortunadamente, Java le permite acceder a miembros estáticos como si fueran miembros de instancias, p. Ej.

// Bad code!
Thread.currentThread().sleep(5000);
someOtherThread.sleep(5000);

Eso hace que parezca como si sleepes un método de instancia, pero en realidad es un método estático - que siempre hace que el sueño hilo actual. Es mejor dejar esto claro en el código de llamada:

// Clearer
Thread.sleep(5000);
Jon Skeet
fuente
1
Otro ejemplo: System.out.println () parece un método de clase, pero en realidad es un método de instancia. Dado que out es una instancia de PrintStream en la clase System.
Jiahui Zhang
@LeslieCheung: No, no me parece un método de clase, ya que System.outno me gusta un nombre de tipo.
Jon Skeet
42

La staticpalabra clave en Java significa que la variable o función se comparte entre todas las instancias de esa clase, ya que pertenece al tipo , no a los objetos en sí.

Entonces, si tiene una variable: private static int i = 0;y la incrementa ( i++) en una instancia, el cambio se reflejará en todas las instancias. iahora será 1 en todos los casos.

Los métodos estáticos se pueden usar sin crear instancias de un objeto.

geowa4
fuente
44
"Compartida entre todas las instancias" da la impresión equivocada, OMI - que sugiere que haces necesidad de contar con una instancia del objeto.
Jon Skeet el
1
(Mientras que en realidad no es necesario que haya ninguna instancia, porque el campo estático, etc., pertenece al tipo .)
Jon Skeet el
@Jon Skeet static pertenece al tipo, no al objeto? ¿Puedes decir más detalles? Escriba like datatype: int, double, ...?
truongnm
@truongnm: escriba como en la clase que declara la variable / método.
Jon Skeet
26

Uso básico de miembros estáticos ...

public class Hello
{
    // value / method
    public static String staticValue;
    public String nonStaticValue;
}

class A
{
    Hello hello = new Hello();
    hello.staticValue = "abc";
    hello.nonStaticValue = "xyz";
}

class B
{
    Hello hello2 = new Hello(); // here staticValue = "abc"
    hello2.staticValue; // will have value of "abc"
    hello2.nonStaticValue; // will have value of null
}

Así es como puede tener valores compartidos en todos los miembros de la clase sin enviar la instancia de clase Hello a otra clase. Y con estática no necesita crear una instancia de clase.

Hello hello = new Hello();
hello.staticValue = "abc";

Simplemente puede llamar a valores o métodos estáticos por nombre de clase:

Hello.staticValue = "abc";
Vasil Valchev
fuente
22

Estático significa que no tiene que crear una instancia de la clase para usar los métodos o variables asociados con la clase. En su ejemplo, puede llamar a:

Hello.main(new String[]()) //main(...) is declared as a static function in the Hello class

directamente, en lugar de:

Hello h = new Hello();
h.main(new String[]()); //main(...) is a non-static function linked with the "h" variable

Desde el interior de un método estático (que pertenece a una clase) no puede acceder a ningún miembro que no sea estático, ya que sus valores dependen de su instanciación de la clase. Un objeto Clock no estático, que es un miembro de instancia, tendría un valor / referencia diferente para cada instancia de su clase Hello y, por lo tanto, no podría acceder a él desde la parte estática de la clase.

Elie
fuente
Gran explicación para el contexto estático :)
Abdel-Raouf
20

Estático en Java:

Static es un modificador sin acceso. La palabra clave estática pertenece a la clase que instancia de la clase. se puede usar para adjuntar una Variable o Método a una Clase.

La palabra clave estática PUEDE usarse con:

Método

Variable

Clase anidada dentro de otra clase

Bloque de inicialización

NO PUEDE ser usado con:

Clase (no anidada)

Constructor

Interfaces

Método Clase interna local (diferencia luego clase anidada)

Métodos de clase interna

Variables de instancia

Variables locales

Ejemplo:

Imagine el siguiente ejemplo que tiene una variable de instancia llamada count que se incrementa en el constructor:

package pkg;

class StaticExample {
    int count = 0;// will get memory when instance is created

    StaticExample() {
        count++;
        System.out.println(count);
    }

    public static void main(String args[]) {

        StaticExample c1 = new StaticExample();
        StaticExample c2 = new StaticExample();
        StaticExample c3 = new StaticExample();

    }
}

Salida:

1 1 1

Dado que la variable de instancia obtiene la memoria en el momento de la creación del objeto, cada objeto tendrá la copia de la variable de instancia, si se incrementa, no se reflejará en otros objetos.

Ahora, si cambiamos el recuento de variables de instancia a uno estático , el programa producirá resultados diferentes:

package pkg;

class StaticExample {
    static int count = 0;// will get memory when instance is created

    StaticExample() {
        count++;
        System.out.println(count);
    }

    public static void main(String args[]) {

        StaticExample c1 = new StaticExample();
        StaticExample c2 = new StaticExample();
        StaticExample c3 = new StaticExample();

    }
}

Salida:

1 2 3

En este caso, la variable estática obtendrá la memoria solo una vez, si algún objeto cambia el valor de la variable estática, retendrá su valor.

Estática con final:

La variable global que se declara como final y estática permanece sin cambios durante toda la ejecución. Porque, los miembros estáticos se almacenan en la memoria de la clase y se cargan solo una vez en toda la ejecución. Son comunes a todos los objetos de la clase. Si declara variables estáticas como finales, cualquiera de los objetos no puede cambiar su valor ya que es final. Por lo tanto, las variables declaradas como finales y estáticas a veces se denominan constantes. Todos los campos de las interfaces se denominan constantes, ya que son finales y estáticos por defecto.

ingrese la descripción de la imagen aquí

Recurso de imagen: estática final

Affy
fuente
15

Para agregar a las respuestas existentes, déjame probar con una imagen:

Se aplica una tasa de interés del 2% a TODAS las cuentas de ahorro. Por lo tanto, es estático .

Un equilibrio debe ser individual , por lo que no es estático.

ingrese la descripción de la imagen aquí

Andrejs
fuente
13

Esta discusión ha ignorado hasta ahora las consideraciones del cargador de clases. Estrictamente hablando, los campos estáticos de Java se comparten entre todas las instancias de una clase para un cargador de clases dado .

Julien Chastang
fuente
1
Esto fue mencionado por Apocalisp en los comentarios sobre la respuesta de Merhdad.
Zach Langley el
1
Buen punto. Mucha gente no sabe esto, pero una vez que comienzas a jugar con los cargadores de clases, se vuelve muy importante.
sleske 02 de
2
Todo esto es cierto, pero no responde la pregunta. Debería haber sido publicado como un comentario.
Marqués de Lorne
7

Se puede asignar un campo a la clase o a una instancia de una clase. Por defecto, los campos son variables de instancia. Al usar staticel campo se convierte en una variable de clase, por lo tanto, hay uno y solo uno clock. Si realiza cambios en un lugar, es visible en todas partes. Los valores de instancia se cambian independientemente uno del otro.

sblundy
fuente
6

La palabra clave staticse usa para denotar un campo o un método como perteneciente a la clase misma y no a la instancia. Usando su código, si el objeto Clockes estático, todas las instancias de la Helloclase compartirán este Clockmiembro de datos (campo) en común. Si lo hace no estático, cada instancia individual de Hellopuede tener un Clockcampo único .

El problema es que agregó un método principal a su clase Hellopara poder ejecutar el código. El problema aquí es que el método principal es estático y, como tal, no puede hacer referencia a campos o métodos no estáticos dentro de él. Puede resolver esto de dos maneras:

  1. Haga que todos los campos y métodos de la Helloclase sean estáticos para que se puedan hacer referencia a ellos dentro del método principal . Esto realmente no es algo bueno (o la razón incorrecta para hacer que un campo y / o método sea estático)
  2. Cree una instancia de su Helloclase dentro del método principal y acceda a todos sus campos y métodos de la manera en que estaban destinados en primer lugar.

Para usted, esto significa el siguiente cambio en su código:

package hello;

public class Hello {

    private Clock clock = new Clock();

    public Clock getClock() {
        return clock;
    }

    public static void main(String args[]) {
        Hello hello = new Hello();
        hello.getClock().sayTime();
    }
}
hfontanez
fuente
6

En Java, la staticpalabra clave puede considerarse simplemente que indica lo siguiente:

"sin consideración o relación con ninguna instancia en particular"

Si piensa de staticesta manera, se vuelve más fácil comprender su uso en los diversos contextos en los que se encuentra:

  • Un staticcampo es un campo que pertenece a la clase en lugar de a cualquier instancia en particular.

  • Un staticmétodo es un método que no tiene noción de this; se define en la clase y no conoce ninguna instancia particular de esa clase a menos que se le pase una referencia

  • Una staticclase miembro es una clase anidada sin ninguna noción o conocimiento de una instancia de su clase adjunta (a menos que se le pase una referencia a una instancia de clase adjunta)

scottb
fuente
5

Estático hace que el miembro del reloj sea un miembro de la clase en lugar de un miembro de la instancia. Sin la palabra clave estática, necesitaría crear una instancia de la clase Hello (que tiene una variable de miembro de reloj), p. Ej.

Hello hello = new Hello();
hello.clock.sayTime();
Stephen Doyle
fuente
5

los métodos estáticos no utilizan ninguna variable de instancia de la clase en la que están definidos. En esta página puede encontrar una muy buena explicación de la diferencia .

Marc Novakowski
fuente
5

He desarrollado un gusto por los métodos estáticos (solo, si es posible) en las clases "auxiliares".

La clase que llama no necesita crear otra variable miembro (instancia) de la clase auxiliar. Simplemente llama a los métodos de la clase auxiliar. También se mejora la clase auxiliar porque ya no necesita un constructor y no necesita variables miembro (instancia).

Probablemente hay otras ventajas.

javaguy
fuente
4
//Here is an example 

public class StaticClass 
{
    static int version;
    public void printVersion() {
         System.out.println(version);
    }
}

public class MainClass 
{
    public static void main(String args[]) {  
        StaticClass staticVar1 = new StaticClass();
        staticVar1.version = 10;
        staticVar1.printVersion() // Output 10

        StaticClass staticVar2 = new StaticClass();
        staticVar2.printVersion() // Output 10
        staticVar2.version = 20;
        staticVar2.printVersion() // Output 20
        staticVar1.printVersion() // Output 20
    }
}
Mohammad Parvez
fuente
3

También se puede pensar en miembros estáticos que no tienen un puntero "this". Se comparten entre todas las instancias.

kal
fuente
3

Comprender conceptos estáticos

public class StaticPractise1 {
    public static void main(String[] args) {
        StaticPractise2 staticPractise2 = new StaticPractise2();
        staticPractise2.printUddhav(); //true
        StaticPractise2.printUddhav(); /* false, because printUddhav() is although inside StaticPractise2, but it is where exactly depends on PC program counter on runtime. */

        StaticPractise2.printUddhavsStatic1(); //true
        staticPractise2.printUddhavsStatic1(); /*false, because, when staticPractise2 is blueprinted, it tracks everything other than static  things and it organizes in its own heap. So, class static methods, object can't reference */

    }
}

Segunda clase

public class StaticPractise2 {
    public static void printUddhavsStatic1() {
        System.out.println("Uddhav");
    }

    public void printUddhav() {
        System.out.println("Uddhav");
    }
}
Uddhav Gautam
fuente
2

main() es un método estático que tiene dos restricciones fundamentales:

  1. El método estático no puede utilizar un miembro de datos no estático ni llamar directamente a un método no estático.
  2. this()y super()no se puede usar en contexto estático.

    class A {  
        int a = 40; //non static
        public static void main(String args[]) {  
            System.out.println(a);  
        }  
    }

Salida: error de tiempo de compilación

Bharthan
fuente
1

Solo se puede acceder a las variables estáticas solo con métodos estáticos, por lo que cuando declaramos las variables estáticas, los métodos getter y setter serán métodos estáticos.

métodos estáticos es un nivel de clase al que podemos acceder usando el nombre de la clase

El siguiente es un ejemplo de getters y setters de variables estáticas:

public class Static 
{

    private static String owner;
    private static int rent;
    private String car;
    public String getCar() {
        return car;
    }
    public void setCar(String car) {
        this.car = car;
    }
    public static int getRent() {
        return rent;
    }
    public static void setRent(int rent) {
        Static.rent = rent;
    }
    public static String getOwner() {
        return owner;
    }

    public static void setOwner(String owner) {
        Static.owner = owner;
    }

}
Bala Krishna
fuente
1

Aquí se formuló una pregunta sobre la elección de la palabra 'estática' para este concepto. Se duplicó con esta pregunta, pero no creo que la etimología se haya abordado claramente. Entonces...


Se debe a la reutilización de palabras clave, comenzando con C.

Considere las declaraciones de datos en C (dentro del cuerpo de una función):

    void f() {
        int foo = 1;
        static int bar = 2;
         :
    }

La variable foo se crea en la pila cuando se ingresa la función (y se destruye cuando la función termina). Por el contrario, la barra siempre está ahí, por lo que es 'estática' en el sentido del inglés común: no va a ninguna parte.

Java y lenguajes similares tienen el mismo concepto para los datos. Los datos pueden asignarse por instancia de la clase (por objeto) o una vez para toda la clase. Dado que Java pretende tener una sintaxis familiar para los programadores de C / C ++, la palabra clave 'estática' es apropiada aquí.

    class C {
        int foo = 1;
        static int bar = 2;
         :
    }

Por último, llegamos a los métodos.

    class C {
        int foo() { ... }
        static int bar() { ... }
         :
    }

Conceptualmente hablando, hay una instancia de foo () para cada instancia de la clase C. Solo hay una instancia de bar () para toda la clase C. Esto es paralelo al caso que discutimos para los datos, y por lo tanto usando 'static 'nuevamente es una opción sensata, especialmente si no desea agregar más palabras clave reservadas a su idioma.

usuario13068046
fuente