Pourquoi n'y a-t-il pas de fonctionnalité constante dans Java?

140

J'essayais d'identifier la raison derrière les constantes en Java, j'ai appris que Java nous permet de déclarer des constantes en utilisant un finalmot-clé.

Ma question est pourquoi Java n'a-t-il pas introduit de fonctionnalité Constant ( const). Comme beaucoup de gens disent qu'il vient de C ++, en C ++, nous avons un constmot - clé.

Veuillez partager vos pensées.

gmhk
la source
2
Il existe un constmot - clé, mais aucune fonctionnalité sous-jacente. Corrigé votre titre et vos balises en conséquence.
Marquis of Lorne

Réponses:

142

Chaque fois que je passe du codage C ++ lourd à Java, il me faut un peu de temps pour m'adapter au manque de const-correctness en Java. Cette utilisation de constC ++ est très différente de la simple déclaration de variables constantes, si vous ne le saviez pas. Essentiellement, cela garantit qu'un objet est immuable lorsqu'il est accédé via un type spécial de pointeur appelé const-pointer Quand en Java, dans les endroits où je voudrais normalement renvoyer un const-pointer, je renvoie à la place une référence avec un type d'interface contenant uniquement des méthodes qui ne devraient pas avoir d'effets secondaires. Malheureusement, cela n'est pas appliqué par la langue.

Wikipedia propose les informations suivantes sur le sujet:

Il est intéressant de noter que la spécification du langage Java considère const comme un mot-clé réservé - c'est-à-dire qui ne peut pas être utilisé comme identificateur de variable - mais ne lui attribue aucune sémantique. On pense que la réservation du mot-clé s'est produite pour permettre à une extension du langage Java d'inclure des méthodes const de style C ++ et un pointeur vers le type const. Le ticket de demande d'amélioration dans le Java Community Process pour l'implémentation de la correction de const en Java a été fermé en 2005, ce qui implique que la correction de const ne trouvera probablement jamais son chemin dans la spécification officielle de Java.

Pistolero47
la source
10
finalCependant, celui de Java est similaire.
reinierpost le
62
Non, ça ne l'est pas. finalpar exemple, fonctionnent complètement différemment des constméthodes C ++ .
dom0
7
@reinierpost Le finalmot-clé sur les propriétés ou les variables garantit simplement qu'une propriété ou une variable n'est affectée qu'une seule fois . On pourrait encore modifier l'état de cet objet, par exemple en appelant une méthode avec des effets secondaires. finalest quelque peu similaire à l'allocation de pile de C ++ en termes de référence à un objet plutôt qu'à un pointeur, mais c'est tout. Ceci s'ajoute bien entendu à ce que dom0 a déjà dit.
Tim
9
finalen Java semble fonctionner comme C ++ constpour les types valeur, mais plus comme un C ++ non-const T&pour les types référence
Mark K Cowan
1
final est un mot-clé schizophrène. Bien qu'il empêche la réaffectation, il est également utilisé pour exposer des variables à des fermetures. Je pourrais vouloir empêcher la réaffectation mais ne pas exposer ces variables, mais il n'y a aucun moyen de le faire. C'est une fonctionnalité de langage plutôt mal pensée à mon avis.
David Bradley
82

Qu'est-ce que cela constsignifie
Premièrement, sachez que la sémantique d'un mot-clé "const" signifie différentes choses pour différentes personnes:

  • référence en lecture seule - finalsémantique Java - la variable de référence elle-même ne peut pas être réaffectée pour pointer vers une autre instance (emplacement mémoire), mais l'instance elle-même est modifiable
  • référence en lecture seule - constpointeur C / sémantique de référence - signifie que cette référence ne peut pas être utilisée pour modifier l'instance (par exemple, ne peut pas affecter à des variables d'instance, ne peut pas invoquer de méthodes mutables) - affecte uniquement la variable de référence, donc une référence non-const pointant vers le la même instance pourrait modifier l'instance
  • objet immuable - signifie que l'instance elle-même ne peut pas être modifiée - s'applique à l'instance, donc toute référence non-const ne serait pas autorisée ou ne pourrait pas être utilisée pour modifier l'instance
  • une combinaison de ce qui précède ?
  • d'autres ?

Pourquoi ou pourquoi pasconst
Deuxièmement, si vous voulez vraiment approfondir certains des arguments "pro" vs "con", consultez la discussion sous ce "bug" de demande d'amélioration (RFE). Cette RFE demande une fonctionnalité de type "référence lisible uniquement" "const". Ouvert en 1999 puis fermé / rejeté par Sun en 2005, le sujet «const» a été vigoureusement débattu:

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

