atributo estático final privado vs atributo final privado

Resuelto asked hace 15 años • 0 respuestas

En Java, ¿cuál es la diferencia entre:

private final static int NUMBER = 10;

y

private final int NUMBER = 10;

Ambos son privatey final, la diferencia es el staticatributo.

¿Que es mejor? ¿Y por qué?

 avatar Sep 13 '09 02:09
Aceptado

En general, staticsignifica "asociado con el tipo en sí, en lugar de una instancia del tipo".

Eso significa que puede hacer referencia a una variable estática sin haber creado nunca una instancia del tipo, y cualquier código que haga referencia a la variable se refiere exactamente a los mismos datos. Compare esto con una variable de instancia: en ese caso, hay una versión independiente de la variable por instancia de la clase. Así por ejemplo:

Test x = new Test();
Test y = new Test();
x.instanceVariable = 10;
y.instanceVariable = 20;
System.out.println(x.instanceVariable);

imprime 10: y.instanceVariabley x.instanceVariableestán separados, porque xy yse refieren a objetos diferentes.

Puede hacer referencia a miembros estáticos mediante referencias, aunque es una mala idea hacerlo. Si lo hiciéramos:

Test x = new Test();
Test y = new Test();
x.staticVariable = 10;
y.staticVariable = 20;
System.out.println(x.staticVariable);

entonces eso imprimiría 20; solo hay una variable, no una por instancia. Hubiera sido más claro escribir esto como:

Test x = new Test();
Test y = new Test();
Test.staticVariable = 10;
Test.staticVariable = 20;
System.out.println(Test.staticVariable);

Eso hace que el comportamiento sea mucho más obvio. Los IDE modernos normalmente sugerirán cambiar la segunda lista por la tercera.

No hay razón para tener una declaración en línea que inicialice el valor como la siguiente, ya que cada instancia tendrá el suyo propio NUMBERpero siempre con el mismo valor (es inmutable y se inicializa con un literal). Esto es lo mismo que tener una sola final staticvariable para todas las instancias.

private final int NUMBER = 10;

Por lo tanto, si no puede cambiar, no tiene sentido tener una copia por instancia.

Pero tiene sentido si se inicializa en un constructor como este:

// No initialization when is declared
private final int number;

public MyClass(int n) {
   // The variable can be assigned in the constructor, but then
   // not modified later.
   number = n;
}

Ahora, para cada instancia de MyClass, podemos tener un valor diferente pero inmutable de number.

Jon Skeet avatar Sep 12 '2009 19:09 Jon Skeet

Una staticvariable permanece en la memoria durante toda la vida útil de la aplicación y se inicializa durante la carga de la clase. Una no staticvariable se inicializa cada vez que se construye un newobjeto. Generalmente es mejor usar:

private static final int NUMBER = 10;

¿Por qué? Esto reduce la huella de memoria por instancia. Posiblemente también sea favorable para los aciertos de caché. Y simplemente tiene sentido: staticdebe usarse para cosas que se comparten entre todas las instancias (también conocidas como objetos) de un determinado tipo (también conocido como class).

Martijn Courteaux avatar Sep 12 '2009 19:09 Martijn Courteaux

Para final , se le pueden asignar diferentes valores en tiempo de ejecución cuando se inicializa. Por ejemplo

class Test{
  public final int a;
}

Test t1  = new Test();
t1.a = 10;
Test t2  = new Test();
t2.a = 20; //fixed

Por lo tanto, cada instancia tiene un valor diferente de campo a .

Para static final , todas las instancias comparten el mismo valor y no se pueden modificar después de la primera inicialización.

class TestStatic{
      public static final int a = 0;
}

TestStatic t1  = new TestStatic();
t1.a = 10; // ERROR, CAN'T BE ALTERED AFTER THE FIRST 
TestStatic t2  = new TestStatic();
t1.a = 20;   // ERROR, CAN'T BE ALTERED AFTER THE FIRST INITIALIZATION.
lucas avatar Aug 21 '2012 08:08 lucas

estático significa "asociado con la clase"; sin él, la variable se asocia con cada instancia de la clase. Si es estático, significa que sólo tendrás uno en la memoria; si no, tendrás uno para cada instancia que crees. estática significa que la variable permanecerá en la memoria mientras la clase esté cargada; sin él, la variable se puede registrar cuando su instancia lo es.

duffymo avatar Sep 12 '2009 19:09 duffymo

Al leer las respuestas, no encontré ninguna prueba real que vaya al grano. Aquí están mis 2 centavos:

public class ConstTest
{

    private final int         value             = 10;
    private static final int  valueStatic       = 20;
    private final File        valueObject       = new File("");
    private static final File valueObjectStatic = new File("");

    public void printAddresses() {


        System.out.println("final int address " +
                ObjectUtils.identityToString(value));
        System.out.println("final static int address " +
                ObjectUtils.identityToString(valueStatic));
        System.out.println("final file address " + 
                ObjectUtils.identityToString(valueObject));
        System.out.println("final static file address " + 
                ObjectUtils.identityToString(valueObjectStatic));
    }


    public static void main(final String args[]) {


        final ConstTest firstObj = new ConstTest();
        final ConstTest sndObj = new ConstTest();

        firstObj.printAdresses();
        sndObj.printAdresses();
    }

}

Resultados para el primer objeto:

final int address java.lang.Integer@6d9efb05
final static int address java.lang.Integer@60723d7c
final file address java.io.File@6c22c95b
final static file address java.io.File@5fd1acd3

Resultados para el segundo objeto:

final int address java.lang.Integer@6d9efb05
final static int address java.lang.Integer@60723d7c
final file address java.io.File@3ea981ca
final static file address java.io.File@5fd1acd3

Conclusión :

Como pensaba, Java hace una diferencia entre los tipos primitivos y otros. Los tipos primitivos en Java siempre están "almacenados en caché", lo mismo para las cadenas literales (no para los nuevos objetos String), por lo que no hay diferencia entre miembros estáticos y no estáticos.

Sin embargo, existe una duplicación de memoria para miembros no estáticos si no son instancias de un tipo primitivo.

Cambiar el valor de valueStatic a 10 irá aún más lejos ya que Java dará las mismas direcciones a las dos variables int.

StackHola avatar Sep 17 '2012 12:09 StackHola