tipos - ¿Cómo se define una clase de constantes en Java?
tipos de variables en java (10)
Supongamos 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 debería usar y por qué?
Aclaraciones a algunas respuestas:Enums - No voy a usar enumeraciones, no estoy enumerando nada, solo estoy recopilando algunas constantes que no están relacionadas entre sí de ninguna manera.
Interfaz : no voy a configurar ninguna clase como una que implemente la interfaz. Solo quiero usar la interfaz para llamar a las constantes de ese modo: ISomeInterface.SOME_CONST
.
¿No son las enums la mejor opción para este tipo de cosas?
Como señala Joshua Bloch en Effective Java:
- Las interfaces solo deben usarse para definir tipos,
- las clases abstractas no evitan la inestabilidad (pueden subclasificarse, e incluso sugerir que están diseñadas para ser subclasificadas).
Puedes usar un Enum si todas tus constantes están relacionadas (como nombres de planetas), poner los valores constantes en las clases con las que están relacionadas (si tienes acceso a ellas), o usar una clase de utilidad no instanciable (definir un constructor privado por defecto) .
class SomeConstants
{
// Prevents instanciation of myself and my subclasses
private SomeConstants() {}
public final static String TOTO = "toto";
public final static Integer TEN = 10;
//...
}
Entonces, como ya se dijo, puede usar importaciones estáticas para usar sus constantes.
Mi método preferido es no hacer eso en absoluto. La edad de las constantes prácticamente murió cuando Java 5 introdujo enumeraciones seguras. E incluso antes, Josh Bloch publicó una versión (un poco más prolija) de eso, que funcionó en Java 1.4 (y versiones anteriores).
A menos que necesite interoperabilidad con algún código heredado, realmente no hay razón para usar las constantes de cadena / entero con nombre.
O 4. Ponlos en la clase que contiene la lógica que usa las constantes más
... lo siento, no pude resistir ;-)
Solo usa la clase final.
Si desea poder agregar otros valores, use una clase abstracta.
No tiene mucho sentido utilizar una interfaz, se supone que una interfaz debe especificar un contrato. Solo quiere declarar algunos valores constantes.
Su aclaración dice: "No voy a usar enumeraciones, no estoy enumerando nada, solo recogiendo algunas constantes que no están relacionadas entre sí de ninguna manera".
Si las constantes no están relacionadas entre sí, ¿por qué quieres juntarlas? Pon cada constante en la clase con la que está más relacionada.
Usa una clase final por simplicidad, 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)){
//...
}
enum
s están bien. IIRC, un elemento en Java efectivo (2nd Ed) tiene constantes de enumeración que enumeran las opciones estándar que implementan una interface
[palabras clave Java] para cualquier valor.
Mi preferencia es usar una interface
[Java keyword] sobre una final class
para constantes. Usted implícitamente obtiene el public static final
. Algunas personas argumentarán que una interface
permite que los programadores malos la implementen, pero los programadores malos escribirán código que apesta sin importar lo que hagas.
¿Qué se ve 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.";
}
Una de las desventajas del constructor privado es que el método existente nunca podría ser probado.
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".
Ampliar / implementar una interfaz constante es una mala práctica, es difícil pensar en la necesidad de extender una constante inmutable en lugar de referirse a ella directamente.
Si se aplica una herramienta de calidad como SonarSource, existen reglas que obligan al desarrollador a soltar la interfaz constante, esto es algo incómodo ya que muchos proyectos disfrutan de la interfaz constante y rara vez para ver cómo se "extienden" las cosas en interfaces constantes.
Mis sugerencias (en orden decreciente de preferencia):
1) No lo hagas Crea las constantes en la clase real donde son más relevantes. Tener una clase / interfaz de ''bolsa de constantes'' no sigue realmente las mejores prácticas de OO.
Yo, y todos los demás, ignoramos el # 1 de vez en cuando. Si vas a hacer eso, entonces:
2) clase final con constructor privado Esto evitará al menos que alguien abuse de su "bolsa de constantes" extendiéndola / implementándola para tener acceso fácil a las constantes. (Sé que dijiste que no harías esto, pero eso no significa que alguien venga después de ti)
3) interfaz Esto funcionará, pero no 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 la clase le importa una constante, debe ser privada y estar en esa clase. Si solo las pruebas se preocupan por una constante, debería estar en una clase de prueba, no en un código de producción. Si se define una constante en varios lugares (no solo accidentalmente), refactorice para eliminar la duplicación. Y así sucesivamente, trátelos como lo harías con un método.