返回Class.forName而不是新实例

时间:2015-09-28 07:31:31

标签: java reflection factory

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

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();

3 个答案:

答案 0 :(得分:4)

不同之处在于new AireBatchDaoFactory将创建特定类的实例(如果AireBatchDaoFactory是接口或抽象类,则不编译)。但是factory可能包含实现AireBatchDaoFactory任何类的完全限定名称(如果它是一个接口)或它的子类(如果它是' sa)类)。 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"

答案 1 :(得分:2)

仔细查看方法

Eg:- $myvariable = 'C:/user/username/desktop/filename';

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

getFactory(String factory)

哪里

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

有效。

简而言之,您正在使用它的名称为类创建一个实例,您不能在编译时使用反射在传递时使用传递名称创建实例。

答案 2 :(得分:1)

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

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