1,new
Student s = new Student();
在堆儲存區開辟了一塊空間,其對象的引用存儲在棧存儲區上。
2,反射 reflect
java的反射機制是指,在運行狀態中,對於任意一個類,我們可以獲取這個類的屬性和方法,對於任意一個對象,我們可以調用這個對象的方法和屬性。這種動態獲取信息和動態調用對象的方法就是java 的反射機制。
Class 類,每個class 都會有一個Class對象,當我們完成一個類通過編譯之后,就會生成一個.class 文件,在生成的.class 文件中,就會有個Class 對象,用於表示這個類的類型信息。
獲得類的Class 對象的3中方法:
1,類名.class (任意數據類型,都會有一個class 屬性)
2,Class.forName("java.lang.String"); 類的全路徑
3,類的實例化對象下,有getClass() 方法。
反射創建對象:
不存在有參的構造函數:
方法1:
類名.class.newInstance(); 就算沒有構造方法,也會調用默認的無參構造方法
Demo newInstance = Demo.class.newInstance();
newInstance.setUserName("chris");
newInstance.setPassword("12345");
System.out.println(newInstance.getUserName()+ newInstance.getPassword());
方法2:
和方法1本質相同,一個是使用類名.class ,一個是使用Class.forName("類的全路勁")來獲取類的類對象,再通過newInstance()方法創建對象。
Class<Demo> clazz = (Class<Demo>) Class.forName("Demo");
Demo newInstance2 = clazz.newInstance();
newInstance2.setPassword("12345");
newInstance2.setUserName("Sarah");
System.out.println(newInstance2.getUserName()+ newInstance2.getPassword());
存在有參的構造函數:
先獲取類的Class 對象,通過類對象獲取到指定的構造器,可以是有參,可以是無參,通過指定的構造器,創建對象
Class<Demo> clazz3 = (Class<Demo>) Class.forName("Demo");
Constructor<Demo> con = clazz3.getDeclaredConstructor(String.class,String.class);
Demo newInstance3 = con.newInstance("Mike","12345");
//newInstance3.setUserName("vincent");可以通過反射是可以改變對象的值
//newInstance3.setPassword("12345");
System.out.println(newInstance3.getUserName()+ newInstance3.getPassword());
Class對象獲取構造器比較:
Constructor<Demo> con = clazz3.getDeclaredConstructor(String.class,String.class); //能獲取到指定參數的構造器,和訪問修飾符無關,private,public 所有的可以獲取到
Constructor<?>[] conn = clazz4.getConstructors();//所有public 修飾的構造器
Constructor<Demo> connn = clazz5.getConstructor(String.class,String.class);//所有public 修飾的帶參數的指定構造器
反射的應用場景:
jdbc的連接
Class.forName("com.mysql.jdbc.Driver")
springIOC反射創建對象
mybatis
3,clone
調用clone,jvm就會創建一個新的對象,將前面對象的內容全部拷貝進去。用clone方法創建對象並不會調用任何構造函數。
前提,必須要實現Cloneable 接口,本地實現 protected native Object clone() throws CloneNotSupportedException;
Demo clone = (Demo) newInstance.clone();
4,反序列化
序列化:將堆內存中的java 對象通過某種方式,存儲到磁盤上或者傳輸給其他網絡節點,也就是java對象轉成二進制。
反序列化:與序列化相反,再將序列化之后的二進制串再轉成數據結構或對象。
為什么需要做序列化?
1,網絡節點的傳輸,java 對象需要轉成二進制串。
2,服務器鈍化:如果在內存中,一個對象長時間沒有被調用,就會將其序列化存儲在本地磁盤上,有需要活動的時候,就會現在內存中尋找,找不到,會將磁盤上的二進制再次反序列化成java 對象。可以節省服務器內存。
實現序列化?
1,需要做序列化的對象的類,必須實現序列化接口:Java.lang.Serializable 接口
通過反序列化創建對象。
//本地創建a.txt 文件,並且把對象序列化轉成二進制寫進文件中
File f = new File(String path)
OutputStream op = new FileOutputStream(file);
ObjectOutputStream ops = new ObjectOutputStream(op);
ops.writeObject(new Demo("Chris", "12345"));
ops.close();
//從寫進的文件中,讀取二進制串,用對象流將其讀出
InputStream in = new FileInputStream(file);
ObjectInputStream os = new ObjectInputStream(in);
Demo d = (Demo) os.readObject();
System.out.println(d.getUserName()+ d.getPassword());
os.close();
反序列化 請注意深復制和淺復制