1.直接new,調用了構造器
2.經過clone(),沒有調用構造器
3.經過反射,調用了構造器
4.經過反序列化,沒有調用構造器
5.經過Unsafe類的allocateInstance()方法,沒有調用構造器java
public class CreateByNew { public CreateByNew() { System.out.println("調用了構造..."); } public static void main(String[] args) { CreateByNew c1 = new CreateByNew(); CreateByNew c2 = new CreateByNew(); System.out.println(c1 == c2);//false }}
輸出:bash
調用了構造... 調用了構造... false
須要實現Cloneable接口,可分爲深克隆和淺克隆。clone()後的新對象會複製原對象的屬性,可是並不會調用構造函數。app
public class CreateByClone implements Cloneable { public int temp; public CreateByClone() { System.out.println("調用了構造.."); } public static void main(String[] args) throws CloneNotSupportedException { CreateByClone c1 = new CreateByClone(); c1.temp = 222; CreateByClone c2 = (CreateByClone) c1.clone(); System.out.println(c2.temp); System.out.println(c1 == c2); }}
輸出:ide
調用了構造.. 222 false
反射建立對象:函數
class.newInstance():調用了無參構造
獲取對應的Constructor,調用constructor的newInstance(),調用對應構造函數建立對象this
public class CreateByReflection { private int temp; public int getTemp() { return temp; } public CreateByReflection() { System.out.println("調用了空參構造..."); } public CreateByReflection(int temp) { this.temp = temp; System.out.println("調用了帶參構造..."); } public static void main(String[] args) throws Exception { Class clazz = CreateByReflection.class; //經過無參構造反射建立 CreateByReflection c1 = (CreateByReflection) clazz.newInstance(); //經過帶參構造反射建立 Constructor constructor = clazz.getDeclaredConstructor(int.class); CreateByReflection c2 = (CreateByReflection) constructor.newInstance(10); System.out.println(c2.getTemp()); System.out.println(c1 == c2); }}
輸出:spa
調用了空參構造... 調用了帶參構造... 10 false
須要被序列化的對象實現Serializable接口,不會調用構造,反序列化回來的對象的屬性值與序列化以前一致,可是是一個新對象。code
public class CreateBySerializable { public static void main(String[] args) { Person p1 = new Person("二狗", 18); writeObject(p1); Person p2 = readObjcet(); System.out.println(p2); System.out.println(p1 == p2); } public static void writeObject(Person person) { FileOutputStream fileOut = null; ObjectOutputStream out = null; try { fileOut = new FileOutputStream("person.txt"); out = new ObjectOutputStream(fileOut); out.writeObject(person); System.out.println("Serialized data is saved"); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally { try { out.close(); } catch (IOException e) { e.printStackTrace(); } try { fileOut.close(); } catch (IOException e) { e.printStackTrace(); } } } public static Person readObjcet() { Person temp = null; FileInputStream fileIn = null; ObjectInputStream in = null; try { fileIn = new FileInputStream("person.txt"); in = new ObjectInputStream(fileIn); temp = (Person) in.readObject(); System.out.println("Deserialized Person..."); return temp; } catch (Exception e) { e.printStackTrace(); return null; }finally { try { in.close(); } catch (IOException e) { e.printStackTrace(); } try { fileIn.close(); } catch (IOException e) { e.printStackTrace(); } } }}class Person implements Serializable { public Person() { System.out.println("調用了空參構造..."); } public Person(String name, int age) { this.name = name; this.age = age; System.out.println("調用了帶參構造..."); } public String name; public int age; @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}'; }}
輸出:orm
調用了帶參構造...Serialized data is saved Deserialized Person...Person{name='二狗', age=18}false
Unsafe類經過native方法直接操做內存分配空間,建立對象。此時對象並無執行構造,只是在內存中分配了空間,全部屬性此時都是對應類型的0值。並且該對象並不被JVM管理,須要咱們本身回收。對象
Unsafe類的構造爲私有,且經過@CallerSensitive方法保證只有BootStrap類加載器加載的類才能夠調用Unsafe類中的方法。
因此只能經過反射獲取Unsafe類實例。
public class CreateByUnsafe { public static void main(String[] args) throws Exception { //基於反射獲取Unsafe實例 Field field = Unsafe.class.getDeclaredField("theUnsafe"); field.setAccessible(true); Unsafe unsafe = (Unsafe) field.get(null); People p1 = (People) unsafe.allocateInstance(People.class); People p2 = (People) unsafe.allocateInstance(People.class); p1.age = 18; System.out.println(p1); System.out.println(p1 == p2); //返回成員變量在內存中的地址相對於對象內存地址的偏移量 Field f = People.class.getDeclaredField("age"); long offset = unsafe.objectFieldOffset(f); System.out.println(offset);//12 // markword:8bytes(64bits) + class pointer:4bytes(32bits) == 12 bytes }}class People { public int age; @Override public String toString() { return "People{" + "age=" + age + '}'; }}
輸出:
People{age=18} false 12