Por que não há recurso constante em Java?

140

Eu estava tentando identificar o motivo por trás das constantes em Java. Aprendi que o Java nos permite declarar constantes usando a finalpalavra-chave.

Minha pergunta é por que o Java não introduziu um constrecurso Constant ( ). Como muitas pessoas dizem que veio do C ++, no C ++ temos a constpalavra-chave.

Por favor, compartilhe seus pensamentos.

gmhk
fonte
2
Não é uma constpalavra-chave, mas não há nenhum recurso subjacente. Corrigido seu título e tags de acordo.
Marquês de Lorne

Respostas:

142

Toda vez que eu passo da pesada codificação C ++ para Java, levo um tempo para me adaptar à falta de correção constante em Java. Esse uso constno C ++ é muito diferente do que apenas declarar variáveis ​​constantes, se você não sabia. Essencialmente, ele garante que um objeto seja imutável quando acessado por meio de um tipo especial de ponteiro chamado const-pointer. Quando em Java, em locais onde normalmente eu gostaria de retornar um const-pointer, retorno uma referência com um tipo de interface. contendo apenas métodos que não devem ter efeitos colaterais. Infelizmente, isso não é imposto pelo idioma.

A Wikipedia oferece as seguintes informações sobre o assunto:

Curiosamente, a especificação da linguagem Java considera const como uma palavra-chave reservada - ou seja, que não pode ser usada como identificador de variável -, mas não atribui nenhuma semântica a ela. Pensa-se que a reserva da palavra-chave ocorreu para permitir uma extensão da linguagem Java para incluir métodos const no estilo C ++ e ponteiro para o tipo const. O ticket de solicitação de aprimoramento no Java Community Process para implementar a correção const em Java foi fechado em 2005, o que implica que a correção const provavelmente nunca encontrará seu caminho na especificação oficial do Java.

Gunslinger47
fonte
10
Java finalé semelhante, no entanto.
Reinierpost
62
Não, não é. finalO método, por exemplo, funciona completamente diferente dos constmétodos C ++ .
Dom
7
@reinierpost A finalpalavra - chave em propriedades ou variáveis apenas garante que uma propriedade ou variável seja atribuída apenas uma vez . Ainda é possível alterar o estado desse objeto, por exemplo, chamando algum método com efeitos colaterais. finalÉ um pouco semelhante empilhar a alocação de C ++ em termos de referência a um objeto em vez de um ponteiro, mas é tudo. Isso é claro, além do que o dom0 já disse.
Tim
9
finalem Java parece funcionar como C ++ constpara tipos de valor, mas mais como um C ++ não-const T&para tipos de referência
Mark K Cowan
1
final é uma palavra-chave esquizofrênica. Embora impeça a reatribuição, também é usado para expor variáveis ​​a fechamentos. Talvez eu queira impedir a reatribuição, mas não expor essas variáveis, mas não há como fazê-lo. É um recurso de linguagem pouco pensado na minha opinião.
David Bradley
82

O que constsignifica
Primeiro, saiba que a semântica de uma palavra-chave "const" significa coisas diferentes para pessoas diferentes:

  • referência somente leitura - finalsemântica Java - a própria variável de referência não pode ser reatribuída para apontar para outra instância (local da memória), mas a própria instância é modificável
  • referência somente leitura - constponteiro C / semântica de referência - significa que esta referência não pode ser usada para modificar a instância (por exemplo, não pode atribuir a variáveis ​​de instância, não pode invocar métodos mutáveis) - afeta apenas a variável de referência, portanto, uma referência não-const apontando para mesma instância pode modificar a instância
  • objeto imutável - significa que a instância em si não pode ser modificada - se aplica à instância, portanto, qualquer referência que não seja const não seria permitida ou não poderia ser usada para modificar a instância
  • alguma combinação do acima ?
  • outros ?

Por que ou por que não?const
Segundo, se você realmente deseja explorar alguns dos argumentos "pro" vs "con", consulte a discussão sob este "bug" da solicitação de aprimoramento (RFE). Esse RFE solicita um recurso "referência somente leitura" - tipo "const". Aberto em 1999 e depois fechado / rejeitado pela Sun em 2005, o tópico "const" foi vigorosamente debatido:

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4211070

Embora existam muitos bons argumentos de ambos os lados, algumas das razões frequentemente citadas (mas não necessariamente convincentes ou claras) constincluem:

  • pode ter semântica confusa que pode ser mal utilizada e / ou abusada (consulte o que constsignifica acima)
  • pode duplicar a capacidade disponível de outra forma (por exemplo, projetar uma classe imutável, usando uma interface imutável)
  • pode ser uma subida de recurso, levando a uma necessidade de outras alterações semânticas, como suporte para passar objetos por valor

