Qual é a melhor maneira de implementar constantes em Java? [fechadas]


372

Eu já vi exemplos como este:

public class MaxSeconds {
   public static final int MAX_SECONDS = 25;
}

e supunha que eu poderia ter uma classe Constantes para agrupar constantes, declarando-as estáticas como finais. Conheço praticamente nenhum Java e estou me perguntando se essa é a melhor maneira de criar constantes.



Respostas:


403

Isso é perfeitamente aceitável, provavelmente até o padrão.

(public/private) static final TYPE NAME = VALUE;

onde TYPEé o tipo, NAMEé o nome em todas as maiúsculas com sublinhado de espaços e VALUEé o valor constante;

Eu recomendo NÃO colocar suas constantes em suas próprias classes ou interfaces.

Como observação lateral: Variáveis ​​declaradas finais e mutáveis ​​ainda podem ser alteradas; no entanto, a variável nunca pode apontar para um objeto diferente.

Por exemplo:

public static final Point ORIGIN = new Point(0,0);

public static void main(String[] args){

    ORIGIN.x = 3;

}

Isso é legal e ORIGINseria então um ponto em (3, 0).


19
Você pode até 'importar MaxSeconds.MAX_SECONDS estático;' para que você não precise soletrá-lo MaxSeconds.MAX_SECONDS
Aaron Maenpaa

23
O comentário anterior sobre a importação estática se aplica apenas ao Java 5+. Alguns acham que a taquigrafia não vale a confusão possível de onde a constante veio, ao ler o código longo, MaxSeconds.MAX_SECONDS pode ser mais fácil de seguir do que subir e examinar as importações.
MetroidFan2002 15/09/08

5
Como você pode alterar o objeto, como o jjnguy mostrou, é melhor que suas constantes sejam objetos imutáveis ​​ou apenas primitivas / strings simples.
Marcospereira 16/09/08

14
Se você está lendo esta pergunta, leia as próximas duas respostas abaixo antes de levar a resposta muito a sério, apesar de ser aceito, é controverso se não estiver errado.
orbfish

3
@jjnguy você não está errado, mas se eu ler apenas a pergunta e as duas primeiras linhas da sua resposta, ficaria com a impressão de que "uma classe de constantes" é "perfeitamente aceitável, provavelmente até o padrão". Essa noção está errada.
Zach Lysobey

235

Eu recomendaria altamente não ter uma única classe de constantes. Pode parecer uma boa ideia no momento, mas quando os desenvolvedores se recusam a documentar constantes e a classe cresce para abranger mais de 500 constantes que nem todas são relacionadas umas às outras (sendo relacionadas a aspectos totalmente diferentes do aplicativo), geralmente se transforma no arquivo de constantes sendo completamente ilegível. Em vez de:

  • Se você tiver acesso ao Java 5+, use enums para definir suas constantes específicas para uma área de aplicativo. Todas as partes da área de aplicação devem se referir a enumerações, e não valores constantes, para essas constantes. Você pode declarar uma enumeração semelhante à forma como declara uma classe. Enums são talvez o recurso mais (e, possivelmente, apenas) útil do Java 5+.
  • Se você tiver constantes válidas apenas para uma classe específica ou uma de suas subclasses, declare-as como protegidas ou públicas e coloque-as na classe superior na hierarquia. Dessa forma, as subclasses podem acessar esses valores constantes (e se outras classes os acessarem via público, as constantes não são válidas apenas para uma classe específica ... o que significa que as classes externas que usam essa constante podem estar muito acopladas ao classe que contém a constante)
  • Se você possui uma interface com comportamento definido, mas os valores retornados ou os argumentos devem ser específicos, é perfeitamente aceitável definir constantes nessa interface para que outros implementadores tenham acesso a elas. No entanto, evite criar uma interface apenas para manter constantes: ela pode se tornar tão ruim quanto uma classe criada apenas para manter constantes.

12
concordo totalmente ... isso pode ser documentado como um anti-padrão clássico para grandes projetos.
Das

30
Off topic, mas ... Os genéricos certamente não são perfeitos, mas eu acho que você poderia fazer um caso muito bom para eles ser um recurso útil do Java 5 :)
Martin McNulty

3
@ ŁukaszL. A pergunta em si é realmente baseada em opiniões (sempre que "melhor" surge, geralmente é uma questão de opinião), portanto a resposta é uma resposta válida para essa pergunta. Eu dei uma resposta sobre o que (sim, eu acredito que seja, então sim, é uma opinião, porque novamente "melhor" muda com o tempo e geralmente é baseada em opiniões) a melhor maneira de implementar constantes em Java é.
precisa saber é o seguinte

11
Nenhuma das opções acima fornece uma variável global verdadeira. E se eu tiver algo que é usado em todos os lugares, mas não é um enum? Eu faço uma enumeração de apenas uma coisa?
markthegrea

11
Se você precisar de uma constante global que abranja todos os módulos, provavelmente há algo errado com sua estratégia de design. Se você realmente precisa de uma constante global, faça uma aula final pública para ela no pacote de nível superior e cole-a lá. Em seguida, exclua-o assim que perceber que nem todas as suas classes realmente precisam dessa constante e mova-a para o pacote que mais faz referência a ela. Você pode compartilhar uma constante entre pacotes, mas é um código exigir uma constante global que não seja um tipo enumerado, pois tipos enumerados podem ter comportamento, mas uma string é uma string, um int é um int etc.
MetroidFan2002

120

É uma PRÁTICA RUIM usar interfaces apenas para manter constantes (denominado padrão de interface constante por Josh Bloch). Aqui está o que Josh aconselha:

