atributo estático final privado vs atributo final privado

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

private final static int NUMBER = 10; 

y

 private final int NUMBER = 10; 

Ambos son private y final , la diferencia es el atributo static .

¿Que es mejor? ¿Y por qué?

En general, static significa “asociado con el tipo en sí mismo, más que con 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 a los mismos datos exactos. 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.instanceVariable y x.instanceVariable están separados, porque y refieren a diferentes objetos.

Puede hacer referencia a miembros estáticos a través de 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 generalmente sugieren cambiar el segundo listado al tercero.

No hay razón para tener una statement como

 private final int NUMBER = 10; 

Si no puede cambiar, no tiene sentido tener una copia por instancia.

Para finalizar , 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 del campo a .

Para final estático , todas las instancias comparten el mismo valor y no se pueden modificar después de inicializarse por primera vez.

 Class TestStatic{ public static final int a; } TestStatic t1 = new TestStatic(); t1.a = 10; TestStatic t2 = new TestStatic(); t1.a = 20; // ERROR, CAN'T BE ALTERED AFTER THE FIRST INITIALIZATION. 

Una variable static permanece en la memoria durante toda la vida útil de la aplicación y se inicializa durante la carga de la clase. Una variable no static se está inicializando cada vez que construyes un new objeto. En general, 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 éxitos de caché. Y simplemente tiene sentido: se debe usar static para las cosas que se comparten en todas las instancias (también conocidos como objetos) de cierto tipo (también conocido como class ).

estático significa “asociado a la clase”; sin él, la variable se asocia con cada instancia de la clase. Si es estático, eso significa que solo tendrá uno en la memoria; si no, tendrás uno para cada instancia que crees. estático significa que la variable permanecerá en la memoria mientras se cargue la clase; sin él, la variable puede ser gc’d cuando su instancia es.

Al leer las respuestas, no encontré una prueba real que realmente fuera 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 2do 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 pensé, Java hace una diferencia entre primitivo y otros tipos. Los tipos primitivos en Java siempre se “almacenan en caché”, lo mismo para cadenas literales (no nuevos objetos String), por lo que no hay diferencia entre los miembros estáticos y no estáticos.

Sin embargo, hay una duplicación de memoria para miembros no estáticos si no son instancia 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.

Mientras que las otras respuestas parecen dejar bastante claro que generalmente no hay ninguna razón para usar constantes no estáticas, no pude encontrar a nadie señalando que es posible tener varias instancias con diferentes valores en sus variables constantes.

Considere el siguiente ejemplo:

 public class TestClass { private final static double NUMBER = Math.random(); public TestClass () { System.out.println(NUMBER); } } 

La creación de tres instancias de TestClass imprimirá el mismo valor aleatorio tres veces, ya que solo se genera un valor y se almacena en la constante estática.

Sin embargo, al intentar el siguiente ejemplo en su lugar:

 public class TestClass { private final double NUMBER = Math.random(); public TestClass () { System.out.println(NUMBER); } } 

La creación de tres instancias de TestClass ahora imprimiría tres valores aleatorios diferentes, porque cada instancia tiene su propio valor constante generado aleatoriamente.

No puedo pensar en ninguna situación en la que sería realmente útil tener diferentes valores constantes en diferentes instancias, pero espero que esto ayude a señalar que hay una clara diferencia entre finales estáticos y no estáticos.

Como ya dijo Jon, una variable estática, también conocida como una variable de clase, es una variable que existe en todas las instancias de una clase.

Encontré un ejemplo de esto aquí :

 public class StaticVariable { static int noOfInstances; StaticVariable() { noOfInstances++; } public static void main(String[] args) { StaticVariable sv1 = new StaticVariable(); System.out.println("No. of instances for sv1 : " + sv1.noOfInstances); StaticVariable sv2 = new StaticVariable(); System.out.println("No. of instances for sv1 : " + sv1.noOfInstances); System.out.println("No. of instances for st2 : " + sv2.noOfInstances); StaticVariable sv3 = new StaticVariable(); System.out.println("No. of instances for sv1 : " + sv1.noOfInstances); System.out.println("No. of instances for sv2 : " + sv2.noOfInstances); System.out.println("No. of instances for sv3 : " + sv3.noOfInstances); } } 

La salida del progtwig se da a continuación:

