Ci sono alcune cose che non funzionano e non funzionano in modo piuttosto sorprendente quando le si confronta con le precedenti funzionalità del booleano di Java.
Ignoreremo il pugilato in quanto è stato aggiunto qualcosa con 1.5. Ipoteticamente, se Sun avesse voluto, avrebbero potuto fare in modo che enum Boolean
si comportasse esattamente come il boxing eseguito su class Boolean
.
Tuttavia, esistono altri modi sorprendenti (per il programmatore) che questo si interromperebbe improvvisamente rispetto alla funzionalità della classe precedente.
Il problema valueOf (String)
Un semplice esempio di questo è:
public class BooleanStuff {
public static void main(String args[]) {
Boolean foo = Boolean.valueOf("TRUE");
System.out.println(foo);
foo = Boolean.valueOf("TrUe");
System.out.println(foo);
foo = Boolean.valueOf("yes"); // this is actually false
System.out.println(foo);
// Above this line is perfectly acceptable Java 1.3
// Below this line takes Java 1.5 or later
MyBoolean bar;
bar = MyBoolean.valueOf("FALSE");
System.out.println(bar);
bar = MyBoolean.valueOf("FaLsE");
System.out.println(bar);
}
enum MyBoolean implements Comparable<MyBoolean> {
FALSE(false), TRUE(true);
private MyBoolean(boolean value) { this.value = value; }
private final boolean value;
public boolean booleanValue() { return value; }
public String toString() { return value ? "true" : "false"; }
}
}
L'esecuzione di questo codice fornisce:
true
true
false
false
Exception in thread "main" java.lang.IllegalArgumentException: No enum constant BooleanStuff.MyBoolean.FaLsE
at java.lang.Enum.valueOf(Enum.java:236)
at BooleanStuff$MyBoolean.valueOf(BooleanStuff.java:17)
at BooleanStuff.main(BooleanStuff.java:13)
Il problema qui è che non posso passare attraverso tutto ciò che non è TRUE
o FALSE
a valueOf(String)
.
Va bene ... lo sostituiremo con il nostro metodo ...
public static MyBoolean valueOf(String arg) {
return arg.equalsIgnoreCase("true") ? TRUE : FALSE;
}
Ma ... c'è un problema qui. non può eseguire l'override di un metodo statico .
E così, tutto il codice che sta passando attorno a true
o True
oa qualche altro caso misto uscirà in errore - e in modo abbastanza spettacolare con un'eccezione di runtime.
Ancora più divertimento con valueOf
Ci sono altri bit che non funzionano molto bene:
public static void main(String args[]) {
Boolean foo = Boolean.valueOf(Boolean.valueOf("TRUE"));
System.out.println(foo);
MyBoolean bar = MyBoolean.valueOf(MyBoolean.valueOf("FALSE"));
System.out.println(bar);
}
Per foo
, ricevo solo un avvertimento sulla boxing di un valore già in scatola. Tuttavia, il codice per la barra è un errore di sintassi:
Error:(7, 24) java: no suitable method found for valueOf(BooleanStuff.MyBoolean)
method BooleanStuff.MyBoolean.valueOf(java.lang.String) is not applicable
(actual argument BooleanStuff.MyBoolean cannot be converted to java.lang.String by method invocation conversion)
method java.lang.Enum.valueOf(java.lang.Class,java.lang.String) is not applicable
(cannot instantiate from arguments because actual and formal argument lists differ in length)
Se riusciamo a forzare l'errore di sintassi in un tipo String
:
public static void main(String args[]) {
Boolean foo = Boolean.valueOf(Boolean.valueOf("TRUE"));
System.out.println(foo);
MyBoolean bar = MyBoolean.valueOf(MyBoolean.valueOf("FALSE").toString());
System.out.println(bar);
}
Otteniamo il nostro errore di runtime:
true
Exception in thread "main" java.lang.IllegalArgumentException: No enum constant BooleanStuff.MyBoolean.false
at java.lang.Enum.valueOf(Enum.java:236)
at BooleanStuff$MyBoolean.valueOf(BooleanStuff.java:11)
at BooleanStuff.main(BooleanStuff.java:7)
Perché qualcuno lo scriverebbe? Boh ... ma il suo codice funzionava e non funzionava più.
Non fraintendermi, mi piace davvero l'idea di una sola copia di un dato oggetto immutabile di sempre. L'enum risolve questo problema. Ho incontrato personalmente il codice del fornitore che conteneva bug nel codice del fornitore che assomigliava a questo:
if(boolValue == new Boolean("true")) { ... }
che mai ha lavorato (No, non l'ho risolto perché lo stato errato era stato riparato da qualche altra parte, e aggiustandolo si è rotto in modo strano che davvero non l'ho fatto t avere il tempo di eseguire il debug) . Se questo fosse un enum, quel codice avrebbe funzionato invece.
Tuttavia, le necessità della sintassi attorno all'enumerazione (sensibile alla distinzione tra maiuscole e minuscole - scavare nel enumConstantDirectory dietro valueOf
, errori di runtime che devono funzionare in questo modo per le altre enumerazioni) e il modo in cui i metodi statici funzionano un numero di cose da interrompere che impedisce che si verifichi una sostituzione in sostituzione di un booleano.