Bien qu'il y ait beaucoup de bons arguments des deux côtés, certaines des raisons souvent citées (mais pas nécessairement convaincantes ou claires) contre constincluent:

  • peut avoir une sémantique confuse qui peut être mal utilisée et / ou abusée (voir ce que constsignifie ci - dessus)
  • peut dupliquer des capacités autrement disponibles (par exemple, concevoir une classe immuable, utiliser une interface immuable)
  • peut être un fluage des caractéristiques, conduisant à la nécessité d'autres changements sémantiques tels que la prise en charge du passage d'objets par valeur

Avant que quiconque essaie de me demander si ce sont de bonnes ou de mauvaises raisons, notez que ce ne sont pas mes raisons . Ils ne sont que "l'essentiel" de certaines des raisons que j'ai glanées en parcourant la discussion RFE. Je ne suis pas nécessairement d'accord avec eux moi-même - j'essaie simplement d'expliquer pourquoi certaines personnes (pas moi) peuvent penser qu'un constmot-clé n'est peut-être pas une bonne idée. Personnellement, j'aimerais que plus de sémantique «const» soit introduite dans le langage de manière non ambiguë.

Bert F
la source
2
+1 juste pour la deuxième partie de votre réponse. De nombreux mots-clés ont une sémantique non triviale. Est-ce volatilesi simple à comprendre? Ou final? Meh.
einpoklum
OTOH, Java a été conçu pour utiliser le moins possible de ces fonctionnalités non triviales. Et je ne dis pas qu'ils ont atteint cet objectif (ou que Java ne s'est pas éloigné de cet objectif). Mais l'exclure pour cette raison pouvait encore avoir du mérite. Qu'il y ait d'autres choses compliquées est une raison de plus pour ne pas en introduire plus (ou vous vous retrouveriez avec le langage D).
Maarten Bodewes le
7

const en C ++ ne signifie pas qu'une valeur est une constante.

const en C ++ implique que le client d'un contrat s'engage à ne pas modifier sa valeur.

La question de savoir si la valeur d'une constexpression change devient plus évidente si vous êtes dans un environnement qui prend en charge la concurrence basée sur les threads.

Comme Java a été conçu dès le départ pour prendre en charge les threads et verrouiller la concurrence, il n'a pas ajouté à la confusion en surchargeant le terme pour avoir la sémantique qui finala.

par exemple:

#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;
}

sorties 42 puis 7.

Bien que xmarqué comme const, lorsqu'un alias non-const est créé, ce xn'est pas une constante. Tous les compilateurs ne nécessitent pas volatilece comportement (bien que chaque compilateur soit autorisé à insérer la constante)

Avec des systèmes plus compliqués, vous obtenez des alias const / non-const sans utiliser de const_cast, donc prendre l'habitude de penser que const signifie que quelque chose ne changera pas devient de plus en plus dangereux. constsignifie simplement que votre code ne peut pas le changer sans une conversion, pas que la valeur est constante.

Pete Kirkham
la source
3
const int x = 42; - x est une constante
2
@Neil Si vous avez un objet ou une variable aliasé à la fois par des pointeurs const et non const, la valeur de l'alias const peut être modifiée par l'alias non const. Par conséquent, constcela ne signifie pas qu'une valeur est constante. Cela signifie que le client d'une valeur est contraint de ne pas la muter. Dans votre exemple, il n'y a pas d'alias, donc tous les utilisateurs sont soumis à la même contrainte. Ce n'est pas le cas en général. constaffecte les clients, pas la valeur - cela dit que vous ne pouvez pas le changer, pas que cela ne changera pas.
Pete Kirkham le
1
L'exactitude des constats concerne ce que le programmeur doit faire, pas ce qu'il peut faire . Je pense que vous semblez tous avoir compris ce point. Je voulais juste ajouter quelques centimes qui pourraient intéresser le lecteur causal: concevoir des modèles comme le immutable interfaceet immutable objectest une autre façon (battable avec la distribution et la réflexion) d'imiter const en Java. "True" const peut être fait avec SealedObject , hélas cela détruit le cas d'utilisation de notre objet.
Martin Andersson
6
Il faut noter que le résultat de votre programme n'est pas défini. const_cast n'est pas là pour changer les variables const, il est là pour passer des variables const aux API qui ne sont pas const correctes, mais aussi ne modifient pas la valeur. Je pense que l'habitude de penser que quelque chose de constant ne changera pas est une bonne chose, car si elles changent, cela signifie que votre programme contient des hacks qui peuvent se casser à tout moment en fonction du compilateur utilisé.
Cygon
1
La modification d'une valeur née à constante est un comportement indéfini. Votre disque est peut-être déjà formaté.
Zhe Yang
5

C'est un peu une vieille question, mais je pensais que je contribuerais quand même mes 2 cents puisque ce fil est venu dans la conversation aujourd'hui.

Cela ne répond pas exactement pourquoi n'y a-t-il pas de const? mais comment rendre vos cours immuables. (Malheureusement, je n'ai pas encore assez de réputation pour publier un commentaire sur la réponse acceptée)