Se as constantes estiverem fortemente vinculadas a uma classe ou interface existente, você deverá adicioná-las à classe ou interface. Por exemplo, todas as classes primitivas numéricas em caixas, como Inteiro e Duplo, exportam constantes MIN_VALUE e MAX_VALUE. Se as constantes são melhor visualizadas como membros de um tipo enumerado, você deve exportá-las com um tipo de enumeração . Caso contrário, você deve exportar as constantes com uma classe de utilitário não instável.

Exemplo:

// Constant utility class
package com.effectivejava.science;
public class PhysicalConstants {
    private PhysicalConstants() { }  // Prevents instantiation

    public static final double AVOGADROS_NUMBER   = 6.02214199e23;
    public static final double BOLTZMANN_CONSTANT = 1.3806503e-23;
    public static final double ELECTRON_MASS      = 9.10938188e-31;
}

Sobre a convenção de nomenclatura:

Por convenção, esses campos têm nomes que consistem em letras maiúsculas, com palavras separadas por sublinhados. É fundamental que esses campos contenham valores primitivos ou referências a objetos imutáveis.


23
Se você vai chamar algo de má prática, talvez deva explicar por que pensa que é?
Glenns

14
Esta é uma postagem antiga, mas é melhor usar a abstractnotação para a classe em vez do construtor privado.
Xtreme Biker

5
Matt, embora a recomendação do motociclista não seja falsa, eu defenderia as aulas finais, em vez de abstratas. O argumento do motociclista em dizer que é que você deseja garantir que sua classe de constantes não seja alterável. Portanto, marcando-o como final, você não está permitindo que seja subclassificado ou instanciado. Isso também ajuda a encapsular sua funcionalidade estática e não permite que outros desenvolvedores a subclassifiquem e façam coisas que não foram projetadas.
liltitus27

7
@XtremeBiker Marcar a classe em abstractvez de um construtor privado não impede completamente a instanciação, porque é possível subclassificá-la e instanciar a subclasse (não que seja uma boa ideia fazê-lo, mas seja possível). @ToolmakerSteve Você não pode subclassificar uma classe com um construtor privado (pelo menos não sem um grande hack), porque o construtor da subclasse precisa chamar o construtor (agora privado) de sua superclasse. Portanto, marcá-lo finalé desnecessário (mas talvez mais explícito).
importe este

3
É ainda pior usar a classe apenas para manter constantes. Se você nunca deseja criar um objeto dessa classe, por que usa a classe regular em primeiro lugar?
MaxZoom 5/05

36

No Java efetivo (2ª edição), é recomendável usar enumerações em vez de entradas estáticas para constantes.

Há uma boa descrição sobre enumerações em Java aqui: http://java.sun.com/j2se/1.5.0/docs/guide/language/enums.html

Observe que, no final desse artigo, a pergunta é:

Então, quando você deve usar enums?

Com uma resposta de:

Sempre que você precisar de um conjunto fixo de constantes


21

Apenas evite usar uma interface:

public interface MyConstants {
    String CONSTANT_ONE = "foo";
}

public class NeddsConstant implements MyConstants {

}

É tentador, mas viola o encapsulamento e desfoca a distinção das definições de classe.


11
De fato, importações estáticas são muito preferíveis.
Aaron Maenpaa 15/09/08

11
Essa prática é um uso estranho de interfaces, cujo objetivo é declarar os serviços fornecidos por uma classe.
Rafa Romero

11
Não discordo de evitar o uso de interface para constantes, mas acho que seu exemplo é enganoso. Você não precisa implementar a interface para obter acesso à constante, porque é implicitamente estática, pública e final. Portanto, é mais simples do que você descreveu aqui.
precisa saber é o seguinte

Isso é verdade ... está violando o encapsulamento, prefiro usar a classe Constant final, que parece mais orientada a objetos e preferível à interface OR enum . Nota: Enum pode ser evitado caso o Android não seja necessário.
CoDe

19

Eu uso a seguinte abordagem:

public final class Constants {
  public final class File {
    public static final int MIN_ROWS = 1;
    public static final int MAX_ROWS = 1000;

    private File() {}
  }

  public final class DB {
    public static final String name = "oups";

    public final class Connection {
      public static final String URL = "jdbc:tra-ta-ta";
      public static final String USER = "testUser";
      public static final String PASSWORD = "testPassword";

      private Connection() {}
    }

    private DB() {}
  }

  private Constants() {}
}

Por exemplo, eu uso Constants.DB.Connection.URLpara ficar constante. Parece mais "orientado a objetos" quanto a mim.


4
Interessante, mas complicado. Por que você não criaria constantes na classe mais intimamente associadas a elas, conforme recomendado por outras pessoas? Por exemplo, em seu código de banco de dados em outro lugar, você tem uma classe base para suas conexões? Por exemplo, "ConnectionBase". Então você pode colocar as constantes lá. Qualquer código que esteja trabalhando com conexões provavelmente já terá uma importação, que pode simplesmente dizer "ConnectionBase.URL" em vez de "Constants.DB.Connection.URL".
Home

3
@ToolmakerSteve Mas e as constantes gerais que várias classes podem usar? por exemplo, estilos, URLs de serviços da web, etc ...?
Daniel Gomez Rico

Colocar todas as constantes em uma classe tem uma vantagem - manutenção. Você sempre sabe exatamente onde encontrar as constantes. Não estou dizendo que isso melhore essa técnica, apenas estou oferecendo uma vantagem. E o que o @ albus.ua fez é categorizar suas constantes, o que é uma boa idéia, especialmente se a classe de constantes contiver muitos valores constantes. Essa técnica ajudará a manter a classe gerenciável e a descrever melhor o objetivo da constante.
Nelda.techspiress