Como podemos ver en este ejemplo, cada objeto tiene su propia copia de la variable de clase.

 C:\java>java StaticVariable No. of instances for sv1 : 1 No. of instances for sv1 : 2 No. of instances for st2 : 2 No. of instances for sv1 : 3 No. of instances for sv2 : 3 No. of instances for sv3 : 3 

¡De las pruebas que he realizado, las variables finales estáticas no son las mismas que las variables finales (no estáticas)! ¡Las variables finales (no estáticas) pueden diferir de un objeto a otro! ¡Pero eso es solo si la inicialización se realiza dentro del constructor! (Si no se inicializa desde el constructor, es solo un desperdicio de memoria, ya que crea variables finales para cada objeto creado que no se puede modificar).

Por ejemplo:

 class A { final int f; static final int sf = 5; A(int num) { this.f = num; } void show() { System.out.printf("About Object: %s\n Final: %d\n Static Final: %d\n\n", this.toString(), this.f, sf); } public static void main(String[] args) { A ob1 = new A(14); ob1.show(); A ob2 = new A(21); ob2.show(); } } 

Lo que aparece en la pantalla es:

Acerca del objeto: A @ addbf1 Final: 14 Final estático: 5

Acerca del objeto: A @ 530daa Final: 21 Final estático: 5

Anónimo Estudiante de informática de primer año, Grecia

Además, a la respuesta de Jon si usa estática final, se comportará como una especie de “definición”. Una vez que compile la clase que lo usa, estará en el archivo comstackdo .class quemado. Mira mi hilo sobre esto aquí .

Para su objective principal: si no usa el NÚMERO de manera diferente en las diferentes instancias de la clase, le aconsejaría usar final y estático. (Solo tiene que tener en cuenta que no copie los archivos comstackdos de la clase sin considerar posibles problemas como el que describe mi caso de estudio. En la mayoría de los casos, esto no ocurre, no se preocupe :))

Para mostrarle cómo usar diferentes valores en instancias, consulte este código:

 public class JustFinalAttr { public final int Number; public JustFinalAttr(int a){ Number=a; } } ...System.out.println(new JustFinalAttr(4).Number); 

Aquí están mis dos centavos:

 final String CENT_1 = new Random().nextInt(2) == 0 ? "HEADS" : "TAILS"; final static String CENT_2 = new Random().nextInt(2) == 0 ? "HEADS" : "TAILS"; 

