使用反射

时间:2015-08-11 07:07:49

标签: java exception if-statement reflection classloader

我正在尝试使用下面代码中给出的方法Class.forname("classname")通过反射动态加载类。

Class<? extends Layout> layoutClassName;
try {
    layoutClassName = (Class<? extends Layout>)   Class.forName(site.getSiteLayout());
} catch (ClassNotFoundException e) {
    layoutClassName= DefaultLayout.class;
}

我正在尝试动态加载一个类,如果它是由登录用户(db配置)定义的,否则提供默认实现。

这很好用,但经过统计分析后,我们发现大约有80%的时间是使用默认实现。

这意味着大约80%的时间都会创建一个Exception对象。由于创建异常对象很重,我想避免它并使用其他逻辑来识别类是否存在。

请建议。

PS:我不是在寻求任何显着的性能提升,我只是想清理我现有的代码。

2 个答案:

答案 0 :(得分:1)

正如你所说......

  

如果在配置

中定义了类,我试图动态加载它

是否在某个文件中提到了“配置”。

我希望你能掌握配置文件(或配置状态),并且只为类创建对象,并且只有在提到时才这样做。如果不应用默认实现。

如果你无法访问配置,我担心据我所知,没有别的方法。

答案 1 :(得分:1)

我不知道是否有一种方便的方法可以检查是否存在类,而不会抛出ClassNotFoundException这种情况适用于一般情况。

在这种情况下,处理ClassNotFoundException似乎是恰当和明确的。所有建议处理异常的早期问题都有:123

但如果你真的想:

  • 动态加载布局(因此,您无法避免反射);
  • 通过不受限制的类名加载布局(如果您没有配置,则无法构建所有布局类的已定义且相对稳定的列表);
  • 出于某种原因最小化ClassNotFoundException

然后我可以建议缓存布局类。如果您没有大量不同的布局,这样的事情可能会起作用:

private HashMap<String, Class<? extends List>> layoutsByName  = new HashMap<>();

public Class<? extends Layout> getLayout(String name) {
    Class<? extends Layout> layoutClass = layoutsByName.get(name);
    if(layoutClass!=null) {
        return layoutClass;
    }
    layoutClass = getLayoutUsingReflection(name);
    layoutsByName.put(name, layoutClass);
    return layoutClass;
}

private Class<? extends Layout> getLayoutUsingReflection(String name) {
    try {
        return (Class<? extends Layout>) Class.forName(name);
    } catch (ClassNotFoundException e) {
        return DefaultLayout.class;
    }
}

这样您就不会两次检查相同的布局。