La manière de garantir l'immuabilité sur un objet est de concevoir vos classes plus soigneusement pour qu'elles soient immuables. Cela nécessite un peu plus de soin qu'une classe mutable.

Cela remonte à l' article 15 Java efficace de Josh Bloch - Minimiser la mutabilité . Si vous n'avez pas lu le livre, prenez-en un exemplaire et relisez-le plusieurs fois, je vous garantis qu'il fera monter votre "jeu java" figuratif .

Au point 15, Bloch suggère de limiter la mutabilité des classes pour garantir l'état de l'objet.

Pour citer directement le livre:

Une classe immuable est simplement une classe dont les instances ne peuvent pas être modifiées. Toutes les informations contenues dans chaque instance sont fournies lors de sa création et sont fixées pour la durée de vie de l'objet. Les bibliothèques de la plate-forme Java contiennent de nombreuses classes immuables, notamment String, les classes primitives encadrées et BigInteger et BigDecimal. Il existe de nombreuses bonnes raisons à cela: les classes immuables sont plus faciles à concevoir, à implémenter et à utiliser que les classes mutables. Ils sont moins sujets aux erreurs et sont plus sûrs.

Bloch décrit ensuite comment rendre vos classes immuables, en suivant 5 règles simples:

  1. Ne fournissez aucune méthode qui modifie l'état de l'objet (c'est-à-dire les setters, aka mutators )
  2. Assurez-vous que la classe ne peut pas être étendue (cela signifie déclarer la classe elle-même comme final).
  3. Faites tous les champs final.
  4. Faites tous les champs private.
  5. Garantissez un accès exclusif à tous les composants mutables. (en faisant des copies défensives des objets)

Pour plus de détails, je recommande vivement de prendre un exemplaire du livre.

Grego
la source
3
const en C ++ est BEAUCOUP plus flexible que l'immuabilité à grande échelle. Dans un sens, «const» peut être considéré comme «immuable dans ce contexte particulier». Exemple: j'ai une classe qui n'est pas immuable, MAIS je veux m'assurer qu'elle n'est pas modifiée via certaines API publiques. Créer une interface (et la renvoyer pour cette API publique) comme suggéré par Gunslinger47 permet d'obtenir la même chose en Java, mais garçon - c'est moche (et donc - il est ignoré par la plupart des développeurs Java, ce qui entraîne un désordre inutile important). .
No-Bugs Hare
3

La sémantique C ++ de constest très différente de Java final. Si les concepteurs l'avaient utilisé, constcela aurait été inutilement déroutant.

Le fait que ce constsoit un mot réservé suggère que les concepteurs avaient des idées pour la mise en œuvre const, mais ils ont depuis décidé de ne pas le faire; voir ce bug fermé . Les raisons invoquées incluent que l'ajout de la prise en charge du style C ++ constentraînerait des problèmes de compatibilité.

Stephen C
la source
-1

Il existe un moyen de créer des variables "const" en Java, mais uniquement pour des classes spécifiques. Définissez simplement une classe avec les propriétés finales et sous-classez-la. Ensuite, utilisez la classe de base où vous voudriez utiliser "const". De même, si vous avez besoin d'utiliser des méthodes "const", ajoutez-les à la classe de base. Le compilateur ne vous permettra pas de modifier ce qu'il pense être les méthodes finales de la classe de base, mais il lira et appellera les méthodes de la sous-classe.

user1122069
la source
Pouvez-vous en donner un exemple, s'il vous plaît?
NO_NAME
la classe MYString implémente GetString {chaîne finale privée aaaa; public String getString (); } la classe MutableString implémente GetString {chaîne privée aaaa2; public String getString (); public String setString ()}
user1122069
-2

Il y aurait deux façons de définir les constantes - constet static final, avec exactement la même sémantique. static finalDécrit en outre le comportement mieux queconst

Bozho
la source
@Bozho, vous avez dit un meilleur comportement que Const, comment est-ce? pouvez-vous partager un exemple
gmhk
eh bien, la variable est static(n'appartenant pas à une instance particulière) et final- ne peut pas être modifiée.
Bozho
-2

Vous pouvez utiliser static final pour créer quelque chose qui fonctionne de manière similaire à Const, j'ai utilisé cela dans le passé.

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
la source
Évalué pour l'optimisation basée sur la rumeur parce que j'ai entendu une rumeur selon laquelle il s'agit d'une stratégie inefficace.
après
J'ai supprimé la rumeur de la réponse. vous pouvez toujours utiliser static final int pour créer du code de style const.
hamish
Ok, j'ai supprimé mon vote défavorable. Peut-être que certains des autres votes négatifs concernent l'instruction switch (qu'est-ce que cela a à voir avec le reste de votre exemple?)
Afarley
dans l'instruction switch, j'ai utilisé le cRPM comme s'il s'agissait d'un const. tout à fait raison, compte tenu de ce qui précède. donc oui j'ai enlevé l'interrupteur.
hamish