¿Debería colocarse una colección de constantes en una clase o interfaz?


Si tengo una colección de constantes estáticas que quiero declarar centralmente para que puedan compartirse entre varios proyectos si se ponen en una clase o interfaz (Java).

En el pasado los he visto en su mayoría poner en una clase, pero empecé a pensar que ya que la clase no y no debe ser instanciado tal vez sería mejor en una interfaz, pero de nuevo la interfaz no debe ser implementado por ninguna clase, por ejemplo,

public class ErrorCodes {
    public static final String ERROR_1 = "-1";
    public static final String ERROR_2 = "-2";
}

O

public interface ErrorCodes {
    public static final String ERROR_1 = "-1";
    public static final String ERROR_2 = "-2";
}
Author: DaveJohnston, 2009-09-03

9 answers

Si tienen conexiones fuertes, entonces los pondría en una enumeración:

public enum Error {
  ERROR_1("-1", "foo went wrong"),
  ERROR_2("-2", "bar went wrong");

  private final String id;
  private final String message;

  Error(String id, String message) {
    this.id=id;
    this.message=message;
  }

  public String getId() {
    return id;
  }

  public String getMessage() {
    return message;
  }
}

La ventaja es que puede tener seguridad de tipo en su código y que puede agregar fácilmente búsquedas basadas en id (ya sea construyendo un HashMap<String,Error> en el constructor o simplemente haciendo un bucle sobre values()).

 29
Author: Joachim Sauer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-09-03 12:06:39

Algunas personas consideran que la interfaz constante es un anti-patrón ( http://en.wikipedia.org/wiki/Constant_interface) .

 9
Author: Andrey Adamovich,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-09-03 12:29:19

Debes hacerlo en una clase.

Una interfaz es una descripción de métodos disponibles, propiedades, etc. a los que los usuarios de la clase pueden acceder - implementando una interfaz, usted garantiza que los miembros declarados en la interfaz están disponibles para el usuario.

Una clase, por otro lado, es una descripción de un objeto o (si no eres demasiado duro con los principios OO...) un marcador de posición para los miembros estáticos. Personalmente me parece muy útil en algunos proyectos para almacenar un montón de constantes en una clase Settings, así que no tengo que buscar las definiciones en todo el proyecto. Creo que este enfoque es lo que buscas, también.

 5
Author: Tomas Lycken,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-09-03 12:06:54

El uso de importación estática debe considerarse aquí (para importar constantes definidas en una clase), o enumeración de tipo seguro.

Desde Interfaz para constantes

Colocar constantes en una interfaz era una técnica popular en los primeros días de Java, pero ahora muchos lo consideran un uso desagradable de las interfaces, ya que las interfaces deben tratar con los servicios proporcionados por un objeto, no sus datos.
Además, el las constantes usadas por una clase son típicamente un detalle de implementación, pero colocarlas en una interfaz las promueve a la API pública de la clase.

 5
Author: VonC,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-09-03 12:07:05

Esto se ha discutido antes de :

La razón por la que no desea las constantes en una interfaz es que atrae a las clases cliente a "implementar" esa interfaz (para acceder a las constantes sin prefijarlas con el nombre de la interfaz). No deberías, sin embargo-la interfaz no es realmente una interfaz para las capacidades del objeto, sino una conveniencia en tiempo de compilación arraigada en el tipo externo de la clase.

Hubo un tiempo en que la " constante interfaz " fue muy conveniente, pero siempre ha sido "incorrecto" y ni siquiera la pereza es una excusa para usarla ahora que tenemos import static declaraciones.

Editar: Aunque debo estar de acuerdo en que para el escenario presentado en su pregunta, los enum son más apropiados.

 5
Author: gustafc,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:30:24

Deberías ponerlos en la clase con un constructor privado.

public class ErrorCodes {
    private ErrorCodes() {} // prevents instantiation
    public static final String ERROR_1 = "-1";
    public static final String ERROR_2 = "-2";

}

O mejor aún, use una enumeración typesafe.

 2
Author: Billy Bob Bain,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-09-03 12:08:50

Recomiendo una combinación de importaciones estáticas e interfaces para constantes.

Si una interfaz Java tiene declaraciones de campo constantes, tenga en cuenta que estas son implícitamente públicas, estáticas y finales (consulte la Especificación del Lenguaje Java, Sección 9.3. Por lo tanto, siempre puede omitir estos modificadores, dejando solo el tipo, y su interfaz constante se vería así:

public interface Constants {
    int AGE = 0x23;
    String NAME = "Andrew";
    boolean IGNORE = true;
}

Esto debería, por supuesto, solo usarse como sigue:

import static Constants.*;

public Whatever {
    public String method() {
        return String.format("%s is %d%c", NAME, AGE, IGNORE ? '?' : '!');
    }
}

No tengo problemas con el uso de este estilo en mi código de producción, y siento que conduce a una colección de constantes muy limpia y compacta, y puede hacer frente a varios tipos de constantes, que una enumeración no podría, así como ser capaz de ser extendido si requred, a diferencia de una enumeración.

Otra posibilidad, que no todos aprobarán, es anidar interfaces (o incluso tipos de enumeración) en su interfaz padre, lo que le permite agrupar sus constantes. Esto:

interface MoreConstants {
    int MAGIC = 0xCAFEBABE;
    interface PROPERTIES {
        String NAME = "name";
    }
    enum ERRORS {
        ON_FIRE, ASLEEP, BROKEN, UNSURE;
    }
}

Y acceder a ellos así, asumiendo una importación estática de la interfaz MoreConstants :

if (!PROPERTIES.NAME.equals(value)) {
    return ERRORS.UNSURE;
}

Por supuesto, estas interfaces nunca deben implementarse, lo que consideraría una mala práctica. La única manera de asegurar esto, sin embargo, es revisiones estrictas del código...

 2
Author: grkvlt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-09-18 18:28:31

Personalmente creo que las constantes deben definirse en una clase por las mismas razones que se describen aquí arriba. Especialmente porque algunos desarrolladores usan estas constantes implementando la interfaz en la clase que quiere usarlas. Cuando esa interfaz contiene una gran cantidad de constantes que no desea mirar el javadoc de esa clase específica ya porque está lleno de descripciones de constantes que probablemente ni siquiera son utilizados por esa clase.

 0
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-09-03 13:45:51

Usar Interfaz para constantes es una buena práctica. Pero no desea implementar esa interfaz para usar las constantes. Pero use importación estática como se muestra a continuación.

package com.data.job.spark;

public interface Constants {

    /** base api url string literal. */
    public static final String BASE_API_URL = "/api/v1";
        /** message string literal. */
    public static final String MESSAGE = "message";

    /** exception string literal. */
    public static final String EXCEPTION = "exception";
}
=================================
import static com.data.job.spark.Constants.EXCEPTION;

@Component("user360ToScyllaDbLoader")
public class TestConstants implements Serializable{


    private static final long serialVersionUID = 1L;
}
 0
Author: Dakshin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-06 14:44:19