Мне кажется, что булев класс является идеальным кандидатом для реализации в качестве перечисления.
Глядя на исходный код, большая часть класса - это статические методы, которые можно перемещать без изменений в перечисление, остальные становятся намного проще, чем перечисление. Сравните оригинал (комментарии и статические методы удалены):
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);
}
}
с версией 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";
}
}
Есть ли какая-то причина, почему Boolean не может стать перечислением?
Если это код Sun, переопределяющий метод equals (), он пропускает очень фундаментальную проверку сравнения ссылок двух объектов перед сравнением их значений. Вот как я думаю, что метод equals () должен быть:
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
Хайленд Марк
источник
источник
if
), но с концептуальной точки зрения / с точки зрения теории типов логические значения и перечисления являются экземплярами типов суммы, поэтому я думаю, что было бы справедливо спросить, почему они не не ликвидировать разрыв между ними.valueOf(String)
(которая будет конфликтовать со значением перечисления) и магию,getBoolean
которая может сделать его так, чтобы онBoolean.valueOf("yes")
возвращал значение true, а не false. Оба из них являются частью спецификации 1.0 и требуют соответствующей обратной совместимости.Ответы:
Ну, я думаю, я мог бы начать с того, что перечисления Java не были добавлены в язык программирования Java до JDK 1.5. и поэтому это решение не было даже альтернативой в первые дни, когда был определен логический класс.
При этом Java имеет репутацию сохраняющей обратной совместимости между выпусками, и поэтому, даже если мы сегодня можем рассматривать ваше решение как хорошую альтернативу, мы не сможем сделать это, не разбив тысячи строк кода, уже использующих старый Boolean. класс.
источник
new Boolean("True")
Иnew Boolean("true")
также может вызвать некоторые проблемы , связанные с гипотетической реализации перечислений.Есть некоторые вещи, которые не работают, и не работают довольно удивительным образом, когда вы сравниваете их с предыдущими функциональными возможностями Java.
Мы собираемся игнорировать бокс, так как он был добавлен в 1.5. Гипотетически, если бы Sun захотел, они могли бы заставить
enum Boolean
себя вести себя так же, как бокс, выполненный наclass Boolean
.Тем не менее, есть и другие удивительные (для программиста) способы, которые внезапно сломались бы по сравнению с функциональностью более раннего класса.
Проблема valueOf (String)
Простой пример этого:
Выполнение этого кода дает:
Проблема здесь в том, что я не могу пройти через что-то, что не является
TRUE
илиFALSE
к чемуvalueOf(String)
.Это нормально ... мы просто переопределим это с помощью нашего собственного метода ...
Но ... здесь есть проблема. Вы не можете переопределить статический метод .
И так, весь код, который передается
true
илиTrue
смешанный случай, будет выдавать ошибку - и это весьма впечатляюще, за исключением времени выполнения.Еще немного веселья с valueOf
Есть некоторые другие биты, которые не работают слишком хорошо:
Для
foo
, я просто получить предупреждение о боксе уже боксировал значение. Тем не менее, код для бара является синтаксической ошибкой:Если мы приведем эту синтаксическую ошибку обратно в
String
тип:Мы возвращаем нашу ошибку во время выполнения:
Зачем кому-то писать это? Не знаю ... но его код, который раньше работал и больше не будет работать.
Не поймите меня неправильно, мне действительно нравится идея только одной копии данного неизменяемого объекта. Перечисление действительно решает эту проблему. Я лично сталкивался с кодом поставщика, в котором были ошибки из кода поставщика, который выглядел примерно так:
это никогда не работало (Нет, я не исправлял это, потому что неправильное состояние было исправлено где-то еще, и исправление этого сломало это странным образом, что у меня действительно не было времени на отладку) . Если бы это было перечисление, этот код сработал бы вместо этого.
Тем не менее, необходимость синтаксиса вокруг перечисления (с учетом регистра - поиск в enumConstantDirectory позади
valueOf
, ошибки времени выполнения, которые должны работать таким же образом для других перечислений) и способ работы статических методов вызывает множество вещей, которые мешают ему быть каплей в замене логического.источник
of
илиfrom
соответствующий javadoc.valueOf
и Boolean.valueOf () существует с 1.0 . Либо Enums не сможет использовать valueOf в качестве статического метода, либо Boolean понадобится метод, отличный от того, который он использовал. Выполнение или нарушает соглашение или совместимость - и отсутствие логического перечисления не нарушает ни то, ни другое. Исходя из этого, выбор довольно прост.Boolean.valueOf(Boolean.valueOf("TRUE"))
, есть два разныхvalueOf
метода:valueOf(String)
иvalueOf(boolean)
. Синтаксическая ошибка, потому что вы забыли реализоватьvalueOf(boolean)
вMyBoolean
. Кроме того, между двумя вызовами существует автоматическая коробка, которая жестко задана на языке,Boolean
но не работает.MyBoolean
Если вы реализовалиvalueOf(boolean)
MyBoolean.valueOf(MyBoolean.valueOf("FALSE").booleanValue())
работуСкорее всего, потому, что примитивный
boolean
тип не являетсяEnum
, а коробочные версии примитивных типов ведут себя почти идентично своей распакованной версии. Например(Производительность может не совпадать, но это другая тема.)
Было бы странно, если бы вы могли написать:
но нет:
источник
if
работу точно так же, как в настоящее время. С другой стороны, нельзя игнорировать тот факт, что вы добавили дополнительную функциональностьBoolean
,boolean
которой нет.В дополнение к
valueOf
вопросу (что является проблемой на уровне Java, он может работать нормально на уровне виртуальной машины Java), это потому , чтоBoolean
имеет открытый конструктор. Это была плохая идея, в настоящее время она устарела, но она здесь, чтобы остаться.источник
Причина в том, что «bool» был частью языка Java намного раньше, чем «enum». В течение многих лет «bool» было очень желательно иметь, в то время как «enum» не было доступно. Только теперь вы можете сказать: «Если бы enum был доступен с самого начала, мы могли бы реализовать bool как enum вместо отдельного типа».
В Swift, который мог бы выразить «bool» как перечисление, есть три структуры с именами «Bool», «DarwinBoolean» и «ObjCBool», реализующие протокол «ExpressibleByBooleanLiteral». (DarwinBoolean совместим с C или C ++ bool, ObjCBool совместим с Objective-C BOOL). «true» и «false» - это специальные значения, распознаваемые компилятором, и могут использоваться только для инициализации объектов, поддерживающих протокол «ExpressibleByBooleanLiteral». Bool имеет внутреннюю переменную "_value", содержащую одноразрядное целое число.
Так что Bool не является частью языка Swift, но входит в стандартную библиотеку. true и false являются частью языка, как и протокол ExpressibleByBooleanLiteral.
источник