Suponga que necesita definir una clase que todo lo que hace es mantener constantes.
public static final String SOME_CONST = "SOME_VALUE";
¿Cuál es la forma preferida de hacer esto?
- Interfaz
- Clase abstracta
- Clase final
¿Cuál debo usar y por qué?
Aclaraciones a algunas respuestas:
Enums : no voy a usar enumeraciones, no voy a enumerar nada, solo recopilar algunas constantes que no están relacionadas entre sí de ninguna manera.
Interfaz : no voy a establecer ninguna clase como una que implemente la interfaz. Sólo quieren utilizar la interfaz para llamar constantes de este modo: ISomeInterface.SOME_CONST
.
java
class-constants
Yuval Adam
fuente
fuente
Respuestas:
Utilice una clase final. para simplificar, puede usar una importación estática para reutilizar sus valores en otra clase
public final class MyValues { public static final String VALUE1 = "foo"; public static final String VALUE2 = "bar"; }
en otra clase:
import static MyValues.* //... if(variable.equals(VALUE1)){ //... }
fuente
VALUE1.equals(variable)
ya que evita NPE.Su aclaración dice: "No voy a usar enumeraciones, no voy a enumerar nada, solo recopilar algunas constantes que no están relacionadas entre sí de ninguna manera".
Si las constantes no están relacionadas entre sí en absoluto, ¿por qué quiere recopilarlas? Coloque cada constante en la clase con la que esté más estrechamente relacionada.
fuente
Mis sugerencias (en orden decreciente de preferencia):
1) No lo hagas . Cree las constantes en la clase real donde sean más relevantes. Tener una clase / interfaz 'bolsa de constantes' no está realmente siguiendo las mejores prácticas de OO.
Yo, y todos los demás, ignoramos el número 1 de vez en cuando. Si vas a hacer eso, entonces:
2) clase final con constructor privado Esto al menos evitará que alguien abuse de su 'bolsa de constantes' extendiéndola / implementándola para tener fácil acceso a las constantes. (Sé que dijiste que no harías esto, pero eso no significa que alguien venga después de ti no lo hará)
3) interfaz Esto funcionará, pero no es mi preferencia, dando la posible mención de abuso en el n. ° 2.
En general, el hecho de que sean constantes no significa que no deba aplicarles los principios normales de oo. Si a nadie más que a una clase le importa una constante, debería ser privada y en esa clase. Si solo las pruebas se preocupan por una constante, debería ser una clase de prueba, no un código de producción. Si una constante se define en varios lugares (no solo accidentalmente el mismo), refactorice para eliminar la duplicación. Y así sucesivamente, trátelos como si fuera un método.
fuente
Como señala Joshua Bloch en Effective Java:
Puede usar un Enum si todas sus constantes están relacionadas (como los nombres de los planetas), poner los valores constantes en las clases con las que están relacionados (si tiene acceso a ellos), o usar una clase de utilidad no instanciable (defina un constructor predeterminado privado) .
class SomeConstants { // Prevents instanciation of myself and my subclasses private SomeConstants() {} public final static String TOTO = "toto"; public final static Integer TEN = 10; //... }
Luego, como ya se indicó, puede usar importaciones estáticas para usar sus constantes.
fuente
Mi método preferido es no hacer eso en absoluto. La era de las constantes prácticamente murió cuando Java 5 introdujo las enumeraciones con seguridad de tipos. E incluso antes de eso, Josh Bloch publicó una versión (un poco más prolija) de eso, que funcionaba en Java 1.4 (y versiones anteriores).
A menos que necesite interoperabilidad con algún código heredado, realmente ya no hay razón para usar constantes String / integer con nombre.
fuente
Solo usa la clase final.
Si desea poder agregar otros valores, use una clase abstracta.
No tiene mucho sentido usar una interfaz, se supone que una interfaz especifica un contrato. Solo desea declarar algunos valores constantes.
fuente
¿No son las enumeraciones la mejor opción para este tipo de cosas?
fuente
enum
s están bien. IIRC, un elemento en Java efectivo (2.a edición) tieneenum
constantes que enumeran opciones estándar que implementan una [palabra clave de Java]interface
para cualquier valor.Mi preferencia es usar una [palabra clave de Java]
interface
sobre unafinal class
para constantes. Implícitamente obtienes elpublic static final
. Algunas personas argumentarán que uninterface
permite que los malos programadores lo implementen, pero los malos programadores van a escribir código que apesta sin importar lo que hagas.¿Cuál luce mejor?
public final class SomeStuff { private SomeStuff() { throw new Error(); } public static final String SOME_CONST = "Some value or another, I don't know."; }
O:
public interface SomeStuff { String SOME_CONST = "Some value or another, I don't know."; }
fuente
O 4. Colóquelos en la clase que contiene la lógica que usa las constantes más
... lo siento, no pude resistir ;-)
fuente
Una de las desventajas del constructor privado es que el método existente nunca podría probarse.
Enum por el concepto de naturaleza bueno para aplicar en un tipo de dominio específico, aplicarlo a constantes descentralizadas no parece lo suficientemente bueno
El concepto de Enum es "Las enumeraciones son conjuntos de elementos estrechamente relacionados".
Extender / implementar una interfaz constante es una mala práctica, es difícil pensar en el requisito de extender una constante inmutable en lugar de referirse a ella directamente.
Si aplica una herramienta de calidad como SonarSource, hay reglas que obligan al desarrollador a eliminar la interfaz constante, esto es algo incómodo ya que muchos proyectos disfrutan de la interfaz constante y rara vez se ven "extender" las cosas que suceden en interfaces constantes
fuente