ブールクラスは列挙型として実装するのに理想的な候補だと私には思えます。
ソースコードを見ると、ほとんどのクラスは静的メソッドであり、変更せずに列挙型に移動できますが、残りは列挙型としてはるかに単純になります。オリジナルを比較する(コメントと静的メソッドは削除されました):
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);
}
}
列挙型バージョン:
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";
}
}
ブール値が列挙型になれない理由はありますか?
これがequals()メソッドをオーバーライドするSunコードである場合、2つのオブジェクトの参照を比較してから値を比較するという非常に基本的なチェックが欠落しています。これは、equals()メソッドが次のようになるべきだと私が考える方法です。
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof Boolean) {
return value == ((Boolean)obj).booleanValue();
}
return false;
}
まあ、私はJava列挙がJavaプログラミング言語に追加されなかった JDK 1.5まで)。 と主張することから始めることができると思います。そのため、ブールクラスが定義された当初は、このソリューションは代替手段でさえありませんでした。
そうは言っても、Javaはリリース間の下位互換性を維持するという評判があるため、今日、私たちがあなたのソリューションを優れた代替案と見なしても、数千行を壊さずにそれを行うことはできません。古いBooleanクラスをすでに使用しているコードの例。
Javaのbooleanの以前の機能と比較すると、機能しないものや、意外な方法で機能しないものがあります。
ボクシングは1.5で追加されたものであるため、ここでは無視します。仮に、Sunが希望する場合、_enum Boolean
_を_class Boolean
_で実行されるボクシングと同じように動作させることができます。
しかし、以前のクラスの機能と比較して、これが突然壊れる(コーダーにとって)他の驚くべき方法があります。
この簡単な例は次のとおりです。
_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"; }
}
}
_
このコードを実行すると、次のようになります。
true true false false スレッド「メイン」の例外Java.lang.IllegalArgumentException:列挙型定数BooleanStuff.MyBoolean.FaLsE at Java.lang.Enum.valueOf(Enum.Java:236) at BooleanStuff $ MyBoolean.valueOf(BooleanStuff.Java:17) at BooleanStuff.main(BooleanStuff.Java :13)
ここでの問題は、TRUE
またはFALSE
以外の何もvalueOf(String)
に渡すことができないことです。
それで大丈夫です...独自のメソッドでオーバーライドするだけです...
_ public static MyBoolean valueOf(String arg) {
return arg.equalsIgnoreCase("true") ? TRUE : FALSE;
}
_
しかし...ここに問題があります。あなた 静的メソッドをオーバーライドすることはできません 。
そのため、true
やTrue
を含むすべてのコード、またはその他の大文字と小文字が混在している場合、エラーが発生します。また、ランタイム例外が発生すると、非常に見事です。
うまく機能しない他のいくつかのビットがあります:
_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);
}
_
foo
の場合、既にボックス化された値をボックス化することに関する警告が表示されます。ただし、barのコードは構文エラーです。
エラー:(7、24)Java:valueOf(BooleanStuff.MyBoolean) メソッドに適したメソッドが見つかりません[BooleanStuff.MyBoolean.valueOf(Java.lang.String)は適用されません (実際の引数BooleanStuff.MyBooleanはメソッド呼び出し変換ではJava.lang.Stringに変換できません) メソッドJava.lang.Enum.valueOf(Java.lang.Class、Java.lang.String)は適用されません (実際の引数リストと正式な引数リストは長さが異なるため、引数からインスタンス化できません)
その構文エラーを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);
}
_
ランタイムエラーが返されます。
true スレッド「メイン」での例外Java.lang.IllegalArgumentException:列挙定数なしBooleanStuff.MyBoolean.false Java.lang.Enum.valueOf(Enum.Java:236 ) at BooleanStuff $ MyBoolean.valueOf(BooleanStuff.Java:11) at BooleanStuff.main(BooleanStuff.Java:7)
なぜ誰もがそれを書くのですか? Dunno ...しかし、以前は機能し、機能しなくなったそのコード。
誤解しないでください。私は、与えられた不変オブジェクトのコピーを1つだけにするという考えが本当に好きです。 enumはこの問題を解決します。私は、次のようなベンダーコードからのバグが含まれるベンダーコードに個人的に遭遇しました。
_if(boolValue == new Boolean("true")) { ... }
_
それ決しては働いた (いいえ、間違った状態がどこかで修正されたため、修正しませんでした。これを修正すると、奇妙な方法で、デバッグする時間がないことが壊れました。)。これが列挙型の場合、そのコードは代わりに機能します。
ただし、列挙型周辺の構文の必要性(大文字と小文字を区別-valueOf
の背後にある enumConstantDirectory の詳細、他の列挙型でそのように機能する必要があるランタイムエラー)と静的な方法メソッドが機能すると、ブール値の代わりにドロップされることを防ぐために多くの障害が発生します。
最も可能性が高いのは、プリミティブboolean
タイプがEnum
ではなく、ボックス化されたプリミティブタイプのバージョンがボックス化されていないバージョンとほぼ同じように動作するためです。例えば。
Integer x = 5;
Integer y = 7;
Integer z = x + y;
(パフォーマンスは同じではないかもしれませんが、それは異なる主題です。)
あなたが書くことができたらそれはちょっと奇妙だろう:
Boolean b = Boolean.TRUE;
switch (b) {
case Boolean.TRUE:
// do things
break;
case Boolean.FALSE:
// do things
break;
}
だがしかし:
boolean b = true;
switch(b) {
case true:
// do things
break;
case false:
// do things
break;
}
valueOf
の問題(これはJavaレベルの問題であり、JVMレベルでは問題なく動作する可能性があります)に加えて、Boolean
にはパブリックコンストラクターがあるためです。これは悪い考えでしたが、現在は非推奨ですが、これは今後も続く予定です。
その理由は、「bool」がJava言語の一部であり、「enum」よりもずっと前だったためです。「enum」は利用できませんでしたが、「bool」はずっと望ましいものでしたが、 。「enumが最初から利用可能であった場合、別の型ではなくenumとしてboolを実装できたはずです」としか言えません。
「bool」を列挙型として表現できたSwiftには、「Bool」、「DarwinBoolean」、「ObjCBool」という3つの構造体があり、「ExpressibleByBooleanLiteral」プロトコルを実装しています。 (DarwinBooleanはCまたはC++ boolと互換性があり、ObjCBoolはObjective-C BOOLと互換性があります)。 「true」と「false」はコンパイラーによって認識される特別な値であり、「ExpressibleByBooleanLiteral」プロトコルをサポートするオブジェクトを初期化するためにのみ使用できます。 Boolには、1ビット整数を含む内部変数「_value」があります。
したがって、BoolはSwift言語の一部ではありませんが、標準ライブラリの一部です。trueとfalseは言語の一部であり、ExpressibleByBooleanLiteralプロトコルも一部です。