17

Criar constantes finais estáticas em uma classe separada pode causar problemas. O compilador Java realmente otimiza isso e coloca o valor real da constante em qualquer classe que a referenciar.

Se você alterar posteriormente a classe 'Constants' e não fizer uma recompilação com outras classes que fazem referência a essa classe, você terminará com uma combinação de valores antigos e novos sendo usados.

Em vez de pensar nelas como constantes, pense nelas como parâmetros de configuração e crie uma classe para gerenciá-las. Tenha os valores não finais e considere o uso de getters. No futuro, como você determinar que alguns desses parâmetros realmente devem ser configuráveis ​​pelo usuário ou administrador, será muito mais fácil.


+1 para esta excelente ressalva. (Se você não pode garantir que é uma constante permanente, considere um getter, como big_peanut_horse menciona.) O mesmo se aplica à const em C #, a propósito: msdn.microsoft.com/en-us/library/e6w8fe1b.aspx
Jon Coombs

13

O erro número um que você pode cometer é criar uma classe acessível globalmente chamada com um nome genérico, como Constantes. Isso simplesmente fica cheio de lixo e você perde toda a capacidade de descobrir qual parte do seu sistema usa essas constantes.

Em vez disso, as constantes devem entrar na classe que as "possui". Você tem uma constante chamada TIMEOUT? Provavelmente deve entrar na sua classe Communications () ou Connection (). MAX_BAD_LOGINS_PER_HOUR? Entra em Usuário (). E assim por diante.

O outro uso possível são os arquivos Java .properties quando "constantes" podem ser definidas em tempo de execução, mas não são facilmente alteráveis ​​pelo usuário. Você pode empacotá-los em seus .jars e referenciá-los com o class resourceLoader.


E, é claro, você nunca desejaria acessar uma constante de mais de uma classe, ou evitar confusão no topo de uma classe.
orbfish

6

Esse é o caminho certo a seguir.

Geralmente, as constantes não são mantidas em classes "Constantes" separadas porque não são detectáveis. Se a constante for relevante para a classe atual, mantê-los lá ajuda o próximo desenvolvedor.



5

Eu prefiro usar getters do que constantes. Esses getters podem retornar valores constantes, por exemplo public int getMaxConnections() {return 10;}, mas qualquer coisa que precise da constante passará por um getter.

Um benefício é que, se o seu programa ultrapassar a constante - você achar que precisa ser configurável - você poderá alterar como o getter retorna a constante.

O outro benefício é que, para modificar a constante, você não precisa recompilar tudo o que a usa. Quando você faz referência a um campo final estático, o valor dessa constante é compilado em qualquer bytecode que a referencie.


5
A recompilação de classes de referência é dificilmente um fardo no século XXI. E você nunca deve usar o modelo de acessador / mutador (getter / setter) para outras coisas além de acessar e alterar variáveis ​​de membro. Conceitualmente, as constantes devem ser imediatas na natureza, enquanto os getter / setters são (ambos) destinados a gerenciar o estado . Além disso, você está apenas pedindo confusão: as pessoas não esperam que um empreendedor produza uma mera constante.

5

