У меня есть этот метод в тот момент, когда я пытаюсь провести рефакторинг.

public static boolean isEmpty(Object value) {
    boolean empty = false;
    if (value instanceof String && ((String) value).isEmpty()) {
        empty = true;
    } else if (value instanceof List && ((List<?>) value).isEmpty()) {
        empty = true;
    } else if (value instanceof String[] && ArrayUtils.isEmpty((String[]) value)) {
        empty = true;
    } else if (value == null) {
        empty = true;
    }

    return empty;
}

Есть ли явно лучший способ сделать это, чего мне не хватает?

Я знаю, что могу поставить все условия в один оператор if, используя связанные операторы ||, но я действительно не понимаю, чем это лучше, чем то, что у меня есть сейчас.

1
LockieR 8 Июл 2021 в 10:37

4 ответа

Лучший ответ

Как упоминалось в ответе deHaar, код можно улучшить, используя комбинации if-return.

Однако вам следует немного обобщить свой код, например поддерживают все типы массивов, а не только строковые массивы, и поддерживают все типы коллекций, а не только списки.

Точно так же String реализует интерфейс с именем CharSequence, поэтому поддерживайте его. Таким образом, код будет поддерживать такие классы, как StringBuilder и StringBuffer.

public static boolean isEmpty(Object value) {
    if (value == null)
        return true;
    if (value instanceof CharSequence) // String, StringBuilder, StringBuffer, ...
        return ((CharSequence) value).isEmpty();
    if (value instanceof Collection) // List, Set, Queue, Deque, ...
        return ((Collection<?>) value).isEmpty();
    if (value instanceof Map)
        return ((Map<?,?>) value).isEmpty();
    if (value.getClass().isArray()) // All array types
        return (Array.getLength(value) == 0);
    return false;
}

Код был изменен, чтобы использовать чистые встроенные методы, то есть не полагаться на ArrayUtils.

ОБНОВЛЕНО : добавлена ​​поддержка примитивных массивов.

Вышеупомянутая реализация близко соответствует оператору JSP EL empty:

Оператор empty - это префиксный оператор, который можно использовать, чтобы определить, является ли значение пустым или пустым.

Чтобы оценить empty A

  • Если A равно null, вернуть true
  • В противном случае, если A - пустая строка, верните true
  • В противном случае, если A - пустой массив, верните true
  • В противном случае, если A является пустым Map, вернуть true
  • В противном случае, если A является пустым Collection, вернуть true
  • В противном случае верните false
2
Andreas 8 Июл 2021 в 17:13

Собственные утилиты Java дают вам возможность проверить, не ли Objects.isNull(value) эквивалентно пустому. Если вы хотите придерживаться нативной Java, вы делаете это правильно, просто украсьте свой код и все. Однако этот метод существует в классе springFramework ObjectUtils независимо от типа объекта:

import org.springframework.util.ObjectUtils;

public static boolean isEmpty(Object value) {
    boolean empty = false;
if (ObjectUtils.isEmpty(value)) {
empty= true
}
return empty;
}

Документ Spring Framework: Class ObjectUtils

1
Hajed.Kh 8 Июл 2021 в 08:09

Вы можете сократить этот код, опуская флаг и напрямую возвращая результат проверки на пустоту:

public static boolean isEmpty(Object value) {
    if (value instanceof String) {
        return ((String) value).isEmpty();
    } else if (value instanceof List) {
        return ((List<?>) value).isEmpty();
    } else if (value instanceof String[]) {
        return ArrayUtils.isEmpty((String[]) value);
    } else {
        return value == null;
    }
}

Это можно считать улучшением читабельности.

2
deHaar 8 Июл 2021 в 08:05

В Java 17 вы сможете написать это, используя выражение switch. Согласно проблеме 8213076 синтаксис будет следующим:

public static boolean isEmpty(Object value) {
    return switch(value) {
      case String s -> s.isEmpty();
      case List l -> l.isEmpty();
      case String[] sa -> ArrayUtils.isEmpty(sa);
      default -> value == null;
    }
}

NB: это предварительная версия в Java 17. Она может быть изменена или даже полностью удалена в более позднем выпуске.


(Первоначально предложенный синтаксис в JEP 406 был немного другим:

public static boolean isEmpty(Object value) {
    return switch(value) {
      case String -> value.isEmpty();
      case List -> value.isEmpty();
      case String[] -> ArrayUtils.isEmpty(value);
      default -> value == null;
    }
}

Как видите, исходная версия не требовала отдельной переменной привязки в каждом case.)

6
Stephen C 8 Июл 2021 в 22:58