我已经在我的应用程序中添加了一个人类可读的配置文件,java.util.Properties
并尝试在其周围添加包装以使类型转换更容易.具体来说,我希望返回的值从提供的默认值"继承"它的类型.这是我到目前为止所得到的:
protected <T> T getProperty(String key, T fallback) {
String value = properties.getProperty(key);
if (value == null) {
return fallback;
} else {
return new T(value);
}
}
Run Code Online (Sandbox Code Playgroud)
getProperty("foo", true)
无论是从属性文件中读取还是类似于字符串,整数,双精度和c,返回值都将是一个布尔值.当然,上面的代码段实际上并没有编译:
PropertiesExample.java:35: unexpected type
found : type parameter T
required: class
return new T(value);
^
1 error
Run Code Online (Sandbox Code Playgroud)
我做错了,还是我只是想做一些无法做到的事情?
编辑:用法示例:
// I'm trying to simplify this...
protected void func1() {
foobar = new Integer(properties.getProperty("foobar", "210"));
foobaz = new Boolean(properties.getProperty("foobaz", "true"));
}
// ...into this...
protected void func2() {
foobar = getProperty("foobar", 210);
foobaz = getProperty("foobaz", true);
}
Run Code Online (Sandbox Code Playgroud)
Pau*_*ora 13
由于类型擦除,您无法实例化通用对象.通常,您可以保留对Class
表示该类型的对象的引用并使用它来调用newInstance()
.但是,这仅适用于默认构造函数.由于您要使用带参数的构造函数,因此您需要查找该Constructor
对象并将其用于实例化:
protected <T> T getProperty(String key, T fallback, Class<T> clazz) {
String value = properties.getProperty(key);
if (value == null) {
return fallback;
} else {
//try getting Constructor
Constructor<T> constructor;
try {
constructor = clazz.getConstructor(new Class<?>[] { String.class });
}
catch (NoSuchMethodException nsme) {
//handle constructor not being found
}
//try instantiating and returning
try {
return constructor.newInstance(value);
}
catch (InstantiationException ie) {
//handle InstantiationException
}
catch (IllegalAccessException iae) {
//handle IllegalAccessException
}
catch (InvocationTargetException ite) {
//handle InvocationTargetException
}
}
}
Run Code Online (Sandbox Code Playgroud)
但是,看到实现这一目标有多麻烦,包括使用反射的性能成本,首先要考虑其他方法.
如果你绝对需要走这条路,如果T
仅限于一组不同的在编译时已知的类型,一个折衷办法是保持静态Map
的Constructor
s,这是在启动时加载-这样你就不必动态每次调用此方法时都要查看它们.例如a Map<String, Constructor<?>>
或Map<Class<?>, Constructor<?>>
,使用静态块填充.
归档时间: |
|
查看次数: |
9664 次 |
最近记录: |