Concordo que o uso de uma interface não é o caminho a percorrer. Evitar esse padrão ainda tem seu próprio item (# 18) no Java eficaz de Bloch .

Um argumento que Bloch faz contra o padrão de interface constante é que o uso de constantes é um detalhe de implementação, mas a implementação de uma interface para usá-los expõe esse detalhe de implementação em sua API exportada.

o public|private static final TYPE NAME = VALUE; padrão é uma boa maneira de declarar uma constante. Pessoalmente, acho que é melhor evitar fazer uma aula separada para abrigar todas as suas constantes, mas nunca vi uma razão para não fazer isso, além da preferência e estilo pessoais.

Se suas constantes puderem ser bem modeladas como uma enumeração, considere o enum estrutura de disponível em 1.5 ou posterior.

Se você estiver usando uma versão anterior à 1.5, ainda poderá extrair enumerações de tipos seguros usando classes Java normais. (Veja este site para mais informações).


Algumas constantes podem ser usadas para chamar uma API. Por exemplo, consulte a interface org.springframework.transaction.TransactionDefinition. Possui uma lista de constantes como int PROPAGATION_REQUIRED = 0;
borjab

Eu sei que isso é antigo, mas o link para o Java efetivo de Bloch está quebrado. Você poderia fornecer outra ou outra referência apoiando que "usar uma interface não é o caminho a seguir", por favor?
Nelda.techspiress

4

Com base nos comentários acima, acho que essa é uma boa abordagem para alterar a classe constante global à moda antiga (com variáveis ​​finais estáticas públicas) para seu equivalente enum da seguinte maneira:

public class Constants {

    private Constants() {
        throw new AssertionError();
    }

    public interface ConstantType {}

    public enum StringConstant implements ConstantType {
        DB_HOST("localhost");
        // other String constants come here

        private String value;
        private StringConstant(String value) {
            this.value = value;
        }
        public String value() {
            return value;
        }
    }

    public enum IntConstant implements ConstantType {
        DB_PORT(3128), 
        MAX_PAGE_SIZE(100);
        // other int constants come here

        private int value;
        private IntConstant(int value) {
            this.value = value;
        }
        public int value() {
            return value;
        }
    }

    public enum SimpleConstant implements ConstantType {
        STATE_INIT,
        STATE_START,
        STATE_END;
    }

}

Então, eu posso indicá-los para gostar:

Constants.StringConstant.DB_HOST

4
Por quê? Como isso é uma melhoria? Agora todas as referências são complicadas (Constants.StringConstant.whatever). IMHO, você está indo por uma estrada esburacada aqui.
Home

3

Um bom design orientado a objetos não deve precisar de muitas constantes publicamente disponíveis. A maioria das constantes deve ser encapsulada na classe que precisa delas para fazer seu trabalho.


11
Ou injetado nessa classe por meio do construtor.
WW.

2

Há uma certa quantidade de opinião para responder a isso. Para começar, as constantes em java geralmente são declaradas públicas, estáticas e finais. Abaixo estão os motivos:

public, so that they are accessible from everywhere
static, so that they can be accessed without any instance. Since they are constants it
  makes little sense to duplicate them for every object.
final, since they should not be allowed to change

Eu nunca usaria uma interface para um acessador / objeto CONSTANTS simplesmente porque geralmente é esperado que as interfaces sejam implementadas. Isso não seria engraçado:

String myConstant = IMyInterface.CONSTANTX;

Em vez disso, eu escolheria entre algumas maneiras diferentes, com base em algumas vantagens e desvantagens, e isso depende do que você precisa:

1.  Use a regular enum with a default/private constructor. Most people would define 
     constants this way, IMHO.
  - drawback: cannot effectively Javadoc each constant member
  - advantage: var members are implicitly public, static, and final
  - advantage: type-safe
  - provides "a limited constructor" in a special way that only takes args which match
     predefined 'public static final' keys, thus limiting what you can pass to the
     constructor

2.  Use a altered enum WITHOUT a constructor, having all variables defined with 
     prefixed 'public static final' .
  - looks funny just having a floating semi-colon in the code
  - advantage: you can JavaDoc each variable with an explanation
  - drawback: you still have to put explicit 'public static final' before each variable
  - drawback: not type-safe
  - no 'limited constructor'

3.  Use a Class with a private constructor:
  - advantage: you can JavaDoc each variable with an explanation
  - drawback: you have to put explicit 'public static final' before each variable
  - you have the option of having a constructor to create an instance
     of the class if you want to provide additional functions related
     to your constants 
     (or just keep the constructor private)
  - drawback: not type-safe

4. Using interface:
  - advantage: you can JavaDoc each variable with an explanation
  - advantage: var members are implicitly 'public static final'
  - you are able to define default interface methods if you want to provide additional
     functions related to your constants (only if you implement the interface)
  - drawback: not type-safe

2

Qual é a melhor maneira de implementar constantes em Java?

Uma abordagem que realmente devemos evitar : usar interfaces para definir constantes.

Criar uma interface especificamente para declarar constantes é realmente a pior coisa: derrota a razão pela qual as interfaces foram projetadas: definindo o (s) método (s) contratado (s).

Mesmo que já exista uma interface para atender a uma necessidade específica, declarar as constantes nelas não faz muito sentido, pois as constantes não devem fazer parte da API e do contrato fornecido às classes do cliente.


Para simplificar, temos amplamente quatro abordagens válidas .

Com static final String/Integercampo:

  • 1) usando uma classe que declara constantes internas, mas não apenas.
  • 1 variante) criando uma classe dedicada a declarar apenas constantes.

Com Java 5 enum:

  • 2) declarar a enumeração em uma classe de finalidade relacionada (como uma classe aninhada).
  • 2) criando a enumeração como uma classe autônoma (definida em seu próprio arquivo de classe).

TLDR: Qual é a melhor maneira e onde localizar as constantes?

Na maioria dos casos, a maneira enum é provavelmente melhor do que a static final String/Integermaneira e, pessoalmente, acho que a static final String/Integermaneira deve ser usada apenas se tivermos boas razões para não usar enum.
E sobre onde devemos declarar os valores constantes, a idéia é pesquisar se existe uma única classe existente que possua uma coesão funcional específica e forte com valores constantes. Se encontrarmos essa classe, devemos usá-la como detentora de constantes . Caso contrário, a constante deve ser associada a nenhuma classe em particular.


static final String/ static final Integerversusenum

O uso de enums é realmente uma maneira de considerar fortemente.
Enums têm uma grande vantagem sobre Stringou Integercampo constante.
Eles estabelecem uma restrição de compilação mais forte. Se você definir um método que aceita a enum como parâmetro, poderá transmitir apenas um valor de enum definido na classe de enum (ou nula).
Com String e Inteiro, você pode substituí-los por quaisquer valores do tipo compatível e a compilação será boa, mesmo que o valor não seja uma constante definida nos campos static final String/ static final Integer.

Por exemplo, abaixo de duas constantes definidas em uma classe como static final Stringcampos:

public class MyClass{

   public static final String ONE_CONSTANT = "value";
   public static final String ANOTHER_CONSTANT = "other value";
   . . .
}

Aqui, um método que espera ter uma dessas constantes como parâmetro:

public void process(String constantExpected){
    ...    
}

Você pode invocá-lo desta maneira:

process(MyClass.ONE_CONSTANT);

ou

process(MyClass.ANOTHER_CONSTANT);

Mas nenhuma restrição de compilação impede que você a invoque desta maneira:

process("a not defined constant value");

Você teria o erro apenas no tempo de execução e somente se fizer uma verificação de cada vez do valor transmitido.

Com enum, as verificações não são necessárias, pois o cliente pode transmitir apenas um valor de enum em um parâmetro enum.

Por exemplo, aqui dois valores definidos em uma classe enum (tão constante fora da caixa):

public enum MyEnum {

