,首先我要指出,你的代碼中有一個錯誤:
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 {
}
你想''檢查「'等於''一個''和''兩個'',還是你的意思是做'||'? –