Antes que alguém tente me debater sobre se essas são boas ou más razões, observe que essas não são minhas razões . Eles são simplesmente a "essência" de algumas das razões pelas quais eu reclamei ao examinar a discussão da RFE. Eu não necessariamente concordo com eles - estou apenas tentando citar por que algumas pessoas (não eu) podem achar que uma constpalavra - chave pode não ser uma boa idéia. Pessoalmente, eu gostaria que mais semânticas "const" fossem introduzidas no idioma de maneira inequívoca.

Bert F
fonte
2
+1 apenas para a segunda parte da sua resposta. Muitas palavras-chave têm semântica não trivial. É volatiletão simples de entender? Ou final? Meh.
einpoklum
OTOH, Java foi projetado para usar o menor número possível de recursos não triviais. E não estou dizendo que eles alcançaram esse objetivo (ou que o Java não se afastou desse objetivo). Mas excluí-lo por esse motivo ainda pode ter tido mérito. O fato de haver outras coisas complicadas é mais um motivo para não apresentar mais (ou você acabaria com a linguagem D).
Maarten Bodewes
7

const em C ++ não significa que um valor é uma constante.

const em C ++ implica que o cliente de um contrato se comprometa a não alterar seu valor.

Se o valor de uma constexpressão muda, fica mais evidente se você estiver em um ambiente que suporta simultaneidade baseada em encadeamento.

Como o Java foi projetado desde o início para oferecer suporte à simultaneidade de encadeamentos e bloqueios, não causou confusão ao sobrecarregar o termo para ter a semântica existente final.

por exemplo:

#include <iostream>

int main ()
{
    volatile const int x = 42;

    std::cout << x << std::endl;

    *const_cast<int*>(&x) = 7;

    std::cout << x << std::endl;

    return 0;
}

saídas 42 e 7.

Embora xmarcado como const, como um alias não constante é criado, xnão é uma constante. Nem todo compilador exige volatileesse comportamento (embora seja permitido a cada compilador incorporar a constante)

Com sistemas mais complicados, você obtém alias const / non-const sem o uso de const_cast, portanto, adquirindo o hábito de pensar que const significa que algo não vai mudar se torna cada vez mais perigoso. constsignifica apenas que seu código não pode alterá-lo sem uma conversão, não que o valor seja constante.

Pete Kirkham
fonte
3
const int x = 42; - x é uma constante
2
@ Neil Se você tiver um objeto ou variável com o alias de ambos os ponteiros const e não-const, o valor do alias const pode ser alterado pelo alias não const. Portanto const, não significa que um valor seja constante. Isso significa que o cliente de um valor está restrito a não modificá-lo. No seu exemplo, não há alias; portanto, todos os usuários estão sob a mesma restrição. Este não é o caso em geral. constafeta os clientes, não o valor - ele diz que você não pode mudá-lo, não que isso não mude.
Pete Kirkham
1
Const-correção é sobre o que o programador deve fazer, não o que ele pode fazer . Acho que todos vocês entenderam esse ponto. Só queria acrescentar um par de centavos que possam ser de interesse para o leitor causal: Os padrões de design, como o immutable interfacee immutable objecté uma outra maneira (beatable com o elenco e reflexão) para const mímico em Java. Const "True" pode ser feito com SealedObject , mas isso destrói o caso de uso do nosso objeto.
Martin Andersson
6
Note-se que o resultado do seu programa é indefinido. const_cast não está lá para alterar variáveis ​​const, mas para passar variáveis ​​const para APIs que não estão corretas, mas também não modificam o valor. Eu acho que o hábito de pensar que algo const não vai mudar é bom, porque se eles mudarem, isso significa que seu programa contém hacks que podem quebrar a qualquer momento, dependendo do compilador usado.
Cygon
1
Modificar um valor nascido para constante é um comportamento indefinido. Seu disco já pode estar formatado.
Zhe Yang
5

Essa é uma pergunta um pouco antiga, mas pensei em contribuir com meus 2 centavos de qualquer maneira, já que esse tópico surgiu na conversa hoje.

Isso não responde exatamente por que não há const? mas como tornar suas aulas imutáveis. (Infelizmente ainda não tenho reputação suficiente para postar como comentário na resposta aceita)

A maneira de garantir a imutabilidade de um objeto é projetar suas classes com mais cuidado para serem imutáveis. Isso requer um pouco mais de cuidado do que uma classe mutável.

