Il me semble que la classe booléenne est un candidat idéal pour être implémenté en tant qu'énumération.
En regardant le code source, la plupart de la classe est constituée de méthodes statiques qui pourraient être déplacées inchangées vers une énumération, le reste devenant beaucoup plus simple comme une énumération. Comparer l'original (commentaires et méthodes statiques supprimés):
public final class Boolean implements java.io.Serializable,
Comparable<Boolean>
{
public static final Boolean TRUE = new Boolean(true);
public static final Boolean FALSE = new Boolean(false);
private final boolean value;
public Boolean(boolean value) {
this.value = value;
}
public Boolean(String s) {
this(toBoolean(s));
}
public boolean booleanValue() {
return value;
}
public String toString() {
return value ? "true" : "false";
}
public int hashCode() {
return value ? 1231 : 1237;
}
public boolean equals(Object obj) {
if (obj instanceof Boolean) {
return value == ((Boolean)obj).booleanValue();
}
return false;
}
public int compareTo(Boolean b) {
return compare(this.value, b.value);
}
}
avec une version enum:
public enum Boolean implements Comparable<Boolean>
{
FALSE(false), TRUE(true);
private Boolean(boolean value) {
this.value = value;
}
private final boolean value;
public boolean booleanValue() {
return value;
}
public String toString() {
return value ? "true" : "false";
}
}
Y a-t-il une raison pour laquelle Boolean ne peut pas devenir un enum?
S'il s'agit du code Sun pour remplacer la méthode equals (), il manque une vérification très fondamentale de la comparaison des références des deux objets avant de comparer leurs valeurs. Voici comment je pense que la méthode equals () devrait être:
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof Boolean) {
return value == ((Boolean)obj).booleanValue();
}
return false;
}
java
api
source-code
Highland Mark
la source
la source
if
) mais d'un point de vue conceptuel / théorie des types, les booléens et les énumérations sont tous les deux des types de somme, donc je pense qu'il est juste de demander pourquoi ils ne l'ont pas fait 't combler l'écart entre eux.valueOf(String)
(qui serait en conflit avec la valeur de l'énumération) et la magie derrièregetBoolean
qui peut faire en sorte queBoolean.valueOf("yes")
renvoie vrai plutôt que faux. Les deux font partie de la spécification 1.0 et nécessiteraient une compatibilité descendante appropriée.Réponses:
Eh bien, je suppose que je pourrais commencer par faire valoir que les énumérations Java n'ont pas été ajoutées au langage de programmation Java avant le JDK 1.5. et par conséquent, cette solution n'était même pas une alternative au début lorsque la classe booléenne a été définie.
Cela étant dit, Java a la réputation de conserver la compatibilité descendante entre les versions et donc, même si nous considérons aujourd'hui votre solution comme une bonne alternative, nous ne pouvons pas le faire sans casser des milliers de lignes de code en utilisant déjà l'ancien booléen. classe.
la source
new Boolean("True")
etnew Boolean("true")
peut également causer des problèmes avec l'implémentation de l'énumération hypothétique.Il y a certaines choses qui ne fonctionnent pas, et ne fonctionnent pas de manière assez surprenante lorsque vous les comparez aux fonctionnalités précédentes du booléen Java.
Nous allons ignorer la boxe car cela a été ajouté avec 1.5. En théorie, si Sun l'avait voulu, ils auraient pu faire en sorte que le
enum Boolean
comportement se fasse exactement comme celui de la boxeclass Boolean
.Pourtant, il existe d'autres façons surprenantes (pour le codeur) que cela se briserait soudainement par rapport à la fonctionnalité de la classe précédente.
Le problème valueOf (String)
Un exemple simple de ceci est:
L'exécution de ce code donne:
Le problème ici est que je ne peux pas passer à travers tout ce qui est pas
TRUE
ouFALSE
àvalueOf(String)
.C'est ok ... nous allons simplement le remplacer par notre propre méthode ...
Mais ... il y a un problème ici. Vous ne pouvez pas remplacer une méthode statique .
Et donc, tout le code qui circule
true
ou toutTrue
autre cas mélangé sera erroné - et de manière assez spectaculaire avec une exception d'exécution.Un peu plus de plaisir avec valueOf
Il y a quelques autres bits qui ne fonctionnent pas trop bien:
Pour
foo
, je reçois juste un avertissement concernant la mise en boîte d'une valeur déjà en boîte. Cependant, le code pour bar est une erreur de syntaxe:Si nous contraignons cette erreur de syntaxe dans un
String
type:Nous récupérons notre erreur d'exécution:
Pourquoi quelqu'un écrirait ça? Je ne sais pas ... mais son code qui fonctionnait et ne fonctionnerait plus.
Ne vous méprenez pas, j'aime vraiment l'idée d'une seule copie d'un objet immuable donné. L'énumération résout ce problème. J'ai personnellement rencontré du code fournisseur contenant des bogues provenant du code fournisseur qui ressemblait à ceci:
cela n'a jamais fonctionné (non, je ne l'ai pas corrigé car l'état incorrect a été corrigé ailleurs, et la correction de cela a cassé cela de manière étrange que je n'ai vraiment pas eu le temps de déboguer) . S'il s'agissait d'une énumération, ce code aurait plutôt fonctionné.
Cependant, les nécessités de la syntaxe autour de l'énumération (sensible à la casse - creuser dans l' énumConstantDirectory derrière
valueOf
, les erreurs d'exécution qui doivent fonctionner de cette façon pour les autres énumérations) et le fonctionnement des méthodes statiques provoquent un certain nombre de choses à casser qui l'empêchent de étant une baisse en remplacement d'un booléen.la source
of
orfrom
et un javadoc approprié.valueOf
et Boolean.valueOf () existe depuis 1.0 . Soit Enums ne pourrait pas utiliser valueOf comme méthode statique, soit Boolean aurait besoin d'une méthode différente de celle qu'il a utilisée. Faire soit casse la convention ou la compatibilité - et ne pas avoir de booléen comme une énumération rompt non plus. De là, le choix est assez simple.Boolean.valueOf(Boolean.valueOf("TRUE"))
, il existe deuxvalueOf
méthodes différentes :valueOf(String)
etvalueOf(boolean)
. L'erreur de syntaxe est due au fait que vous avez oublié d'implémenter levalueOf(boolean)
inMyBoolean
. Ensuite, il y a la mise en boîte automatique entre les deux appels, qui est codée en dur dans la langue,Boolean
mais pasMyBoolean
. Si vous avez implémenté desvalueOf(boolean)
MyBoolean.valueOf(MyBoolean.valueOf("FALSE").booleanValue())
travauxTrès probablement parce que le
boolean
type primitif n'est pas unEnum
, et les versions en boîte des types primitifs se comportent presque de manière identique à leur version non en boîte. Par exemple(La performance n'est peut-être pas la même, mais c'est un sujet différent.)
Ce serait un peu étrange si vous pouviez écrire:
mais non:
la source
if
travail comme il le fait actuellement. D'un autre côté, il n'y a aucun moyen d'ignorer le fait que vous avez ajouté des fonctionnalités supplémentaires à cellesBoolean
queboolean
vous n'avez pas.En plus de
valueOf
problème (qui est un problème au niveau Java, cela pourrait bien fonctionner au niveau JVM), c'est parce qu'ilBoolean
a un constructeur public. C'était une mauvaise idée, actuellement déconseillée, mais c'est celle qui est là pour rester.la source
La raison en est que "bool" faisait partie du langage Java bien avant "enum". Pendant de nombreuses années, "bool" était très souhaitable, tandis que "enum" n'était pas disponible. Ce n'est que maintenant que vous pouvez dire "si l'énumération était disponible depuis le début, alors nous aurions pu implémenter bool comme une énumération au lieu d'un type séparé".
Dans Swift, qui aurait pu exprimer "bool" comme une énumération, il existe trois structures nommées "Bool", "DarwinBoolean" et "ObjCBool" implémentant le protocole "ExpressibleByBooleanLiteral". (DarwinBoolean est compatible avec un booléen C ou C ++, ObjCBool est compatible avec un BOOL Objective-C). "true" et "false" sont des valeurs spéciales reconnues par le compilateur et ne peuvent être utilisées que pour initialiser des objets prenant en charge le protocole "ExpressibleByBooleanLiteral". Bool a une variable interne "_value" contenant un entier d'un bit.
Bool ne fait donc pas partie du langage Swift, mais de la bibliothèque standard. true et false font partie du langage, tout comme le protocole ExpressibleByBooleanLiteral.
la source