I use this code and it works quite good for me (only partial code, coding from memory..):
(This is used in conjunction with the Properties class of java, but it makes it easier to add properties and keep your property file template in sync.)
to use:
Date date = Conf.value(Prop.SOME_DATE,Date.class);
and
enum Prop {
SOME_DATE(Date.class, "2009-10-28", "Some date"){
Object parse(String value){
return new Date(value);
}};
private final Class<?> type;
private final String description;
private final Object default;
Properties(Class<?> type, String defaultValue, String desc){
this.type = type;
this.description = desc;
this.default = this.parse(defaultValue);
}
abstract Object parse(String value);
}
and
class Conf {
private static final String PROP_FILE_NAME = "some.properties";
private volatile Map<Prop,Object> store;
public void load(){
//Read from property file and use default if not given.
//I code it in a way that it will not permit null as value, so
//if default is null the user is forced to provide setting.
}
public <T> T value(Prop prop, Class<T> clazz){
return (T)this.store.get(prop);
}
public static void main(String[] args){
//code to autogenerate property file
//Something like:
//#Default : 2009-10-28 Description : Some date. Type:Date
//#SOME_DATE=2009-10-28
}
}
The class argument makes the method a little verbose, but sometimes it is irritating if you can only let java infer the type, like this:
CountDownLatch latch = Conf.value(Prop.SOME_INTEGER);
//Compilation error! Since it expects int and won't unbox.
CountDownLatch latch = Conf.value(Prop.SOME_ITEGER,Integer.class);
//Verbose, but works everytime. Of course you could get a
//ClassCastException, but you should notice that early
//in the development...