Isso remonta ao item efetivo Java de Josh Bloch 15 - Minimizar a mutabilidade . Se você ainda não leu o livro, pegue uma cópia e leia-a algumas vezes, garanto que ele exibirá seu "jogo java" figurativo .

No item 15, Bloch sugere que você limite a mutabilidade das classes para garantir o estado do objeto.

Para citar o livro diretamente:

Uma classe imutável é simplesmente uma classe cujas instâncias não podem ser modificadas. Todas as informações contidas em cada instância são fornecidas quando criadas e são fixadas durante a vida útil do objeto. As bibliotecas da plataforma Java contêm muitas classes imutáveis, incluindo String, as classes primitivas in a box e BigInteger e BigDecimal. Há muitas boas razões para isso: Classes imutáveis ​​são mais fáceis de projetar, implementar e usar do que classes mutáveis. Eles são menos propensos a erros e são mais seguros.

Bloch descreve como tornar suas aulas imutáveis, seguindo 5 regras simples:

  1. Não forneça métodos que modifiquem o estado do objeto (por exemplo, setters, também conhecidos como mutadores )
  2. Verifique se a classe não pode ser estendida (isso significa declarar a própria classe como final).
  3. Faça todos os campos final.
  4. Faça todos os campos private.
  5. Garanta acesso exclusivo a qualquer componente mutável. (fazendo cópias defensivas dos objetos)

Para mais detalhes, eu recomendo pegar uma cópia do livro.

grego
fonte
3
O const em C ++ é MUITO mais flexível que a imutabilidade em grande escala. Em certo sentido, 'const' pode ser visto como 'imutável dentro deste contexto particular'. Exemplo: tenho uma classe que não é imutável, MAS quero garantir que ela não seja modificada por meio de determinadas APIs públicas. Criar uma interface (e devolvê-la para essa API pública), conforme sugerido por Gunslinger47, alcança a mesma coisa em Java, mas, rapaz - é feio (e por isso - é ignorado pela maioria dos desenvolvedores de Java, levando a uma bagunça desnecessária). .
Não-bugs Hare
3

A semântica de C ++ de consté muito diferente de Java final. Se os designers tivessem usado constisso, seria desnecessariamente confuso.

O fato de constser uma palavra reservada sugere que os designers tinham idéias para implementar const, mas desde então decidiram contra; veja este bug fechado . Os motivos declarados incluem que adicionar suporte ao estilo C ++ constcausaria problemas de compatibilidade.

Stephen C
fonte
-1

Existe uma maneira de criar variáveis ​​"const" em Java, mas apenas para classes específicas. Basta definir uma classe com propriedades finais e subclassificá-la. Em seguida, use a classe base onde você deseja usar "const". Da mesma forma, se você precisar usar os métodos "const", adicione-os à classe base. O compilador não permitirá que você modifique o que considera os métodos finais da classe base, mas lerá e chamará métodos na subclasse.

user1122069
fonte
Você pode dar um exemplo disso, por favor?
NO_NAME 31/01
classe MYString implementa GetString {private final String aaaa; public String getString (); } classe MutableString implementa GetString {private String aaaa2; public String getString (); public String setString ()}
user1122069 3/17/17
-2

Haveria duas maneiras de definir constantes - conste static final, com a mesma semântica exata. Além disso, static finaldescreve o comportamento melhor do queconst

Bozho
fonte
@Bozho, você disse um comportamento melhor que o Const, de que maneira é? você pode compartilhar qualquer exemplo
gmhk 30/04/10
bem, a variável é static(não pertence a instância específica) e final- não pode ser alterada.
Bozho
-2

Você pode usar estática final para criar algo que funcione de maneira semelhante à Const. Eu usei isso no passado.

protected static final int cOTHER = 0;
protected static final int cRPM = 1;
protected static final int cSPEED = 2;
protected static final int cTPS = 3;
protected int DataItemEnum = 0;

public static final int INVALID_PIN = -1;
public static final int LED_PIN = 0;
hamish
fonte
Voto negativo para otimização baseada em boatos, porque ouvi um boato de que essa é uma estratégia ineficaz.
afarley
Tirei o boato da resposta. você ainda pode usar o int final estático para criar código no estilo const.
hamish
Ok, eu removi meu voto negativo. Talvez alguns dos outros downvotes está prestes a instrução switch (o que isso tem a ver com o resto do seu exemplo?)
afarley
na instrução switch, usei o cRPM como se fosse uma const. muito certo, considerando o acima. então sim, eu removi o interruptor.
hamish