    ONE_CONSTANT("value"), ANOTHER_CONSTANT(" another value");

    private String value;

    MyEnum(String value) {
       this.value = value;
    }
         ...
}

Aqui, um método que espera ter um desses valores de enumeração como parâmetro:

public void process(MyEnum myEnum){
    ...    
}

Você pode invocá-lo desta maneira:

process(MyEnum.ONE_CONSTANT);

ou

process(MyEnum.ANOTHER_CONSTANT);

Mas a compilação nunca permitirá que você a invoque desta maneira:

process("a not defined constant value");

Onde devemos declarar as constantes?

Se seu aplicativo contiver uma única classe existente que possua uma coesão funcional específica e forte com os valores constantes, o 1) e o 2) parecerão mais intuitivos.
Geralmente, facilita o uso das constantes se elas forem declaradas na classe principal que as manipula ou que tiverem um nome muito natural para adivinhar que a encontraremos lá dentro.

Por exemplo, na biblioteca JDK, os valores exponenciais e constantes pi são declarados em uma classe que declara não apenas declarações constantes ( java.lang.Math).

   public final class Math {
          ...
       public static final double E = 2.7182818284590452354;
       public static final double PI = 3.14159265358979323846;
         ...
   }

Os clientes que usam funções matemáticas dependem frequentemente da Mathclasse. Portanto, eles podem encontrar constantes com bastante facilidade e também podem se lembrar de onde Ee PIsão definidos de uma maneira muito natural.

Se seu aplicativo não contiver uma classe existente que tenha uma coesão funcional muito específica e forte com os valores constantes, as formas 1 e 2) parecerão mais intuitivas.
Geralmente, não facilita o uso das constantes se elas são declaradas em uma classe que as manipula, enquanto também temos 3 ou 4 outras classes que as manipulam tanto quanto e nenhuma dessas classes parece ser mais natural do que outras. hospedar valores constantes.
Aqui, definir uma classe personalizada para manter apenas valores constantes faz sentido.
Por exemplo, na biblioteca JDK, o java.util.concurrent.TimeUnitenum não é declarado em uma classe específica, pois não existe realmente uma e apenas uma classe específica do JDK que aparece como a mais intuitiva para mantê-la:

public enum TimeUnit {
    NANOSECONDS {
      .....
    },
    MICROSECONDS {
      .....
    },
    MILLISECONDS {
      .....
    },
    SECONDS {
      .....
    },
      .....
}      

Muitas classes declarou em java.util.concurrentusá-los: BlockingQueue, ArrayBlockingQueue<E>, CompletableFuture, ExecutorService, ... e realmente nenhum deles parece mais adequado para segurar o enum.


1

Uma constante, de qualquer tipo, pode ser declarada criando uma propriedade imutável que dentro de uma classe (que é uma variável de membro com o finalmodificador). Normalmente, os modificadores statice publictambém são fornecidos.

public class OfficePrinter {
    public static final String STATE = "Ready";  
}

Existem inúmeras aplicações em que o valor de uma constante indica uma seleção de uma n-tupla (por exemplo, enumeração ) de opções. Em nosso exemplo, podemos escolher definir um tipo enumerado que restringirá os possíveis valores atribuídos (ou seja , segurança de tipo aprimorada ):

public class OfficePrinter {
    public enum PrinterState { Ready, PCLoadLetter, OutOfToner, Offline };
    public static final PrinterState STATE = PrinterState.Ready;
}

1

Uma única classe de constantes genéricas é uma má ideia. As constantes devem ser agrupadas com a classe com a qual estão mais logicamente relacionadas.

Em vez de usar variáveis ​​de qualquer tipo (especialmente enumerações), sugiro que você use métodos. Crie um método com o mesmo nome que a variável e faça com que ele retorne o valor que você atribuiu à variável. Agora exclua a variável e substitua todas as referências a ela por chamadas para o método que você acabou de criar. Se você acha que a constante é genérica o suficiente para não precisar criar uma instância da classe apenas para usá-la, faça do método constant um método de classe.


1

FWIW, um valor de tempo limite em segundos provavelmente deve ser uma configuração (lida em um arquivo de propriedades ou por injeção como no Spring) e não uma constante.


1

Qual é a diferença

1

public interface MyGlobalConstants {
    public static final int TIMEOUT_IN_SECS = 25;
}

2)

public class MyGlobalConstants {
    private MyGlobalConstants () {} // Prevents instantiation
    public static final int TIMEOUT_IN_SECS = 25;
}

e usando MyGlobalConstants.TIMEOUT_IN_SECSsempre que precisarmos dessa constante. Eu acho que ambos são iguais.


11
Parece ser essencialmente um comentário em resposta à resposta que bincob deu. Eu acho que eles se comportam de maneira muito semelhante, mas o argumento de Bincob era que eles não definiam de forma alguma uma interface. E a sugestão era adicionar constantes às classes reais, não criar uma classe de esqueleto MyGlobalConstants. (Embora isso ocasionalmente faça sentido; use uma "classe estática" tendo constantes estáticas e um construtor privado para evitar instanciação; consulte java.lang.math.) Considere usar enum.
Jon Coombs

