知道Class中的所有变量是否为空的最佳方法是什么?

th3*_*aly 23 java

这意味着该类已初始化,但未设置变量.

样本类:

public class User {

    String id = null;
    String name = null;

    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}
Run Code Online (Sandbox Code Playgroud)

实际的类是巨大的,我不想检查每个变量是否(xyz == null).

Did*_*r L 47

对于Java 8的另一个非反射解决方案,在paxdiabo的答案中,但没有使用一系列if的,将流式传输所有字段并检查空值:

return Stream.of(id, name)
        .allMatch(Objects::isNull);
Run Code Online (Sandbox Code Playgroud)

这仍然很容易保持,同时避免反射.


ars*_*jii 31

尝试这样的事情:

public boolean checkNull() throws IllegalAccessException {
    for (Field f : getClass().getDeclaredFields())
        if (f.get(this) != null)
            return false;
    return true;            
}
Run Code Online (Sandbox Code Playgroud)

尽管如果可行的话,检查每个变量可能会更好.

  • 请注意,这不适用于“私有”字段。 (4认同)
  • @Yar,要使此功能适用于私有字段,您应该执行f.setAccessible(true) (3认同)
  • 是的,它可能比 `if (var == null)` 花费更长的时间。 (2认同)
  • 使用反射非常慢,隐藏了很多实际完成的事情,并且从更一般的角度来看,重构可能会很痛苦(当实际上通过反射时,一个字段可以被您的 IDE 标记为未使用:/,您将永远不知道它实际上被使用了,除非您有良好的测试或运行您的应用程序)当然,这并不禁止使用反射,但如果您可以使用任何其他选项..那就去吧 (2认同)
  • 说您需要添加 `f.setAccessible(true)` 以避免私有字段上的 IllegalAccessException 一点也不为过。 (2认同)

Mar*_*nyi 12

这可以使用生成的 Lombokequals和静态EMPTY对象轻松完成:

import lombok.Data;

public class EmptyCheck {
    public static void main(String[] args) {
        User user1 = new User();

        User user2 = new User();
        user2.setName("name");

        System.out.println(user1.isEmpty()); // prints true
        System.out.println(user2.isEmpty()); // prints false
    }

    @Data
    public static class User {
        private static final User EMPTY = new User();

        private String id;
        private String name;
        private int age;

        public boolean isEmpty() {
            return this.equals(EMPTY);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

先决条件

  • 不应使用自定义行为来实现默认构造函数,因为它用于创建EMPTY对象
  • 类的所有字段都应该有一个实现equals(内置Java类型通常没有问题,如果是自定义类型,您可以使用Lombok)

优点

  • 不涉及反射
  • 随着新字段添加到类中,这不需要任何维护,因为 Lombok 将在equals实现中自动检查它们
  • 不像一些其他的答案,这个作品不只是为null检查,而且对于具有非空默认值基本类型(例如,如果字段为int它检查0,在以下情况下boolean进行false,等等)

  • 这里的 Empty 是一个静态字段,所以应该不是问题。 (3认同)
  • 这就是我使用 lombok 注释的原因 (2认同)

b15*_*b15 10

如果你想要这个用于单元测试,我只使用hasNoNullFieldsOrProperties()来自assertj

assertThat(myObj).hasNoNullFieldsOrProperties();
Run Code Online (Sandbox Code Playgroud)


小智 6

流呢?

public boolean checkFieldsIsNull(Object instance, List<String> fieldNames) {

    return fieldNames.stream().allMatch(field -> {
        try {
            return Objects.isNull(instance.getClass().getDeclaredField(field).get(instance));
        } catch (IllegalAccessException | NoSuchFieldException e) {
            return true;//You can throw RuntimeException if need.
        }
    });
}
Run Code Online (Sandbox Code Playgroud)


pax*_*blo 5

“最佳”是一个主观术语:-)

我只会使用检查每个变量的方法。如果您的班级已经有很多这样的东西,那么如果您执行以下操作,则大小增加不会那么大:

public Boolean anyUnset() {
    if (  id == null) return true;
    if (name == null) return true;
    return false;
}
Run Code Online (Sandbox Code Playgroud)

如果您将所有内容保持在相同的顺序,则代码更改(以及如果您偏执的话可以使用脚本自动检查)将相对轻松。

另外(假设它们都是字符串),您基本上可以将这些值放入某种映射(例如HashMap)中,并仅保留该列表的键名列表。这样,您可以遍历键列表,检查值设置是否正确。

  • 是的你将会。我不确定您为什么会认为这是一个问题。您知道要添加的字段,您必须为它们创建setter和getter。添加一条简单的额外检查行并不会带来很多额外的工作。 (3认同)
  • 但是,如果这样做,则每次向类添加字段时都必须编辑该方法。此外,可以将通用方法放在抽象类中,并扩展为在所有其他Value Object中使用 (2认同)
  • @Birger,如果那是他们的意思,那么他们应该这么说。在过去的四年左右的时间里,他们有足够的机会对其进行更改:-)在任何情况下,正如其他人也提出的那样,除非您的类非常不稳定,添加了成员​​变量或经常大量移除。 (2认同)