부울 클래스는 열거 형으로 구현하기에 이상적인 후보 인 것 같습니다.
소스 코드를 살펴보면 대부분의 클래스는 정적 메서드이며 열거 형으로 변경되지 않고 나머지는 열거 형으로 훨씬 간단 해집니다. 원본과 비교 (설명 및 정적 메소드 제거) :
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 코드 인 경우, 값을 비교하기 전에 두 오브젝트의 참조를 비교하는 매우 기본적인 점검이 누락되었습니다. 이것은 equals () 메소드가 다음과 같아야한다고 생각합니다.
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof Boolean) {
return value == ((Boolean)obj).booleanValue();
}
return false;
}
답변
글쎄, JDK 1.5까지 Java 열거가 Java 프로그래밍 언어에 추가되지 않았다고 주장함으로써 시작할 수 있다고 생각 합니다. 따라서이 솔루션은 Boolean 클래스가 정의 된 초기에는 대안이 아니 었습니다.
즉, Java는 릴리스 간 이전 버전과의 호환성을 유지하는 것으로 유명하므로 오늘날 솔루션을 훌륭한 대안으로 생각하더라도 이미 이전 부울을 사용하여 수천 줄의 코드를 끊지 않으면 해결할 수 없습니다 수업.
답변
작동하지 않는 것들이 있으며 Java 부울의 이전 기능과 비교할 때 놀라운 방법으로 작동하지 않습니다.
우리는 1.5가 추가 된 권투를 무시할 것입니다. 가설로, 만약 Sun이 원한다면 그들은에서 enum Boolean
수행 된 권투처럼 행동하도록 만들 수있었습니다 class Boolean
.
그러나 이전 클래스의 기능과 비교했을 때 이것이 갑자기 깨지는 다른 놀라운 방법이 있습니다.
valueOf (String) 문제
이에 대한 간단한 예는 다음과 같습니다.
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"; }
}
}
이 코드의 실행은 다음을 제공합니다.
진실 진실 그릇된 그릇된 스레드 "main"의 예외 java.lang.IllegalArgumentException : 열거 형 상수 없음 BooleanStuff.MyBoolean.FaLsE java.lang.Enum.valueOf (Enum.java:236)에서 BooleanStuff $ MyBoolean.valueOf (BooleanStuff.java:17)에서 BooleanStuff.main (BooleanStuff.java:13)에서
여기에서 문제는 아니다 아무것도 통과 할 수 없다는 것입니다 TRUE
또는 FALSE
하기를 valueOf(String)
.
괜찮습니다 … 우리는 우리 자신의 방법으로 그것을 무시할 것입니다 …
public static MyBoolean valueOf(String arg) {
return arg.equalsIgnoreCase("true") ? TRUE : FALSE;
}
하지만 … 여기에 문제가 있습니다. 당신은 정적 메서드를 재정의 할 수 없습니다 .
따라서 전달 true
되거나 True
다른 경우가 혼합 된 모든 코드 는 오류가 발생합니다. 런타임 예외는 매우 훌륭합니다.
valueOf로 더 재미있게
너무 잘 작동하지 않는 다른 비트가 있습니다.
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);
}
런타임 오류가 다시 발생합니다.
진실 스레드 "main"의 예외 java.lang.IllegalArgumentException : 열거 형 상수 없음 BooleanStuff.MyBoolean.false java.lang.Enum.valueOf (Enum.java:236)에서 BooleanStuff $ MyBoolean.valueOf (BooleanStuff.java:11)에서 BooleanStuff.main (BooleanStuff.java:7)에서
왜 누군가가 그것을 쓸까요? Dunno …하지만 코드는 작동했지만 더 이상 작동하지 않습니다.
나를 잘못 이해하지 마라. 나는 주어진 불변의 객체의 사본 하나만을 좋아한다는 것을 정말로 좋아한다. 열거 형은이 문제를 해결합니다. 나는 개인적으로 다음과 같은 벤더 코드에서 버그가있는 벤더 코드를 만났다.
if(boolValue == new Boolean("true")) { ... }
그것은 결코 작동 하지 않았습니다 (아니오, 잘못된 상태가 다른 곳에서 수정 되었기 때문에 수정하지 않았습니다.이 문제를 해결하면 실제로 디버깅 할 시간이 없었던 이상한 방식으로 파산했습니다) . 이것이 열거 형이라면 그 코드가 대신 작동했을 것입니다.
그러나 enum 주위의 구문의 필요성 (대소 문자를 구분 -enumConstantDirectory 뒤에 파고 valueOf
, 다른 enum에 대해 그런 식으로 작동 해야하는 런타임 오류) 및 정적 메서드 작동 방식으로 인해 여러 가지가 깨져서 부울을 대체 할 수 있습니다.
답변
대부분의 경우 원시 때문에 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”이 “enum”보다 훨씬 이전에 Java 언어의 일부이기 때문입니다. 수년 동안 “bool”은 매우 바람직한 반면 “enum”은 사용할 수 없었습니다. “지금부터 열거 형을 사용할 수 있었다면 별도의 유형 대신 부형을 열거 형으로 구현할 수있었습니다”라고 말할 수 있습니다.
“bool”을 열거 형으로 표현할 수있는 Swift에는 “ExpressibleByBooleanLiteral”프로토콜을 구현하는 “Bool”, “DarwinBoolean”및 “ObjCBool”이라는 세 개의 구조체가 있습니다. DarwinBoolean은 C 또는 C ++ bool과 호환되며 ObjCBool은 Objective-C BOOL과 호환됩니다. “true”및 “false”는 컴파일러에서 인식되는 특수 값이며 “ExpressibleByBooleanLiteral”프로토콜을 지원하는 개체를 초기화하는 데만 사용할 수 있습니다. Bool에는 1 비트 정수를 포함하는 내부 변수 “_value”가 있습니다.
따라서 Bool은 Swift 언어의 일부가 아니라 표준 라이브러리입니다. true와 false는 언어의 일부이며 ExpressibleByBooleanLiteral 프로토콜도 마찬가지입니다.