Também colocar "final" na declaração de classe impedirá a subclassificação. (Em C # você poderia fazer "estático", que significa "final abstrato", por isso não há necessidade de construtor privado explícito.)
Jon Coombs

Sim, @ JonCoombs, mas "final" não impede sua instanciação direta. E o Java não permite que o final e o resumo apareçam juntos para as classes, daí o construtor privado que aparece infinitamente para impedir instanciação e subclasse. Não tenho idéia de por que o "resumo final" não é permitido, a não ser que, à primeira vista, pareça contraditório na forma como se lê: "você não pode subclassificar, mas essa classe deve ser subclassificada".

0

Eu não chamaria a classe da mesma (além de maiúsculas e minúsculas) da constante ... Eu teria no mínimo uma classe de "Configurações", "Valores" ou "Constantes", onde todas as constantes viveriam. Se eu tiver um grande número deles, os agruparia em classes constantes lógicas (UserSettings, AppSettings, etc.)


Ter uma aula chamada Constantes era o que eu planejava fazer, esse foi apenas um pequeno exemplo que encontrei.
mk.

0

Para dar um passo adiante, você pode colocar constantes usadas globalmente em uma interface para que elas possam ser usadas em todo o sistema. Por exemplo

public interface MyGlobalConstants {
    public static final int TIMEOUT_IN_SECS = 25;
}

Mas não o implemente. Basta consultá-los diretamente no código através do nome completo da classe.


O ponto sobre declará-los em uma interface (e não implementá-la) é que você pode perder a "final estática pública".
Tom Hawtin - defina

9
As interfaces são para definir um contrato comportamental, não um mecanismo de conveniência para manter constantes.
John Topley

@ JohnTopley Sim, mas funciona. ;)
trusktr

0

Para constantes, o Enum é uma escolha melhor IMHO. Aqui está um exemplo

