newInstance: 弱类型。低效率。只能调用无参构造。
new: 强类型。相对高效。能调用任何public构造。
newInstance()是实现IOC、反射、面对接口编程 和 依赖倒置 等技术方法的必然选择,new 只能实现具体类的实例化,不适合于接口编程。
里面就是通过这个类的默认构造函数构建了一个对象,如果没有默认构造函数就抛出InstantiationException, 如果没有访问默认构造函数的权限就抛出IllegalAccessException
在初始化一个类,生成一个实例的时候;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降耦的讨论见如下(非本人观点,仅供参考):
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的区别,而不是>在问工厂模式、类与类之间的耦合之类的东西;
是的,从表面上看好像是偏离,产生这个疑问在于自己还没有对设计模式 或有关Java设计理论有所了解,在工厂模式中,就常常使用newIntance来创建对象,而不是使用new,如下:
Class c = Class.forName(className);
factory = (ForumFactory)c.newInstance();
很多初学者奇怪:为什么这里不直接使用new?用newInstance与用new是区别的,区别在哪里?就在于为什么要使用工厂模式的答案中。
wInstance与用new是区别的,区别在于创建对象的方式不一样,前者是使用类加载机制,那么为什么会有两种创建对象方式?这个就要从可伸缩、可扩展,可重用等软件思想上解释了。
Java中工厂模式经常使用newInstance来创建对象,因此从为什么要使用工厂模式上也可以找到具体答案。
例如:
|
其中AInterface是A的接口,如果下面这样写,你可能会理解:
|
进一步,如果下面写,你可能会理解:
|
上面代码就消灭了A类名称,优点:无论A类怎么变化,上述代码不变,甚至可以更换A的兄弟类B , C , D....等,只要他们继承Ainterface就可以。