请教 newInstance 的用法

我是一个java爱好者,向各位请教一个问题:
比如:
在初始化一个类,生成一个实例的时候;newInstance() 和 new 有什么区别
谢谢大家。

newInstance :一般不会有public的Constructor
new :该类必须有public 的Constructor

newInstance: 弱类型。低效率。只能调用无参构造。
new: 强类型。相对高效。能调用任何public构造。

结论:newInstance只有必须要用(就是new不能用的时候)才用。

> newInstance: 弱类型。低效率。只能调用无参构造。
> new: 强类型。相对高效。能调用任何public构造。
>
> 结论:newInstance只有必须要用(就是new不能用的时候)才
> 谩?>

newInstance 比 new 低藕合,各有各的用法而已。

谈不上什么低耦合。newInstance 不过就是能做动态生成而已。这是reflection的功能,也是唯一的功能。

假如new也可以动态,就没什么区别了,如:new "MyClass"。

我发现不知道为什么,很多人认为reflection可以减少耦合。可能都是指的可以在配置文件里面配置类名字吧。

这在客观上确实达到了降低耦合的目的,但是,实际上,我要说,此处降低耦合的不是reflection,而是那个你cast过去的interface。interface,只有interface,才是推动历史的唯一力量。:->

reflection不过提供了把实现的决定时间延迟到运行时的功能而已。


而其实,即使使用reflection,也应该把它包装在一个抽象工厂中,如此才能隐藏reflection的缺点。而且,抽象工厂可以表达reflection,而reflection不能表达抽象工厂。

举个例子:

不要直接在客户代码中这样写:
MyInterface obj = (MyInterface)Class.forName(theclassname).newInstance();
如此,你就把自己强制绑在reflection上,这也是强耦合的一种。

而是利用抽象工厂:
interface MyInterfaceFactory{
MyInterface newInstance();
}
class ClientCode{
private final MyInterfaceFactory myfactory;
public void f(){
MyInterface obj = myfactory.newInstance();
}
}

这个myfactory是一个抽象工厂对象,它可以通过构造函数注射进来。

然后,可以提供一个使用reflection的工厂实现

class ReflectionFactory implements MyInterfaceFactory{
public MyInterface newInstance(){
return Class.forName(name).newInstance();
}
private final String name;
}
这样,reflection也好,newInstance也好,都是一个工厂实现而已,不会影响整个框架。
这才是低耦合。

懒得长篇大论,随便拿jive举个例子,ForumFactory中的:
String classNameProp = JiveGlobals.getJiveProperty("ForumFactory.className");
Class c = Class.forName(className);
factory = (ForumFactory)c.newInstance();

如果改用new DbForumFactory()那就完蛋了,难道每个想修改jive实现的人都要去反编译再重写ForumFactory?

呵呵。你这个例子,真正起到消除耦合的,正是这个ForumFactory接口,而不是reflection。

不信,可不可以这样?

ForumFactory factory = Factories.getForumFactory();

不行吗?把用reflection的逻辑封装进getForumFactory()不好吗?不比直接使用它灵活?

在getForumFactory()里面,你愿意用reflection也好,或者用其它间接层也好,都是实现细节了。而实现细节是不会影响耦合度的。

我们讨论的是框架,是设计,是分工,不是最终完成的功能。你的反问好像是说:我的功能要求动态生成,我能不用reflection吗?

当然要用,没人不让你用reflection,不过,只有在必须用的时候(在你这个必须动态生成的例子)才用,因为reflection有缺点。

其实,就算用reflection,也有各种用法,你是class.newInstance()?还是在class里面先找到某个构造函数然后调用那个构造函数?还是说再委托给第三方的如spring啦,pico啦来创建对象?(这些库底层也是调用reflection的)

你能说你的newInstance()就是千秋万载永远正确的选择?

而把这些细节封装起来,才能达到减小耦合的效果。

一个检测的办法就是:你试着改变策略,用pico或者直接new,看看要改动的代码有多少。

好像已经偏离了楼主的意图,它是在问newInstance和new的区别,而不是在问工厂模式、类与类之间的耦合之类的东西;

>好像已经偏离了楼主的意图,它是在问newInstance和new的区别,而不是>在问工厂模式、类与类之间的耦合之类的东西;

是的,从表面上看好像是偏离,产生这个疑问在于自己还没有对设计模式或有关Java设计理论有所了解,在工厂模式中,就常常使用newIntance来创建对象,而不是使用new,如下:

 Class c = Class.forName(className);
 factory = (ForumFactory)c.newInstance();

很多初学者奇怪:为什么这里不直接使用new?用newInstance与用new是区别的,区别在哪里?就在于为什么要使用工厂模式的答案中。

楼上已经讨论比较清楚,如果还有疑问,可学习设计模式中最简单最广泛的工厂模式。

补充:

newInstance与用new是区别的,区别在于创建对象的方式不一样,前者是使用类加载机制,那么为什么会有两种创建对象方式?这个就要从可伸缩、可扩展,可重用等软件思想上解释了。

Java中工厂模式经常使用newInstance来创建对象,因此从为什么要使用工厂模式上也可以找到具体答案。

例如:


Class c = Class.forName(“A”);
factory = (AInterface)c.newInstance();

其中AInterface是A的接口,如果下面这样写,你可能会理解:

String className = "A";
Class c = Class.forName(className);
factory = (AInterface)c.newInstance();

进一步,如果下面写,你可能会理解:


String className = readfromXMlConfig;//从xml 配置文件中获得字符串
Class c = Class.forName(className);
factory = (AInterface)c.newInstance();

上面代码就消灭了A类名称,优点:无论A类怎么变化,上述代码不变,甚至可以更换A的兄弟类B , C , D....等,只要他们继承Ainterface就可以。

从jvm的角度看,
我们使用new的时候,这个要new的类可以没有加载;
但是使用newInstance时候,就必须保证:1、这个类已经加载;2、这个类已经连接了。而完成上面两个步骤的正是class的静态方法forName()方法,这个静态方法调用了启动类加载器(就是加载java API的那个加载器)。
有了上面jvm上的理解,那么我们可以这样说,newInstance实际上是把new这个方式分解为两步,即,首先调用class的加载方法加载某个类,然后实例化。
这样分步的好处是显而易见的。我们可以在调用class的静态加载方法forName时获得更好的灵活性,提供给了我们降耦的手段。

以上是我个人的理解,不知道对不对?请各位前辈指教!

我想应该是:newInstance是单态(Singleton)的用法

历经风雨之后,才明白这句java真谛“只有interface,才是推动历史的唯一力量。”

ajoo兄圣贤。

这里的
factory = (AInterface)c.newInstance();
其中factory是什么类型的的对象啊,难道只能是AInterface型的?
哪位给解释一下啊!谢谢!

不过,只有在必须用的时候(在你这个必须动态生成的例子)才用,因为reflection有缺点。
能否请教reflection的缺点都有什么,并且它致命的原因是什么????