Ejemplo:

 package test; public class Test { final long OBJECT_ID = new Random().nextLong(); final static long CLASSS_ID = new Random().nextLong(); public static void main(String[] args) { Test[] test = new Test[5]; for (int i = 0; i < test.length; i++){ test[i] = new Test(); System.out.println("Class id: "+test[i].CLASSS_ID);//<- Always the same value System.out.println("Object id: "+test[i].OBJECT_ID);//<- Always different } } } 

La clave es que las variables y funciones pueden devolver diferentes valores. Por lo tanto, las variables finales se pueden asignar con diferentes valores.

muy poco y estático

No hay mucha diferencia ya que ambas son constantes. Para la mayoría de los objetos de datos de clase, estática significaría algo asociado con la clase en sí misma, ya que solo hay una copia, sin importar cuántos objetos se crearon con la nueva.

Dado que es una constante, puede no almacenarse ni en la clase ni en una instancia, pero el comstackdor aún no le permitirá acceder a objetos de instancia desde un método estático, incluso si sabe cuál sería. La existencia de la API de reflexión también puede requerir algún trabajo inútil si no la convierte en estática.

Como una variable en una clase se declara como final Y se inicializa en el mismo comando, no hay absolutamente ninguna razón para no declararlo como estático, ya que tendrá el mismo valor sin importar la instancia. Por lo tanto, todas las instancias pueden compartir la misma dirección de memoria para un valor, lo que ahorra tiempo de procesamiento al eliminar la necesidad de crear una nueva variable para cada instancia y guardar la memoria al compartir 1 dirección común.

el final estático privado se considerará como constante y solo se puede acceder a la constante dentro de esta clase. Dado que, la palabra clave estática incluida, el valor será constante para todos los objetos de la clase.

el valor privado de la variable final será como constante por objeto.

Puede referir el java.lang.String o buscar el ejemplo a continuación.

 public final class Foo { private final int i; private static final int j=20; public Foo(int val){ this.i=val; } public static void main(String[] args) { Foo foo1= new Foo(10); Foo foo2= new Foo(40); System.out.println(foo1.i); System.out.println(foo2.i); System.out.println(check.j); } } 

//Salida:

 10 40 20 

El estático es el mismo miembro en todas las instancias de clase y la clase misma.
El no estático es uno para cada instancia (objeto), por lo que en su caso exacto es una pérdida de memoria si no pone estática.

Si marca esta variable estática, entonces, como sabe, estaría requiriendo métodos estáticos para volver a acceder a estos valores, esto será útil si ya piensa en usar estas variables solo en métodos estáticos. Si esto es así, este sería el mejor.

Sin embargo, puede hacer que la variable ahora sea pública, ya que nadie puede modificarla como “System.out”, sino que depende de sus intenciones y de lo que desea lograr.

Digamos que si la clase no tendrá más de una instancia, ¿cuál tomará más memoria?

private private int int ID = 250; o ID int final privada = 250;

He entendido que estática se referirá al tipo de clase con una sola copia en la memoria y no estática en una nueva ubicación de memoria para cada variable de instancia. Sin embargo, internamente, si solo comparamos 1 instancia de la misma clase (es decir, no se crearía más de 1 instancia), ¿hay alguna sobrecarga en términos de espacio utilizado por 1 variable final estática?

La variable estática pertenece a la clase (lo que significa que todos los objetos comparten esa variable). La variable no estática pertenece a cada objeto.

 public class ExperimentFinal { private final int a; private static final int b = 999; public ExperimentFinal(int a) { super(); this.a = a; } public int getA() { return a; } public int getB() { return b; } public void print(int a, int b) { System.out.println("final int: " + a + " \nstatic final int: " + b); } public static void main(String[] args) { ExperimentFinal test = new ExperimentFinal(9); test.print(test.getA(), test.getB()); } } 

Como puede ver en el ejemplo anterior, para “final int” podemos asignar nuestra variable para cada instancia (objeto) de la clase, sin embargo, para “static final int”, deberíamos asignar una variable en la clase (la variable estática pertenece a la clase )

Solo otro ejemplo simple para comprender el uso de variables fijas, estáticas y finales estáticas. Los comentarios del código tienen la explicación adecuada.

 public class City { // base price that is always same for all objects[For all cities]. private static double iphone_base_price = 10000; // this is total price = iphone_base_price+iphone_diff; private double iphone_citi_price; // extra price added to iphone_base_price. It is constant per city. Every // city has its own difference defined, private final double iphone_diff; private String cityName = ""; // static final will be accessible everywhere within the class but cant be // changed once initialized. private static final String countryName = "India"; public City(String cityName, double iphone_diff) { super(); this.iphone_diff = iphone_diff; iphone_citi_price = iphone_base_price + iphone_diff; this.cityName = cityName; } /** * get phone price * * @return */ private double getPrice() { return iphone_citi_price; } /** * Get city name * * @return */ private String getCityName() { return cityName; } public static void main(String[] args) { // 300 is the City newyork = new City("Newyork", 300); System.out.println(newyork.getPrice() + " " + newyork.getCityName()); City california = new City("California", 800); System.out.println(california.getPrice() + " " + california.getCityName()); // We cant write below statement as a final variable can not be // reassigned // california.iphone_diff=1000; //************************ // base price is defined for a class and not per instances. // For any number of object creation, static variable's value would be the same // for all instances until and unless changed. // Also it is accessible anywhere inside a class. iphone_base_price = 9000; City delhi = new City("delhi", 400); System.out.println(delhi.getPrice() + " " + delhi.getCityName()); City moscow = new City("delhi", 500); System.out.println(moscow.getPrice() + " " + moscow.getCityName()); // Here countryName is accessible as it is static but we can not change it as it is final as well. //Something are meant to be accessible with no permission to modify it. //Try un-commenting below statements System.out.println(countryName); // countryName="INDIA"; // System.out.println(countryName); } } 

Si usa estática, el valor de la variable será el mismo en todas sus instancias, si se cambia en una instancia, las otras también cambiarán.

Esto podría ayudar

 public class LengthDemo { public static void main(String[] args) { Rectangle box = new Rectangle(); System.out.println("Sending the value 10.0 " + "to the setLength method."); box.setLength(10.0); System.out.println("Done."); } }