检查并替换Java中多个变量中的空值

6

我正在尝试找到一种在Java中执行多个变量的null检查/替换的简单方法。

我有一个包含大约20个字符串变量的对象。在构造函数中,我想检查任何变量值是否为null。如果它们为null,我想将它们替换为空字符串。我可以执行一系列if语句,但我觉得一定有更简洁的方法来实现这个目标。


3
构造函数中有20个字符串参数是一个更大的问题。 - Ingo Bürk
2
你是否将20个值作为参数传递给构造函数?如果是,那么这真的是一个糟糕的设计。 - Rahul Winner
你能否更清楚地解释一下“我可以执行一系列if语句”的意思? - Kick Buttowski
很遗憾,我并不是这段代码的设计者,我只是在使用它。抱歉,我本意是指一系列if语句,但已经有人纠正了。 - user1795370
7个回答

7
除非您想要使用反射(我强烈不建议),否则最好的方法可能是创建一个帮助方法(return s == null ? "" : s),然后执行。
field1 = nullToEmpty(field1);
field2 = nullToEmpty(field2);
...

如果您已经依赖于Apache Commons或Guava,您可以使用StringUtils.defaultStringStrings.nullToEmpty

3
我同意aioobe的观点,应该尽量避免使用反射。但是,如果你有幸参与了一个需要手动模拟REST接口的项目,并且这个接口返回的对象中包含大量的Integer、String、Double等类型,那么我认为你别无选择。
以下是一个通用方法,它会将对象中所有可找到的空指针替换为其标量默认值,并将字符串字段填充为空字符串。如果它找到的对象具有无参默认构造函数,则会递归执行此操作。希望这对其他处于同样情况的人有所帮助。
static void fillNullObjects(Object object) {
    Field[] fields = object.getClass().getDeclaredFields();
    for (Field field : fields) {
        try {
            field.setAccessible(true);
            if (field.get(object) != null) {
                continue;
            }
            else if (field.getType().equals(Integer.class)) {
                field.set(object, 0);
            }
            else if (field.getType().equals(String.class)) {
                field.set(object, "");
            }
            else if (field.getType().equals(Boolean.class)){
                field.set(object, false);
            }
            else if (field.getType().equals(Character.class)) {
                field.set(object, '\u0000');
            }
            else if (field.getType().equals(Byte.class)) {
                field.set(object, (byte) 0);
            }
            else if (field.getType().equals(Float.class)) {
                field.set(object, 0.0f);
            }
            else if (field.getType().equals(Double.class)) {
                field.set(object, 0.0d);
            }
            else if (field.getType().equals(Short.class)) {
                field.set(object, (short) 0);
            }
            else if (field.getType().equals(Long.class)) {
                field.set(object, 0L);
            }
            else if (field.getType().getDeclaredFields().length > 0){
                for (Constructor<?> constructor : field.getClass().getConstructors()) {
                    if (constructor.getParameterTypes().length == 0) {
                        field.set(object, constructor.newInstance());
                        fillNullObjects(field.get(object));
                    }
                }
            }
       } catch (IllegalAccessException | InstantiationException | InvocationTargetException e) {
            e.printStackTrace();
        }
    }
}

非常有帮助。谢谢你。 - Pratham

2

1
public static String checkNull (String inputString){
    if(inputString == null){
         inputString = "";
    }
    return inputString;
}

只需在需要检查字符串时调用该函数。


2
在我看来,更好的表达方式是 return inputString == null ? "" : inputString; - aioobe
1
@Tom 是的,没错。我太快地解决了那个问题。已经修复了。 - TheFaster

1

将变量存储在数组中(如果您不确定变量的数量,则可以使用列表),并循环遍历它

String[] variables;
//...
for(int i = 0; i < variables.length; i++)
    if(variables[i] == null) variables[i] = "";

1

20个字段变量听起来像是一个极端的情况。在任何情况下,您都应该尽量避免明确处理那么多变量,或者至少将代码分解成它们只在一个地方明确列出。

一种常见的模式是将每个变量与枚举关联,并使用枚举作为映射的键,类型为Enum -> String,或者使用枚举的序数作为索引到大小为Enumeration值的String数组中。

像这样:

public enum StringProperties {
    TTL, RECVBUF, SENDBUF, RETRIES, ... ;
}

如果您想要明确的默认值,可以将枚举与一些参数结合使用:
public enum StringProperties {
    TTL ("100"), 
    RECVBUF ("1024"), 
    SENDBUF ("1500"), 
    RETRIES ("10"), 
    ... 
    ;
    public String getDefaultValue() { ... }
}

这个策略意味着如果你需要添加/删除属性或更改默认值,你的代码需要最少的修改。
在你的(拷贝构造函数?)情况下,你可以使用类似以下的方式循环枚举值:
for (StringProperties property : StringProperties.values()) {
    if (obj.getProperty(property) != null) {
        // handle present case
        ...
    } else {
        // handle default storage case
        ...
    }
}

或者像Thomas说的那样,你可以单独使用一个字符串数组,但这意味着你不需要一种方法来处理每个字符串。

0

对于每个字段,请使用标准的Java方法:

Objects.toString(field, "");

如果可能的话,避免使用具有大量字段的构造函数。建议使用Builder(如在《Effective Java,Item 2:当面临许多构造函数参数时,请考虑使用构建器》中建议的那样)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接