Лучший способ определить истинное, ложное, неустановленное состояние - PullRequest
22 голосов
/ 24 ноября 2008

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

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

Ответы [ 10 ]

42 голосов
/ 24 ноября 2008
Boolean a = true;
Boolean b = false;
Boolean c = null;

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

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

public enum ThreeState {
    TRUE,
    FALSE,
    TRALSE
};

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

12 голосов
/ 29 декабря 2015

В 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();

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

10 голосов
/ 24 ноября 2008

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

8 голосов
/ 24 ноября 2008

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

4 голосов
/ 24 ноября 2008

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

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

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

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

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

1 голос
/ 04 сентября 2017

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

1 голос
/ 24 ноября 2008

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

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

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

0 голосов
/ 08 августа 2018

Чтобы добавить к @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;
  }
}
0 голосов
/ 24 ноября 2008

В родительском классе инициируйте логическое значение 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";
}

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

0 голосов
/ 24 ноября 2008

java.lang.Boolean сделает это за вас. Есть статические константы Boolean.TRUE, Boolean.False.

private Boolean myBoolean;

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...