Есть ли способ определить универсальный метод, который проверяет на ноль, а затем создать объект? - PullRequest
3 голосов
/ 04 ноября 2010

Я хотел бы написать метод, который проверяет, где аргумент равен нулю, и, если он есть, возвращает новый объект этого типа. это выглядит так:

public static <T> T checkNull(T obj) {
    if (null == obj) return someHowCreateTheObjectWithTypeT();
    else return obj;
}

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

Сначала я подумал об отражении. Но я просто не могу получить экземпляр Class, когда объект имеет значение null, и вы не можете создать Class без имени типа T ...

Обновление:

Я думал о передаче класса в качестве параметра, но это не лучшее решение, как показывают следующие ответы:)

Мое настоящее решение заключается в использовании параметра defaultValue:

public static <T> T checkNull(T obj, T defaultValue) {
    if (null == obj) return defaultValue;
    return obj;
}

Который быстрее и безопаснее, чем решение для отражения, и тот же многословный; Но затем я должен систематически указывать DEFAULT_VALUE для всех типов интересов, что не является легкой работой.

Ответы [ 4 ]

3 голосов
/ 04 ноября 2010

Это невозможно. Чтобы дженерики работали таким образом, он должен захватывать во время компиляции тип, с которым он будет вызываться. Однако null не имеет типа, поэтому вы не сможете определить T, чтобы создать его экземпляр.

Теперь вы можете обойти эту проблему, передав также экземпляр Class, но вам понадобится довольно надежная обработка ошибок с использованием Reflection, чтобы гарантировать, что тип T является конкретным классом и имеет открытый конструктор без параметров, который можно вызывать .

3 голосов
/ 04 ноября 2010

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

public static T checkNull(Object o, Class<T> c) {
  try {
    return (o == null) ? c.newInstance() : o;
  } catch (Exception e) {
    return null;
  }
}
2 голосов
/ 04 ноября 2010

Не может быть сделано. Вы должны добавить дополнительный параметр Class<T>, а затем использовать его для нового отражения. Тип T не сохраняется в процессе компиляции.

1 голос
/ 04 ноября 2010

Как уже отмечали другие, это невозможно сделать. Тем не менее, Guava предоставляет эквивалент значения по умолчанию, которое вы указали в методе:

String foo = Objects.firstNonNull(someString, "default");

Это немного отличается от вашего метода в том, что firstNonNull выдаст NullPointerException, если оба аргумента null.

Другой вариант - создать метод, использующий интерфейс Supplier<T> в Guava или что-то подобное:

public static T firstNonNull(T first, Supplier<? extends T> defaultSupplier) {
  return first != null ? first : Preconditions.checkNotNull(defaultSupplier.get());
}

Затем вы можете использовать Supplier, который создает и возвращает новый экземпляр по умолчанию, когда и только когда первый аргумент равен нулю.

...