Подтвердить что ты не робот

Лучший способ определить true, false, unset state

Если у вас есть ситуация, когда вам нужно знать, где не было задано логическое значение (например, если это недопустимое значение должно наследоваться от родительского значения), логический примитив Java (и эквивалент на других языках) явно не адекватной.

Какая наилучшая практика для достижения этой цели? Определите новый простой класс, способный выражать все три состояния или использовать класс Java Boolean и использовать null для указания состояния unset?

4b9b3361

Ответ 1

Boolean a = true;
Boolean b = false;
Boolean c = null;

Я бы это использовал. Это наиболее прямолинейно.

Другой способ - использовать перечисление. Возможно, это еще лучше и быстрее, так как не требуется бокс:

public enum ThreeState {
    TRUE,
    FALSE,
    TRALSE
};

Преимущество первого заключается в том, что пользователям вашего класса не нужно заботиться о логическом состоянии трех состояний. Они все равно могут пройти true и false. Если вам не нравится null, так как он мало говорит о его значении здесь, вы все равно можете сделать public static final Boolean tralse = null; в своем классе.

Ответ 2

В Java 8 есть опция Необязательный:

public static final Optional<Boolean> TRI_TRUE = Optional.of(true);
public static final Optional<Boolean> TRI_FALSE = Optional.of(false);
public static final Optional<Boolean> TRI_UNKNOWN = Optional.empty();

В качестве бонуса вы получите все эти карты и методы использования.

Ответ 3

Хотя это не специфично для Java, мои собственные предпочтения в этом сценарии состоят в том, чтобы определить класс или перечисление ThreeState и использовать его - как вы уже упоминали, True, False и Undefined (или Default или Unset, как диктует ваша терминология, специфичная для вашего домена). Он чувствует себя лучше, более естественным и более самодокументированным, чем представляет unset/undefined с null.

Ответ 4

@Nullable Boolean получает мой голос.

Ответ 5

Использование нулей для представления состояния чего-то плохого дизайна. Это неописуемо и трудно поддерживать. Я предпочел бы иметь объект State с состоянием по умолчанию, если на нем не было явно установлено. Например:

if(state == null) {
    doSomething();
}

Это не говорит мне ничего о ожидаемом состоянии. Что-то более похожее на это делает его более понятным.

if(state.awaitingSet()) {
    doSomething();
}

Не говоря уже о расширяемости. Что происходит, когда вам нужно четвертое состояние?

Ответ 6

Это зависит. Здесь вы упоминаете, что оно будет отменено, если оно должно наследовать его значение из родительского значения. У вас есть иерархия данных? Что-то вроде этого:

Parent a { 
    boolean val = true;
    boolean val2 = false; 
}
Child b {
    boolean val = false;
    //here val2 should be unset!
}

В этом случае, если это возможно, я бы сказал, просто не включайте val2 в Child, и ваша логика поиска будет такой, чтобы, если она не находит переменную, она ищет родителей для значения.

Ответ 7

Я бы просто использовал int (целое число) со значениями 0,1,2 и обрабатывал внутри программы.

Ответ 8

Чтобы добавить к @voho, Optional также хорошо работает с лямбда, создавая потенциально более чистую структуру:

public class Node {
  private Node parent;
  private Optional<Boolean> something = Optional.empty();

  public boolean isSomething() {
    return something.orElseGet(() -> {
      if (parent != null)
        return parent.isSomething();
      return false;
    });
  }

  public void setSomething(boolean v) {
    this.something = Optional.of(v);
  }
}

Тем не менее, это все же не очевидно, что намного лучше, чем Boolean и нулевая проверка:

public class Node {
  private Node parent;
  private Boolean something;

  public boolean isSomething() {
    if (something != null)
      return something;
    if (parent != null)
      return parent.isSomething();
    return false;
  }

  public void setSomething(boolean v) {
    this.something = v;
  }
}

Ответ 9

В классе родителя инициализируйте значение boolean для null и в дочернем классе создайте метод, чтобы проверить, установлено ли логическое значение

в родительском классе

private Boolean a = null;

public void setA(Boolean a) {
    this.a = a;
}


public Boolean getA() {
    return a;
}

В дочернем классе

if (a == true)
{
dothis;
}
else if (a == false)
{
dothat;
}
else
{
assert false : "Boolean a has not been set";
}

Убедитесь, что утверждения включены. Утверждения предназначены только для цикла разработки и цикла тестирования, они не предназначены для исключений во время выполнения.

Ответ 10

java.lang.Boolean делает это за вас. Существуют статические константы Boolean.TRUE, Boolean.False.

private Boolean myBoolean;

должно быть все, что вам нужно. Обратите внимание, что Boolean.TRUE пройдет тест эквивалентности, но отличается от "true" (который получает autoboxed до TRUE).