我在旧项目中找到了这段代码
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();
答案 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的实现。要知道原因,为什么要这样做,你可以看看这个逻辑是如何使用的。