MyInterface intf = (MyInterface) Class.forName(className).newInstance();
我有一段代码,它将使用上述调用按需创建新接口并调用某种方法。所有的实现类通常都包含许多final static
变量和静态初始化代码,我想在其生命周期中只触发一次。
但是由于我正在使用newInstance()调用,所以我觉得旧对象得到GCed并且类再次被初始化,因此所有静态变量都被初始化。
为了避免这种情况,我想把它放在一个缓存中,这样这些类就不会再次重构,因此在它的生命周期内会被初始化一次。 (注意:我的接口是线程安全的。)
我应该把它放在Hashtable
中,然后查一下,还是有更好的方法来处理缓存?
答案 0 :(得分:6)
所有实现类 通常包含大量的最终静态 变量和静态初始化 我想要解雇的代码 一生一次。
但是因为我正在使用newInstance() 打电话,我的印象是 旧对象得到了GCed和类 再次初始化,因此所有的 静态变量。
不,这不是真的。静态字段和静态块只运行一次 - 加载类时。因此,重复创建实例不会重新运行它们。此外,他们不会被垃圾收集。因此,您不必担心静态字段被GCed并重复重新创建: - )。
附加说明:
以上仅适用于仅使用默认类加载器的情况。如果您使用多个类加载器并卸载类加载器,那么它加载的所有类以及它们的静态字段将符合GC的条件。此外,静态字段存在每个类加载器,而不仅仅是每个类,因此如果使用不同的类加载器加载相同的类,静态初始化将确实运行多次。但这可能不适合你...
另见这里的讨论:
答案 1 :(得分:3)
如果我理解正确,你需要创建类的新实例,并且你想确保一些初始化代码只执行一次,而不是每次调用newInstance()
。我认为如果你把初始化代码放在一个静态部分,那么你很好:AFAIK静态初始化程序块中的代码在加载类时由虚拟机执行一次。另请参阅此question。
答案 2 :(得分:2)
这样的事情怎么样:
private static Map<String, Object> cache =
new ConcurrentHashMap<String, Object>();
@SuppressWarnings("unchecked")
public static <T> T getImplementation(final String implementationClass){
T result;
synchronized(cache){
result = (T) cache.get(implementationClass);
if(result == null){
try{
result =
(T) Class.forName(implementationClass).newInstance();
} catch(final Exception e){
// error handling here
}
cache.put(implementationClass, result);
}
}
return result;
}
这将保证每个类只使用一个实例(只要你只使用这个方法)
使用示例:
FooService service = getImplementation("com.mycompany.FooServiceImpl");
使用Guava,可以改进此代码with a Computing Map:
private static Map<String, Object> cache =
new MapMaker().makeComputingMap(
new Function<String, Object>(){
@Override
public Object apply(final String input){
try{
return Class.forName(input).newInstance();
} catch(final Exception e){
// error handling here
}
}
});
@SuppressWarnings("unchecked")
public static <T> T getImplementation(final String implementationClass){
return (T) cache.get(implementationClass);
}
答案 3 :(得分:2)
这个怎么样。
static final Map<String, Object> instances = new HashMap<String, Object>();
public static Object getInstance(String name) {
if (name == null) {
return null;
}
Object obj = null;
synchronized (ClassName.class) {
try {
obj = instances.get(name);
if (obj == null) {
obj = Class.forName(name).newInstance();
instances.put(name, obj);
}
} catch (ClassNotFoundException e) {
} catch (InstantiationException e) {
} catch (IllegalAccessException e) {
}
}
return obj;
}
答案 4 :(得分:1)
答案 5 :(得分:0)
这称为Singleton。
使用这种模式,你的班级只有一个实例。
有一些例外,但是对于大多数目的,你只有一个实例。