繁体   English   中英

返回Class.forName而不是新实例

[英]return Class.forName instead of new instance

我在一个旧项目中找到了这段代码

public abstract class AireBatchDaoFactory {
     public static final String ORACLE_FACTORY = "airebatch.oracle.OracleDaoFactory";
     public static AireBatchDaoFactory getFactory(String factory) throws SQLException
     {
        try {
           return (AireBatchDaoFactory) Class.forName(factory).newInstance();
        } 
        catch (Exception e) {
            throw new SQLException("error msg");
        }
     }
     public abstract AireBatchDao getAireBatchDao() throws SQLException;}

我想了解两者之间的具体区别

return (AireBatchDaoFactory) Class.forName(factory).newInstance();

return new AireBatchDaoFactory();

不同之处在于, new AireBatchDaoFactory将创建该特定类的实例(如果AireBatchDaoFactory是接口或抽象类,则不会编译)。 但是factory可以包含实现AireBatchDaoFactory (如果是接口)或对其进行子类化(如果是类)的任何类的全限定名称。 Class.forName(factory).newInstance()将加载由factory命名的类,并为其创建一个新实例。

对于代码库的运行时插件,这是相当常见的模式。 通常,您定义插件实现的接口。 然后,您提供一种运行时方法,用于指定要使用的特定类(在属性文件中,某些其他配置等中),并使用Class.forName加载类并使用newInstance创建它的实例。 由于该类是在运行时决定的,因此使用它的代码的作者可能在编写使用它的代码之后很长时间才编写过它。 因此,将其用于插件。

考虑:

Plugin.java

interface Plugin {
    void doSomething();
}

Foo.java

public class Foo implements Plugin {
    public void doSomething() {
        System.out.println("I'm Foo");
    }
}

Bar.java

public class Bar implements Plugin {
    public void doSomething() {
        System.out.println("I'm Bar");
    }
}

App.java

public class App {

    public static final void main(String[] args) {
        try {
            String classToLoad = args[0];
            Plugin plugin = Class.forName(classToLoad).newInstance();
            plugin.doSomething();
        }
        catch (Exception e) {
            //...handle error...
        }
    }
}

跑步

java App Foo

...加载Foo类并在其上调用doSomething ,使我们得到"I'm Foo"

跑步

java App Bar

...加载Bar类,并在其上调用doSomething ,使我们得到"I'm Bar"

仔细看方法

getFactory(String factory)

您正在接收类名称作为参数。 你不能写

factory factory = new factory(); // error.

哪里

 Class.forName(factory).newInstance();

已验证。

简而言之,您将使用您在编译时未使用的类的名称为该类创建一个实例,并在运行时使用Reflection使用传递的名称创建该实例。

您不能为抽象类调用new AireBatchDaoFactory() 在您的示例中,反射用于获取具有名称的类的实例,该名称作为getFactory方法的参数传递。 此类应扩展AireBatchDaoFactory抽象类。

在这种情况下,您可以更改在运行时从AireBatchDaoFactory获得的实现。 要知道为什么这样做,您可以看看如何使用此逻辑。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM