He visto ejemplos como este:
public class MaxSeconds {
public static final int MAX_SECONDS = 25;
}
y supuse que podría tener una clase de Constantes para envolver constantes, declarándolas estáticas como finales. Prácticamente no conozco Java en absoluto y me pregunto si esta es la mejor manera de crear constantes.
Respuestas:
Eso es perfectamente aceptable, probablemente incluso el estándar.
donde
TYPE
es el tipo,NAME
es el nombre en mayúsculas con guiones bajos para espacios yVALUE
es el valor constante;Recomiendo NO poner sus constantes en sus propias clases o interfaces.
Como nota al margen: las variables que se declaran finales y son mutables aún se pueden cambiar; sin embargo, la variable nunca puede apuntar a un objeto diferente.
Por ejemplo:
Eso es legal y
ORIGIN
sería un punto en (3, 0).fuente
Recomiendo encarecidamente no tener una sola clase de constantes. Puede parecer una buena idea en ese momento, pero cuando los desarrolladores se niegan a documentar las constantes y la clase crece para abarcar más de 500 constantes que no están relacionadas entre sí (están relacionadas con aspectos completamente diferentes de la aplicación), esto generalmente se convierte en un archivo de constantes completamente ilegible. En lugar:
fuente
Es un MALA PRÁCTICA usar interfaces solo para mantener constantes ( Josh Bloch lo denomina patrón de interfaz constante ). Esto es lo que aconseja Josh:
Ejemplo:
Sobre la convención de nomenclatura:
fuente
abstract
notación para la clase en lugar del constructor privado.abstract
lugar de un constructor privado no evita por completo la creación de instancias, porque se podría subclasificar e instanciar la subclase (no es una buena idea hacerlo, pero es posible). @ToolmakerSteve No puede subclasificar una clase con un constructor privado (al menos no sin un gran truco malo), porque el constructor de la subclase necesita llamar al constructor (ahora privado) de su superclase. Entonces, marcarlofinal
es innecesario (pero quizás más explícito).En Java efectivo (2a edición), se recomienda que use enumeraciones en lugar de entradas estáticas para constantes.
Aquí hay una buena reseña sobre las enumeraciones en Java: http://java.sun.com/j2se/1.5.0/docs/guide/language/enums.html
Tenga en cuenta que al final de ese artículo la pregunta planteada es:
Con una respuesta de:
fuente
Solo evita usar una interfaz:
Es tentador, pero viola la encapsulación y difumina la distinción de las definiciones de clase.
fuente
Yo uso el siguiente enfoque:
Que, por ejemplo, solía
Constants.DB.Connection.URL
ser constante. Se ve más "objeto orientado" en cuanto a mí.fuente
Crear constantes finales estáticas en una clase separada puede meterte en problemas. El compilador de Java realmente optimizará esto y colocará el valor real de la constante en cualquier clase que lo haga referencia.
Si luego cambia la clase 'Constantes' y no realiza una compilación difícil en otras clases que hacen referencia a esa clase, terminará con una combinación de valores antiguos y nuevos que se están utilizando.
En lugar de pensar en estas como constantes, piense en ellas como parámetros de configuración y cree una clase para administrarlas. Haga que los valores sean no finales e incluso considere usar getters. En el futuro, si determina que algunos de estos parámetros deberían ser configurables por el usuario o el administrador, será mucho más fácil hacerlo.
fuente
El error número uno que puede cometer es crear una clase accesible globalmente llamada con un nombre genérico, como Constantes. Esto simplemente se llena de basura y pierde toda capacidad de averiguar qué parte de su sistema usa estas constantes.
En cambio, las constantes deben ir a la clase que las "posee". ¿Tienes una constante llamada TIMEOUT? Probablemente debería ir a su clase de Comunicaciones () o Conexión (). MAX_BAD_LOGINS_PER_HOUR? Entra en Usuario (). Y así sucesivamente y así sucesivamente.
El otro uso posible son los archivos .properties de Java cuando las "constantes" se pueden definir en tiempo de ejecución, pero no son fácilmente modificables por el usuario. Puede empaquetarlos en sus archivos .jars y hacer referencia a ellos con Class resourceLoader.
fuente
Ese es el camino correcto a seguir.
En general, las constantes no se guardan en clases separadas de "Constantes" porque no se pueden descubrir. Si la constante es relevante para la clase actual, mantenerla allí ayuda al próximo desarrollador.
fuente
¿Qué pasa con una enumeración?
fuente
Prefiero usar getters en lugar de constantes. Esos captadores pueden devolver valores constantes, por ejemplo
public int getMaxConnections() {return 10;}
, pero cualquier cosa que necesite la constante pasará por un captador.Una ventaja es que si su programa supera la constante (se da cuenta de que debe ser configurable), puede cambiar la forma en que el captador devuelve la constante.
El otro beneficio es que para modificar la constante no tiene que volver a compilar todo lo que la usa. Cuando hace referencia a un campo final estático, el valor de esa constante se compila en cualquier código de bytes que lo haga referencia.
fuente
Estoy de acuerdo en que usar una interfaz no es el camino a seguir. Evitar este patrón incluso tiene su propio elemento (# 18) en Java efectivo de Bloch .
Un argumento que hace Bloch contra el patrón de interfaz constante es que el uso de constantes es un detalle de implementación, pero la implementación de una interfaz para usarlos expone ese detalle de implementación en la API exportada.
El
public|private static final TYPE NAME = VALUE;
patrón es una buena forma de declarar una constante. Personalmente, creo que es mejor evitar hacer una clase separada para albergar todas tus constantes, pero nunca he visto una razón para no hacerlo, aparte de la preferencia personal y el estilo.Si sus constantes se pueden modelar bien como una enumeración, considere la estructura de enumeración disponible en 1.5 o posterior.
Si está utilizando una versión anterior a la 1.5, aún puede obtener enumeraciones seguras de tipo mediante el uso de clases Java normales. (Vea este sitio para más información sobre eso).
fuente
En base a los comentarios anteriores, creo que este es un buen enfoque para cambiar la clase constante global pasada de moda (que tiene variables finales estáticas públicas) a su equivalente enum de una manera como esta:
Entonces puedo referirlos a me gusta:
fuente
Un buen diseño orientado a objetos no debería necesitar muchas constantes disponibles públicamente. La mayoría de las constantes deben encapsularse en la clase que las necesita para hacer su trabajo.
fuente
Hay una cierta cantidad de opinión para responder esto. Para empezar, las constantes en java generalmente se declaran públicas, estáticas y finales. A continuación se detallan los motivos:
Nunca usaría una interfaz para un objeto / acceso CONSTANTES simplemente porque generalmente se espera que las interfaces se implementen. ¿No se vería esto gracioso?
En su lugar, elegiría entre algunas formas diferentes, en función de algunas pequeñas compensaciones, por lo que depende de lo que necesite:
fuente
Un enfoque que realmente deberíamos evitar : usar interfaces para definir constantes.
Crear una interfaz específicamente para declarar constantes es realmente lo peor: derrota la razón por la cual se diseñaron las interfaces: definir el contrato de método (s).
Incluso si ya existe una interfaz para abordar una necesidad específica, declarar las constantes en ellas realmente no tiene sentido ya que las constantes no deberían formar parte de la API y el contrato proporcionado a las clases de clientes.
Para simplificar, tenemos en general 4 enfoques válidos .
Con
static final String/Integer
campo:Con
Java 5 enum
:TLDR: ¿Cuál es la mejor manera y dónde ubicar las constantes?
En la mayoría de los casos, la forma enum es probablemente más fina que la
static final String/Integer
forma y personalmente creo que lastatic final String/Integer
forma debería usarse solo si tenemos buenas razones para no usar enumeraciones.Y sobre dónde deberíamos declarar los valores constantes, la idea es buscar si hay una sola clase existente que posea una cohesión funcional específica y fuerte con valores constantes. Si encontramos tal clase, deberíamos usarla como el titular de las constantes . De lo contrario, la constante no debe estar asociada a ninguna clase en particular.
static final String
/static final Integer
versusenum
El uso de enumeraciones es realmente una forma de considerarlo.
Las enumeraciones tienen una gran ventaja sobre el campo
String
oInteger
constante.Establecen una restricción de compilación más fuerte. Si define un método que toma la enumeración como parámetro, solo puede pasar un valor de enumeración definido en la clase de enumeración (o nulo).
Con String e Integer puede sustituirlos por cualquier valor de tipo compatible y la compilación estará bien incluso si el valor no es una constante definida en los campos
static final String
/static final Integer
.Por ejemplo, debajo de dos constantes definidas en una clase como
static final String
campos:Aquí un método que espera tener una de estas constantes como parámetro:
Puedes invocarlo de esta manera:
o
Pero ninguna restricción de compilación le impide invocarlo de esta manera:
Tendría el error solo en tiempo de ejecución y solo si realiza una comprobación a la vez del valor transmitido.
Con enum, no se requieren comprobaciones ya que el cliente solo puede pasar un valor enum en un parámetro enum.
Por ejemplo, aquí hay dos valores definidos en una clase enum (tan constante fuera de la caja):
Aquí un método que espera tener uno de estos valores de enumeración como parámetro:
Puedes invocarlo de esta manera:
o
Pero la compilación nunca le permitirá invocarlo de esta manera:
¿Dónde debemos declarar las constantes?
Si su aplicación contiene una sola clase existente que posee una cohesión funcional específica y fuerte con los valores constantes, el 1) y el 2) parecen más intuitivos.
En general, facilita el uso de las constantes si se declaran en la clase principal que las manipula o que tienen un nombre muy natural para adivinar que lo encontraremos dentro.
Por ejemplo, en la biblioteca JDK, los valores exponenciales y constantes pi se declaran en una clase que declara no solo declaraciones constantes (
java.lang.Math
).Los clientes que usan funciones matemáticas dependen a menudo de la
Math
clase. Por lo tanto, pueden encontrar constantes con bastante facilidad y también pueden recordar dóndeE
yPI
se definen de una manera muy natural.Si su aplicación no contiene una clase existente que tenga una cohesión funcional muy específica y fuerte con los valores constantes, las formas 1 variante) y 2 variante parecen más intuitivas.
En general, no facilita el uso de las constantes si se declaran en una clase que las manipula, mientras que también tenemos otras 3 o 4 clases que las manipulan tanto y ninguna de estas clases parece ser más natural que otras. hospedar valores constantes.
Aquí, definir una clase personalizada para contener solo valores constantes tiene sentido.
Por ejemplo, en la biblioteca JDK, la
java.util.concurrent.TimeUnit
enumeración no se declara en una clase específica ya que en realidad no hay una sola clase específica JDK que aparezca como la más intuitiva para contenerla:Muchas clases declaradas en
java.util.concurrent
el uso de ellos:BlockingQueue
,ArrayBlockingQueue<E>
,CompletableFuture
,ExecutorService
, ... y realmente ninguno de ellos parece más apropiado para mantener la enumeración.fuente
Una constante, de cualquier tipo, puede declararse creando una propiedad inmutable que dentro de una clase (que es una variable miembro con el
final
modificador). Por lo general, también se proporcionan los modificadoresstatic
ypublic
.Existen numerosas aplicaciones donde el valor de una constante indica una selección de una n-tupla (por ejemplo, enumeración ) de opciones. En nuestro ejemplo, podemos elegir definir un Tipo enumerado que restringirá los posibles valores asignados (es decir , seguridad de tipo mejorada ):
fuente
Una sola clase de constantes genéricas es una mala idea. Las constantes deben agruparse con la clase con la que están más relacionadas lógicamente.
En lugar de usar variables de cualquier tipo (especialmente enumeraciones), sugeriría que use métodos. Cree un método con el mismo nombre que la variable y haga que devuelva el valor que asignó a la variable. Ahora elimine la variable y reemplace todas las referencias con llamadas al método que acaba de crear. Si cree que la constante es lo suficientemente genérica como para no tener que crear una instancia de la clase solo para usarla, entonces haga que el método constante sea un método de clase.
fuente
FWIW, un valor de tiempo de espera en segundos probablemente debería ser una configuración (leída desde un archivo de propiedades o mediante inyección como en Spring) y no una constante.
fuente
Cuál es la diferencia
1)
2)
y usar
MyGlobalConstants.TIMEOUT_IN_SECS
donde sea que necesitemos esta constante. Creo que ambos son iguales.fuente
No llamaría a la clase lo mismo (aparte de la carcasa) como la constante ... Tendría como mínimo una clase de "Configuración", "Valores" o "Constantes", donde vivirían todas las constantes. Si tengo un gran número de ellos, los agruparía en clases constantes lógicas (UserSettings, AppSettings, etc.)
fuente
Para ir un paso más allá, puede colocar constantes usadas globalmente en una interfaz para que puedan usarse en todo el sistema. P.ej
Pero no lo implemente. Simplemente refiérase a ellos directamente en código a través del nombre de clase completamente calificado.
fuente
Para Constantes, Enum es una mejor opción en mi humilde opinión. Aquí hay un ejemplo
clase pública myClass {
fuente
Una de las formas en que lo hago es creando una clase 'Global' con los valores constantes y haciendo una importación estática en las clases que necesitan acceso a la constante.
fuente
static final
es mi preferencia, solo usaría unenum
si el elemento fuera realmente enumerable.fuente
yo suelo
static final
a declarar constantes e ir con los nombres ALL_CAPS notación. He visto bastantes instancias de la vida real donde todas las constantes se agrupan en una interfaz. Algunas publicaciones lo han llamado acertadamente una mala práctica, principalmente porque no es para eso que sirve una interfaz. Una interfaz debe hacer cumplir un contrato y no debe ser un lugar para colocar constantes no relacionadas. Ponerlo junto en una clase que no se pueda instanciar (a través de un constructor privado) también está bien si la semántica constante no pertenece a una clase específica ( es). Siempre pongo una constante en la clase con la que está más relacionada, porque eso tiene sentido y también es fácil de mantener.Las enumeraciones son una buena opción para representar un rango de valores, pero si está almacenando constantes independientes con énfasis en el valor absoluto (p. Ej., TIEMPO DE ESPERA = 100 ms), simplemente puede optar por el
static final
enfoque.fuente
Estoy de acuerdo con lo que la mayoría dice, es mejor usar enumeraciones cuando se trata de una colección de constantes. Sin embargo, si está programando en Android, hay una solución mejor: Anotación IntDef .
La anotación IntDef es superior a las enumeraciones de una manera simple, ocupa mucho menos espacio, ya que es simplemente un marcador de tiempo de compilación. No es una clase, ni tiene la propiedad de conversión automática de cadenas.
fuente
Es MALO hábito y una práctica terriblemente molesta citar a Joshua Bloch sin comprender el fundamentalismo básico de la zona cero.
No he leído nada Joshua Bloch, así que tampoco
Como en el fundamentalismo bíblico, todas las leyes bíblicas pueden resumirse por
y de manera similar, el fundamentalismo de la ingeniería de software puede resumirse en
Además, entre los círculos fundamentalistas bíblicos se dibuja un corolario fuerte y razonable.
Del mismo modo, si no te respetas a ti mismo como programador y solo aceptas los pronunciamientos y las profecías de algún gurú de la programación SIN cuestionar los fundamentos, tus citas y tu confianza en Joshua Bloch (y similares) no tiene sentido. Y, por lo tanto, en realidad no respetarías a tus compañeros programadores.
Las leyes fundamentales de la programación de software.
¿Las constantes de patrón de interfaz son un mal hábito?
¿Bajo qué leyes de programación fundamentalmente efectiva y responsable cae este edicto religioso?
Simplemente lea el artículo de Wikipedia sobre las constantes de patrón de interfaz ( https://en.wikipedia.org/wiki/Constant_interface ), y las tontas excusas que establece contra las constantes de patrón de interfaz.
Whatif-No IDE? ¿Quién en la tierra como programador de software no usaría un IDE? La mayoría de nosotros somos programadores que preferimos no tener que demostrar que tenemos un sobrevivencia machista y estético para evitar el uso de un IDE.
¿Contamina el espacio de nombres con variables no utilizadas dentro del alcance actual? Podrían ser defensores de esta opinión
El uso de interfaces para aplicar constantes es un abuso de las interfaces. Los defensores de tales tienen la mala costumbre de
Es difícil, si no imposible, convertir las interfaces en clases implementadas en el futuro. Hah .... hmmm ... ???
Cualesquiera que sean las excusas, NO HAY EXCUSA VÁLIDA cuando se trata de ingeniería de software FUNDAMENTAMENTE EFECTIVA para deslegitimar o, en general, desalentar el uso de constantes de interfaz.
No importa cuáles fueron las intenciones originales y los estados mentales de los padres fundadores que elaboraron la Constitución de los Estados Unidos. Podríamos debatir las intenciones originales de los padres fundadores, pero lo único que me importa son las declaraciones escritas de la Constitución de los Estados Unidos. Y es responsabilidad de cada ciudadano estadounidense explotar el fundamentalismo literario escrito, no las intenciones fundacionales no escritas, de la Constitución de los Estados Unidos.
Del mismo modo, no me importa lo que las intenciones "originales" de los fundadores de la plataforma Java y el lenguaje de programación tenían para la interfaz. Lo que me importa son las características efectivas que proporciona la especificación Java, y tengo la intención de explotar esas características al máximo para ayudarme a cumplir con las leyes fundamentales de la programación de software responsable. No me importa si se percibe que "viola la intención de las interfaces". No me importa lo que Gosling o alguien Bloch diga sobre la "forma correcta de usar Java", a menos que lo que digan no viole mi necesidad de cumplir con los fundamentos EFICAZmente.
Lo fundamental es la normalización del modelo de datos
No importa cómo se aloje o transmita su modelo de datos. Ya sea que use interfaces o enumeraciones o cualquier otra cosa, relacional o sin SQL, si no comprende la necesidad y el proceso de normalización del modelo de datos.
Primero debemos definir y normalizar el modelo de datos de un conjunto de procesos. Y cuando tenemos un modelo de datos coherente, SOLO podemos usar el flujo de proceso de sus componentes para definir el comportamiento funcional y el proceso bloquea un campo o ámbito de aplicaciones. Y solo entonces podemos definir la API de cada proceso funcional.
Incluso las facetas de la normalización de datos propuestas por EF Codd ahora se ven seriamente desafiadas y severamente desafiadas. Por ejemplo, su declaración sobre 1NF ha sido criticada por ser ambigua, desalineada y simplificada en exceso, al igual que el resto de sus declaraciones, especialmente en el advenimiento de los servicios de datos modernos, tecnología de transmisión y transmisión. En mi opinión, las declaraciones de EF Codd deben eliminarse por completo y diseñarse un nuevo conjunto de declaraciones más matemáticamente plausibles.
Una falla evidente de EF Codd's y la causa de su desalineación con la comprensión humana efectiva es su creencia de que los datos de dimensiones mutables y multidimensionales perceptibles humanamente pueden percibirse eficientemente a través de un conjunto de mapeos bidimensionales fragmentados.
Los fundamentos de la normalización de datos
Lo que EF Codd no pudo expresar.
Dentro de cada modelo de datos coherente, estos son el orden secuencial graduado de coherencia del modelo de datos a lograr.
En un campo o cuadrícula de aplicaciones de componentes entre servicios, debe haber un solo modelo de datos coherente o existe un medio para que un modelo / versión de datos se identifique.
¿Todavía estamos preguntando si podríamos usar las constantes de interfaz? De Verdad ?
Hay problemas de normalización de datos en juego más consecuentes que esta pregunta mundana. SI no resuelve esos problemas, la confusión que cree que causan las constantes de la interfaz es comparativamente nada. Nada.
A partir de la normalización del modelo de datos, usted determina los componentes como variables, como propiedades, como constantes de interfaz de contrato.
Luego, determina qué se aplica a la inyección de valor, la retención de la configuración de propiedad, las interfaces, las cadenas finales, etc.
Si tiene que usar la excusa de necesitar localizar un componente más fácil de dictar contra las constantes de la interfaz, significa que tiene la mala costumbre de no practicar la normalización del modelo de datos.
Quizás desee compilar el modelo de datos en una versión vcs. Que puede extraer una versión claramente identificable de un modelo de datos.
Los valores definidos en las interfaces están completamente garantizados para ser no mutables. Y compartible. ¿Por qué cargar un conjunto de cadenas finales en su clase desde otra clase cuando todo lo que necesita es ese conjunto de constantes?
Entonces, ¿por qué no esto para publicar un contrato de modelo de datos? Quiero decir, si puedes manejarlo y normalizarlo de manera coherente, ¿por qué no? ...
Ahora puedo hacer referencia a las etiquetas contratadas de mis aplicaciones de una manera como
Esto confunde el contenido del archivo jar? Como programador de Java, no me importa la estructura del jar.
¿Esto presenta complejidad al intercambio de tiempo de ejecución motivado por osgi? Osgi es un medio extremadamente eficiente para permitir que los programadores continúen con sus malos hábitos. Hay mejores alternativas que osgi.
¿O por qué no esto? No hay fugas de las constantes privadas en el contrato publicado. Todas las constantes privadas deben agruparse en una interfaz privada llamada "Constantes", porque no quiero tener que buscar constantes y soy demasiado vago para escribir repetidamente "Cadena final privada".
Quizás incluso esto:
El único problema con las constantes de la interfaz que vale la pena considerar es cuando se implementa la interfaz.
¿Esta no es la "intención original" de las interfaces? Como si me importara la "intención original" de los padres fundadores en la elaboración de la Constitución de los Estados Unidos, en lugar de cómo la Corte Suprema interpretaría las cartas escritas de la Constitución de los Estados Unidos.
Después de todo, vivo en la tierra de los libres, los salvajes y el hogar de los valientes. Sé valiente, sé libre, sé salvaje: utiliza la interfaz. Si mis compañeros programadores se niegan a usar medios de programación eficientes y perezosos, ¿estoy obligado por la regla de oro a disminuir mi eficiencia de programación para alinearme con la de ellos? Tal vez debería, pero esa no es una situación ideal.
fuente