classe pública myClass {

public enum myEnum {
    Option1("String1", 2), 
    Option2("String2", 2) 
    ;
    String str;
            int i;

            myEnum(String str1, int i1) { this.str = str1 ; this.i1 = i }


}

0

Uma das maneiras que faço é criar uma classe 'Global' com os valores constantes e fazer uma importação estática nas classes que precisam acessar a constante.


0

static finalé minha preferência, eu só usaria um enumse o item fosse realmente enumerável.


0

Eu uso static finalpara declarar constantes e ir com a notação de nomeação ALL_CAPS. Eu já vi algumas instâncias da vida real em que todas as constantes são agrupadas em uma interface. Algumas postagens justificaram isso como uma má prática, principalmente porque não é para isso que serve uma interface. Uma interface deve impor um contrato e não deve ser um local para colocar constantes não relacionadas. Reuni-lo em uma classe que não pode ser instanciada (por meio de um construtor privado) também é bom se a semântica constante não pertencer a uma classe específica ( es). Eu sempre coloco uma constante na classe com a qual ela está mais relacionada, porque isso faz sentido e também é fácil de manter.

As enums são uma boa opção para representar uma faixa de valores, mas se você estiver armazenando constantes independentes com ênfase no valor absoluto (por exemplo, TIMEOUT = 100 ms), basta seguir a static finalabordagem.


0

Concordo com o que a maioria está dizendo, é melhor usar enumerações ao lidar com uma coleção de constantes. No entanto, se você estiver programando no Android, há uma solução melhor: Anotação IntDef .

@Retention(SOURCE)
@IntDef({NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST,NAVIGATION_MODE_TABS})
public @interface NavigationMode {}
public static final int NAVIGATION_MODE_STANDARD = 0;
public static final int NAVIGATION_MODE_LIST = 1;
public static final int NAVIGATION_MODE_TABS = 2;
...
public abstract void setNavigationMode(@NavigationMode int mode);
@NavigationMode
public abstract int getNavigationMode();

A anotação IntDef é superior às enumerações de uma maneira simples, ocupa muito menos espaço, pois é simplesmente um marcador de tempo de compilação. Não é uma classe, nem possui a propriedade de conversão automática de cadeias.


Embora eu concorde com a melhor prática de não usar a interface apenas em Java e evitar enum no Android, essa substituição no Android só funciona quando você está usando um pequeno número de campos. É uma economia significativa de memória, mas pode causar inchaço à medida que você é interface por campo em uma enumeração mista. Por exemplo, se eu tenho uma enumeração mista que define o que um objeto leva em seu construtor, não posso salvar nada com essa abordagem e volto a constantes seguras que não são do tipo, porque no Android você não deseja muitas classes / interfaces.
Droid Teahouse

0

É um péssimo hábito e uma prática terrivelmente irritante citar Joshua Bloch sem entender o fundamentalismo básico do ponto zero.

Eu não li nada Joshua Bloch, então também

  • ele é um péssimo programador
  • ou as pessoas até agora que acho citá-lo (Joshua é o nome de um garoto que presumo) estão simplesmente usando seu material como scripts religiosos para justificar suas indulgências religiosas por software.

Como no fundamentalismo bíblico, todas as leis bíblicas podem ser resumidas por

  • Ame a identidade fundamental com todo seu coração e toda sua mente
  • Ame seu próximo como a si mesmo

e, de modo semelhante, o fundamentalismo da engenharia de software pode ser resumido em

  • dedique-se aos fundamentos do ponto zero com todo o seu poder e mente de programação
  • e dedique-se à excelência de seus colegas programadores como faria por si mesmo.

Além disso, entre os círculos fundamentalistas bíblicos, um corolário forte e razoável é traçado

  • Primeiro AME a si mesmo. Porque se você não se ama muito, o conceito "ame o próximo como a si mesmo" não tem muito peso, pois "o quanto você se ama" é a linha de dados acima da qual você amaria os outros.

Da mesma forma, se você não se respeita como programador e apenas aceita os pronunciamentos e profecias de algum guru-nath da programação SEM questionar os fundamentos, suas citações e confiança em Joshua Bloch (e similares) não fazem sentido. E, portanto, você realmente não respeitaria seus colegas programadores.

As leis fundamentais da programação de software

  • preguiça é a virtude de um bom programador
  • você deve tornar sua vida de programação o mais fácil, o mais preguiçoso e, portanto, o mais eficaz possível
  • você deve tornar as conseqüências e as entranhas da sua programação o mais fácil, o mais preguiçoso e, portanto, o mais eficaz possível para os seus programadores vizinhos que trabalham com você e capturam as entranhas da programação.

As constantes do padrão de interface são um mau hábito ???

Sob quais leis da programação fundamentalmente eficaz e responsável se enquadra esse edito religioso?

Basta ler o artigo da wikipedia sobre constantes de padrão de interface ( https://en.wikipedia.org/wiki/Constant_interface ), e as desculpas tolas que ele declara em relação às constantes de padrão de interface.

  • Whatif-No IDE? Quem diabos, como programador de software, não usaria um IDE? Muitos de nós somos programadores que preferem não ter que provar ter um sobrevivencialismo escapular masculino, evitando o uso de um IDE.

    • Também - espere um segundo defensor da programação micro-funcional como um meio de não precisar de um IDE. Espere até você ler minha explicação sobre a normalização do modelo de dados.
  • Polui o espaço para nome com variáveis ​​não usadas no escopo atual? Poderia ser proponente dessa opinião

    • não estão cientes da necessidade de normalização do modelo de dados e
  • O uso de interfaces para impor constantes é um abuso de interfaces. Os proponentes de tais têm um mau hábito de

    • não vendo que "constantes" devem ser tratadas como contrato. E as interfaces são usadas para impor ou projetar a conformidade com um contrato.
  • É difícil, senão impossível, converter interfaces em classes implementadas no futuro. Hah .... hmmm ... ???

    • Por que você gostaria de se envolver em um padrão de programação como o seu modo de vida persistente? IOW, por que dedicar-se a um hábito de programação tão AMBIVALENTE e ruim?

Quaisquer que sejam as desculpas, NÃO EXISTEM VÁLIDAS VÁLIDAS no que diz respeito à engenharia de software FUNDAMENTALMENTE EFICAZ para deslegitimar ou geralmente desencorajar o uso de constantes de interface.

Não importa quais foram as intenções e estados mentais originais dos pais fundadores que criaram a Constituição dos Estados Unidos. Poderíamos debater as intenções originais dos pais fundadores, mas tudo o que me interessa são as declarações escritas da Constituição dos EUA. E é responsabilidade de todo cidadão dos EUA explorar o fundamentalismo literário escrito, não os fundamentos não escritos da Constituição dos EUA.

Da mesma forma, não me importo com o que as intenções "originais" dos fundadores da plataforma Java e da linguagem de programação tinham para a interface. O que importa são os recursos efetivos que a especificação Java fornece e pretendo explorar esses recursos ao máximo para me ajudar a cumprir as leis fundamentais da programação de software responsável. Não me importo se sou percebido como "violando a intenção de interfaces". Não me importo com o que Gosling ou alguém Bloch diz sobre a "maneira correta de usar Java", a menos que o que eles digam não viole minha necessidade de cumprir com EFICAZ os fundamentos.

O fundamental é a normalização do modelo de dados

Não importa como seu modelo de dados é hospedado ou transmitido. Se você usa interfaces ou enumerações ou qualquer que seja, relacional ou não-SQL, se não entender a necessidade e o processo de normalização do modelo de dados.

Primeiro, devemos definir e normalizar o modelo de dados de um conjunto de processos. E quando temos um modelo de dados coerente, SOMENTE então podemos usar o fluxo do processo de seus componentes para definir o comportamento funcional e o processo bloqueia um campo ou domínio de aplicativos. E somente então podemos definir a API de cada processo funcional.

Mesmo as facetas da normalização de dados, conforme proposto pelo EF Codd, agora são severamente desafiadas e severamente desafiadas. por exemplo, sua declaração sobre a 1NF foi criticada por ser ambígua, desalinhada e simplificada demais, assim como o restante de suas declarações, especialmente no advento dos modernos serviços de dados, re-tecnologia e transmissão. Na IMO, as instruções EF Codd devem ser completamente descartadas e um novo conjunto de instruções matematicamente plausíveis deve ser projetado.

Uma falha evidente dos EF Codd e a causa de seu desalinhamento da compreensão humana eficaz é sua crença de que dados multidimensionais e de dimensões mutáveis ​​humanamente perceptíveis podem ser eficientemente percebidos através de um conjunto de mapeamentos bidimensionais fragmentados.

Os fundamentos da normalização de dados

O que a EF Codd não conseguiu expressar.

Dentro de cada modelo de dados coerente, estas são a ordem graduada sequencial de coerência do modelo de dados a ser atingida.

  1. A unidade e identidade das instâncias de dados.
    • projetar a granularidade de cada componente de dados, em que sua granularidade esteja em um nível em que cada instância de um componente possa ser identificada e recuperada exclusivamente.
    • ausência de alias de instância. isto é, não existem meios pelos quais uma identificação produza mais de uma instância de um componente.
  2. Ausência de ocorrência de diafonia. Não existe a necessidade de usar uma ou mais outras instâncias de um componente para contribuir para identificar uma instância de um componente.
  3. A unidade e identidade dos componentes / dimensões dos dados.
    • Presença de desalinhamento de componente. Deve haver uma definição na qual um componente / dimensão possa ser identificado exclusivamente. Qual é a definição principal de um componente;
    • onde a definição principal não resultará na exposição de subdimensões ou componentes de membros que não fazem parte de um componente pretendido;
  4. Meios exclusivos de distribuição de componentes. Deve existir uma, e apenas uma, definição de dessalinização de componente para um componente.
  5. Existe uma, e apenas uma, interface ou contrato de definição para identificar um componente pai em um relacionamento hierárquico de componentes.
  6. Ausência de diafonia de componente. Não existe a necessidade de usar um membro de outro componente para contribuir para a identificação definitiva de um componente.
    • Nesse relacionamento pai-filho, a definição de identificação de um pai não deve depender de parte do conjunto de componentes de membros de um filho. Um componente membro da identidade de um pai deve ser a identidade completa do filho, sem recorrer à referência a um ou a todos os filhos de um filho.
  7. Prevenir aparências bi-modais ou multimodais de um modelo de dados.
    • Quando existem duas definições candidatas de um componente, é um sinal óbvio que existem dois modelos de dados diferentes sendo misturados como um. Isso significa que há incoerência no nível do modelo de dados ou no campo.
    • Um campo de aplicativos deve usar um e apenas um modelo de dados, de forma coerente.
  8. Detecte e identifique a mutação de componentes. A menos que você tenha realizado uma análise estatística de componentes de grandes dados, provavelmente você não vê ou vê a necessidade de tratar a mutação de componentes.
    • Um modelo de dados pode ter seus componentes alternados ciclicamente ou gradualmente.
    • O modo pode ser rotação de membro ou rotação de transposição.
    • A mutação de rotação de membros pode ser uma troca distinta de componentes filhos entre componentes. Ou onde componentes completamente novos precisariam ser definidos.
    • A mutação transicional se manifestaria como um membro dimensional se transformando em um atributo, vice-versa.
    • Cada ciclo de mutação deve ser identificado como um modal de dados distinto.
  9. Versionize cada mutação. De modo que você pode obter uma versão anterior do modelo de dados, quando talvez surgir a necessidade de tratar uma mutação de 8 anos do modelo de dados.

Em um campo ou grade de aplicativos de componentes entre serviços, deve haver um e apenas um modelo de dados coerente ou existe um meio para um modelo / versão de dados se identificar.

Ainda estamos perguntando se poderíamos usar constantes de interface? Realmente ?

Há questões de normalização de dados em jogo mais conseqüentes do que essa questão mundana. Se você não resolver esses problemas, a confusão que você acha que as constantes da interface causam é comparativamente nada. Zilch.

A partir da normalização do modelo de dados, você determina os componentes como variáveis, como propriedades, como constantes da interface do contrato.

Em seguida, você determina o que entra em injeção de valor, espaço reservado na configuração da propriedade, interfaces, cadeias finais, etc.

Se você precisar usar a desculpa de precisar localizar um componente mais fácil de determinar em relação às constantes da interface, isso significa que você tem o mau hábito de não praticar a normalização do modelo de dados.

Talvez você queira compilar o modelo de dados em um release do vcs. Que você pode obter uma versão distintamente identificável de um modelo de dados.

Os valores definidos nas interfaces são completamente garantidos como não mutáveis. E compartilhável. Por que carregar um conjunto de seqüências finais em sua classe a partir de outra classe quando tudo que você precisa é esse conjunto de constantes?

Então, por que não publicar um contrato de modelo de dados? Quero dizer, se você pode gerenciar e normalizá-lo de forma coerente, por que não? ...

public interface CustomerService {
  public interface Label{
    char AssignmentCharacter = ':';
    public interface Address{
      String Street = "Street";
      String Unit= "Unit/Suite";
      String Municipal = "City";
      String County = "County";
      String Provincial = "State";
      String PostalCode = "Zip"
    }

    public interface Person {
      public interface NameParts{
        String Given = "First/Given name"
        String Auxiliary = "Middle initial"
        String Family = "Last name"
      }
    }
  }
}

Agora posso referenciar os rótulos contratados dos meus aplicativos de uma maneira como

CustomerService.Label.Address.Street
CustomerService.Label.Person.NameParts.Family

Isso confunde o conteúdo do arquivo jar? Como programador Java, não me importo com a estrutura do jar.

Isso apresenta complexidade à troca de tempo de execução motivada por osgi? Osgi é um meio extremamente eficiente para permitir que os programadores continuem com seus maus hábitos. Existem alternativas melhores que osgi.

Ou por que não isso? Não há vazamento das constantes privadas no contrato publicado. Todas as constantes privadas devem ser agrupadas em uma interface privada chamada "Constantes", porque não quero procurar constantes e tenho preguiça de digitar repetidamente "private final String".

public class PurchaseRequest {
  private interface Constants{
    String INTERESTINGName = "Interesting Name";
    String OFFICIALLanguage = "Official Language"
    int MAXNames = 9;
  }
}

Talvez até isso:

public interface PurchaseOrderConstants {
  public interface Properties{
    default String InterestingName(){
       return something();
    }
    String OFFICIALLanguage = "Official Language"
    int MAXNames = 9;
  }
}

O único problema com as constantes da interface que vale a pena considerar é quando a interface é implementada.

Esta não é a "intenção original" das interfaces? Como se eu me importasse com a "intenção original" dos pais fundadores na elaboração da Constituição dos EUA, e não como a Suprema Corte interpretaria as cartas escritas da Constituição dos EUA ???

Afinal, moro na terra dos livres, da natureza e do lar dos bravos. Seja corajoso, livre, seja selvagem - use a interface. Se meus colegas programadores se recusarem a usar meios de programação eficientes e preguiçosos, sou obrigado pela regra de ouro a diminuir minha eficiência de programação para se alinhar à deles? Talvez eu deva, mas essa não é uma situação ideal.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.