五種方法創(chuàng)建java對象,你知道幾種呢?
五種方法創(chuàng)建java對象
作為Java開發(fā)人員,我們通常每天都會創(chuàng)建許多對象,但是我們總是使用新的或依賴管理系統(tǒng)(例如Spring)來創(chuàng)建這些對象。但是,有更多方法可以創(chuàng)建本文中將要研究的對象。
用Java創(chuàng)建對象的共有5種核心方式,下面將以其示例加以說明,然后介紹創(chuàng)建對象的行的字節(jié)碼。但是,有很多API可以為我們創(chuàng)建對象,但是這些API還將間接使用這5種核心方式之一,例如Spring BeanFactory。

如果您將執(zhí)行最后給出的程序,則會看到方法1、2、3使用構(gòu)造函數(shù)創(chuàng)建對象,而4、5沒有調(diào)用構(gòu)造函數(shù)創(chuàng)建對象。
1、使用新關(guān)鍵字
這是創(chuàng)建對象的最常見和常規(guī)的方法,也是一種非常簡單的方法。通過使用此方法,我們可以調(diào)用要調(diào)用的任何構(gòu)造函數(shù)(無參數(shù)的構(gòu)造函數(shù)和參數(shù)化的)。
Employee?emp1?=?new?Employee();
2.使用Class類的newInstance()方法
我們還可以使用Class類的newInstance()方法創(chuàng)建一個對象。此newInstance()方法調(diào)用no-arg構(gòu)造函數(shù)來創(chuàng)建對象。
我們可以通過newInstance()通過以下方式創(chuàng)建對象:
Employee?emp2?=?(Employee)?Class.forName("org.programming.mitra.exercises.Employee").newInstance();
Or
Employee?emp2?=?Employee.class.newInstance();
3.使用構(gòu)造方法類的newInstance()方法
與Class類的newInstance()方法類似,java.lang.reflect.Constructor類中有一個newInstance()方法可用于創(chuàng)建對象。我們還可以使用此newInstance()方法來調(diào)用參數(shù)化構(gòu)造函數(shù)和私有構(gòu)造函數(shù)。
Constructor?constructor?=?Employee.class.getConstructor();
Employee?emp3?=?constructor.newInstance();
這兩種newInstance()方法都被稱為創(chuàng)建對象的反射方式。實(shí)際上,Class類的newInstance()方法在內(nèi)部使用了Constructor類的newInstance()方法。這就是為什么最好使用后一種方法,并且也將其用于諸如Spring,Hibernate,Struts等不同框架的原因。要了解這兩種newInstance()方法之間的區(qū)別,請閱讀使用Example在Java中通過Reflection創(chuàng)建對象。
4.使用clone()方法:
每當(dāng)我們在任何對象上調(diào)用clone()時,JVM實(shí)際上都會為我們創(chuàng)建一個新對象,并將先前對象的所有內(nèi)容復(fù)制到其中。使用clone方法創(chuàng)建對象不會調(diào)用任何構(gòu)造函數(shù)。
要在對象上使用clone()方法,我們需要實(shí)現(xiàn)Cloneable并在其中定義clone()方法。
Employee?emp4?=?(Employee)?emp3.clone();
Java克隆是Java社區(qū)中最值得探討的話題,它的確有其缺點(diǎn),但是在對象完全滿足Java克隆的強(qiáng)制條件之前,它仍然是創(chuàng)建任何對象的副本的最流行和最簡單的方法。
5.使用反序列化
每當(dāng)我們序列化然后反序列化一個對象時, JVM就會為我們創(chuàng)建一個單獨(dú)的對象。在反序列化中,JVM不使用任何構(gòu)造函數(shù)來創(chuàng)建對象。要反序列化對象,我們需要在類中實(shí)現(xiàn)Serializable接口。
ObjectInputStream?in?=?new?ObjectInputStream(new?FileInputStream("data.obj"));
Employee?emp5?=?(Employee)?in.readObject();
正如我們在上面的字節(jié)碼中看到的那樣,所有四個方法調(diào)用都轉(zhuǎn)換為invokevirtual(這些方法直接處理對象的創(chuàng)建),除了第一個轉(zhuǎn)換為兩個調(diào)用的方法是一個是新的,另一個是調(diào)用特殊的(對構(gòu)造函數(shù)的調(diào)用)。
例:
讓我們考慮一個我們要為其創(chuàng)建對象的Employee類:
class?Employee?implements?Cloneable,?Serializable?{
????private?static?final?long?serialVersionUID?=?1L;
????private?String?name;
????public?Employee()?{?System.out.println("Employee?Constructor?Called...");?}
????public?String?getName()?{?return?name;?}
????public?void?setName(String?name)?{?this.name?=?name;?}
????@Override
????public?boolean?equals(Object?o)?{
????????if?(this?==?o)?return?true;
????????if?(o?==?null?||?getClass()?!=?o.getClass())?return?false;
????????Employee?employee?=?(Employee)?o;
????????return?Objects.equals(name,?employee.name);
????}
????@Override
????public?int?hashCode()?{?return?Objects.hash(name);?}
????@Override
????public?String?toString()?{?return?String.format("Employee{name='%s'}",?name);?}
????@Override
????public?Object?clone()?{
????????Object?obj?=?null;
????????try?{
????????????obj?=?super.clone();
????????}?catch?(CloneNotSupportedException?e)?{
????????????e.printStackTrace();
????????}
????????return?obj;
????}
}
在下面的Java程序中,我們將以所有5種方式創(chuàng)建Employee對象。
public?class?ObjectCreation?{
????public?static?void?main(String...?args)?throws?Exception?{
????????//?1.?Using?new?keyword
????????Employee?emp1?=?new?Employee();
????????emp1.setName("emp1");
????????//?2.?Using?Class?class's?newInstance()?method
????????Employee?emp2?=?Employee.class.newInstance();
????????emp2.setName("emp2");
????????//?3.?Using?Constructor?class's?newInstance()?method
????????Constructor?constructor?=?Employee.class.getConstructor();
????????Employee?emp3?=?constructor.newInstance();
????????emp3.setName("emp3");
????????//?4.?Using?clone()?method
????????Employee?emp4?=?(Employee)?emp3.clone();
????????emp4.setName("emp4");
????????//?Serialization
????????try?(ObjectOutputStream?out?=?new?ObjectOutputStream(new?FileOutputStream("data.obj")))?{
????????????out.writeObject(emp4);
????????}
????????//?5.?Using?Deserialization
????????Employee?emp5;
????????try?(ObjectInputStream?in?=?new?ObjectInputStream(new?FileInputStream("data.obj")))?{
????????????emp5?=?(Employee)?in.readObject();
????????????emp5.setName("emp5");
????????}
????????System.out.println(emp1?+?",?hashcode?:?"?+?emp1.hashCode());
????????System.out.println(emp2?+?",?hashcode?:?"?+?emp2.hashCode());
????????System.out.println(emp3?+?",?hashcode?:?"?+?emp3.hashCode());
????????System.out.println(emp4?+?",?hashcode?:?"?+?emp4.hashCode());
????????System.out.println(emp5?+?",?hashcode?:?"?+?emp5.hashCode());
????}
}
該程序?qū)⒔o出以下輸出:
Employee?Constructor?Called...
Employee?Constructor?Called...
Employee?Constructor?Called...
Employee{name='emp1'},?hashcode?:?3117192
Employee{name='emp2'},?hashcode?:?3117193
Employee{name='emp3'},?hashcode?:?3117194
Employee{name='emp4'},?hashcode?:?3117195
Employee{name='emp5'},?hashcode?:?3117196