,首先我要指出,你的代码中有一个错误:
if (properties.getProperty("totalnum").equals("null")) { ... }
如果没有定义财产,getProperty()
返回null
,因此当您尝试访问equals()
时,您的代码将产生NullPointerException
。它不会返回值为“null”的字符串。这就是所有线路的情况。
我处理这个使用反射,与声明public
领域可能与值检查被标注一个配置类。然后,方法将在该配置类的实例上设置值,从属性映射中读取。
进一步阅读:
这样做的优点是该配置显示intuitiv中的有效值e,口语格式。缺点是“解组”代码有点复杂。尽管这种方法非常强大。
的配置看起来是这样的:
static class Config {
@RegExp("^(one|two)$")
public String number;
public Boolean check;
@Required @Range(min=1, max=6)
public Integer totalnum;
}
如果字段缺乏@Required
注释,丢失的属性不会导致异常,因而使用的Config
的初始值。
解组使用这个工作:
Config config = new Config();
setProperties(properties, config);
setProperties()
当值缺失会引发一些例外,有错误的类型或值。可以捕捉并区分异常以显示适当的错误消息。
在你的应用程序,你可以再访问配置一样简单对象:
if (config.totalnum == 3) {
// do something when totalnum is 3
}
这是解组代码:
private void setProperties(Properties properties, Props props) throws SecurityException, IllegalArgumentException, IllegalAccessException {
Class<?> clazz = props.getClass();
for (Field field : clazz.getDeclaredFields()) {
if ((field.getModifiers() & Modifier.PUBLIC) == 0) {
// ignore non-public properties
continue;
}
// the type of the field
Class<?> fieldType = field.getType();
// the field name of the class
String fieldName = field.getName();
// the raw value loaded from the .properties file
String value = properties.getProperty(fieldName);
// fields may be annotated with @Required
boolean required = (field.getAnnotation(Required.class) != null);
if (required && value == null) {
// field required but not defined in the properties, fail
throw new IllegalArgumentException(
String.format(
"Field %s is required",
fieldName
)
);
} else if (value == null) {
// ignore undefined field, default to class initialized value
continue;
}
// checks per type follow ...
if (fieldType == String.class) {
// fields may be annotated with RegExp to specify a matcher
RegExp regExp = field.getAnnotation(RegExp.class);
if (regExp != null && !Pattern.matches(regExp.value(), value)) {
throw new IllegalArgumentException(
String.format(
"Value for field %s does not match %s: %s",
fieldName,
regExp.value(),
value
)
);
}
field.set(props, value);
} else if (fieldType == Integer.class) {
// may throw NumberFormatException if not a valid integer
Integer intValue = Integer.parseInt(value);
// fields may be annotated with Range to specify an integer range
Range range = field.getAnnotation(Range.class);
if (range != null && !(intValue >= range.min() && intValue <= range.max())) {
throw new IllegalArgumentException(
String.format(
"Value for field %s out of range (%d..%d): %d",
fieldName,
range.min(),
range.max(),
intValue
)
);
}
field.set(props, intValue);
} else if (fieldType == Boolean.class) {
// strictly check valid boolean values
if (!Pattern.matches("^(true|false)$", value)) {
throw new IllegalArgumentException(
String.format(
"Value for field %s is not a valid boolean (true|false): %s",
fieldName,
value
)
);
}
field.set(props, Boolean.parseBoolean(value));
}
}
}
尽管已经相当复杂的代码是相当简单的。它不处理其他数字类型,如Long
或基本类型如int
。这些可以使用更多if
分支来实施。
这些是说明(在独立的类中定义):
@Retention(RUNTIME)
@Target(FIELD)
public @interface Range {
public int min() default Integer.MIN_VALUE;
public int max() default Integer.MAX_VALUE;
}
@Retention(RUNTIME)
@Target(FIELD)
public @interface RegExp {
public String value() default "^.*$";
}
@Retention(RUNTIME)
@Target(FIELD)
public @interface Required {
}
你想''检查“'等于''一个''和''两个'',还是你的意思是做'||'? –