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

Возможно ли в Java проверить, являются ли поля объектов пустыми, а затем добавить значение по умолчанию ко всем этим атрибутам?

Мне нужно убедиться, что атрибут объекта не равен null, и добавьте значение по умолчанию, если оно равно null. Есть ли простой способ сделать это, или мне нужно сделать это вручную, проверив каждый атрибут его получателями и сеттерами?

4b9b3361

Ответ 1

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

for (Field f : obj.getClass().getFields()) {
  f.setAccessible(true);
  if (f.get(obj) == null) {
     f.set(obj, getDefaultValueForType(f.getType()));
  }
}

[Обновление]

С современной Java вы можете использовать аннотации для установки значений по умолчанию для полей для каждого класса. Полная реализация может выглядеть так:

// DefaultString.java:
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface DefaultString {
    String value();
}

// DefaultInteger.java:
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface DefaultInteger {
    int value();
}

// DefaultPojo.java:
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;

public class DefaultPojo {

    public void setDefaults() {
        for (Field f : getClass().getFields()) {
            f.setAccessible(true);
            try {
                if (f.get(this) == null) {
                    f.set(this, getDefaultValueFromAnnotation(f.getAnnotations()));
                }
            } catch (IllegalAccessException e) { // shouldn't happen because I used setAccessible
            }
        }
    }

    private Object getDefaultValueFromAnnotation(Annotation[] annotations) {
        for (Annotation a : annotations) {
            if (a instanceof DefaultString)
                return ((DefaultString)a).value();
            if (a instanceof DefaultInteger)
                return ((DefaultInteger)a).value();
        }
        return null;
    }

}

// Test Pojo
public class TestPojo extends DefaultPojo {
    @DefaultString("Hello world!")
    public String stringValue;
    @DefaultInteger(42);
    public int integerValue;
}

Тогда значения по умолчанию для TestPojo можно установить, просто запустив test.setDetaults()

Ответ 2

Вам нужно вручную фильтровать входные данные для конструкторов и сеттеров. Ну... вы могли бы использовать отражение, но я бы не советовал. Часть работы конструкторов и сеттеров заключается в проверке ввода. Это может включать такие вещи, как:

public void setPrice(double price) {
  if (price < 0.0d) {
    throw new IllegalArgumentException("price cannot be negative " + price);
  }
  this.price = price;
}

и

public void setName(String name) {
  if (name == null) {
    throw new NullPointerException("name cannot be null");
  }
  this.name = name;
}

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

Ответ 3

Возможно, проверьте Hibernate Validator 4.0, справочную реализацию JSR 303: Bean Проверка.

Это пример аннотированного класса:

public class Address {

    @NotNull 
    private String line1;
    private String line2;
    private String zip;
    private String state;

    @Length(max = 20)
    @NotNull
    private String country;

    @Range(min = -2, max = 50, message = "Floor out of range")
    public int floor;

        ...
}

Для ознакомления см. Начало работы с JSR 303 (Bean Validation) - часть 1 и часть 2 или раздел "Начало работы" справочного руководства, которое является частью дистрибутива Hibernate Validator.

Ответ 4

Неотражающее решение для Java 8 без использования ряда if's должно было бы передавать все поля и проверять на отсутствие:

return Stream.of(id, name).allMatch(Objects::isNull);

Это остается довольно легко поддерживать, избегая отражения. Это вернет true для нулевых атрибутов.

Ответ 5

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

В качестве альтернативы вы можете инициализировать объект со значениями по умолчанию. Таким образом вам не нужно делать какие-либо проверки.

Ответ 6

У меня недостаточно контекста, чтобы дать вам правильный ответ, но я посоветую вам сделать код неизменным максимально возможным. Используйте поля public final. Больше getters или setters: каждое поле должно быть определено constructor. Ваш код короче, читабельнее и не позволяет писать код с побочными эффектами.

Это не мешает вам передавать пустые аргументы вашему конструктору, хотя... Вы все равно можете проверить каждый аргумент, как это было предложено с помощью @cletus, но я предлагаю вам вместо NullPointerException добавить IllegalArgumentException, что doesn не давайте нового намека на то, что вы сделали.

В любом случае, это то, что я делаю, насколько могу, и это улучшило мой код (читаемость, стабильность) в большой степени. Все в моей команде делают это, и мы очень этому довольны. Мы узнали, что когда мы пытаемся написать код erlang, где все неизменно.

Надеюсь, что это поможет.

Ответ 7

Я пробовал это, и он работает без каких-либо проблем, чтобы проверить, пусто ли поле. Я частично ответил на ваш вопрос, поскольку я лично не пытался добавлять значения по умолчанию в атрибуты

if(field.getText()!= null && !field.getText().isEmpty())

Надеюсь, что это поможет

Ответ 8

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

@SuppressWarnings({ "unchecked" })
static void emptyObject(Object obj) 
{
    Class c1 = obj.getClass();
    Field[] fields = c1.getDeclaredFields();

    for(Field field : fields)
    {
        try
        {
            if(field.getType().getCanonicalName() == "boolean")
            {
                field.set(obj, false);
            }
            else if(field.getType().getCanonicalName() == "char")
            {
                field.set(obj, '\u0000');
            }
            else if((field.getType().isPrimitive()))
            {
                field.set(obj, 0);
            }
            else
            {
                field.set(obj, null);
            }
        }
        catch(Exception ex)
        {

        }
    }
}