一.類的加載機制java
jvm把class文件加載到內存,並對數據進行校驗、解析和初始化,最終造成jvm能夠直接使用的java類型的過程。
(1)加載
將class文件字節碼內容加載到內存中,並將這些靜態數據轉換成方法區中的運行時數據結構,在堆中生成一個表明這個類的java.lang.Class對象,做爲方法區類數據的訪問入口。安全
(2)連接 將java類的二進制代碼合併到jvm的運行狀態之中的過程。數據結構
(3)初始化
初始化階段是執行類構造器方法的過程。類構造器方法是由編譯器自動收集類中的全部類變量的賦值動做和靜態語句塊(static塊)中的語句合併產生的。
當初始化一個類的時候,若是發現其父類尚未進行過初始化,則須要先初始化其父類的初始化
虛擬機會保證一個類的構造器方法在多線程環境中被正確加鎖和同步
當訪問一個java類的靜態域時,只有真正聲明這個靜態變量的類纔會被初始化。
二.java反射機制多線程
通俗地說:反射就是將Student類中的方法、成員變量、構造方法,抽象出來可讓Class的對象單獨進行訪問。
JAVA反射機制是在運行狀態中,對於任意一個類,都可以知道這個類的全部屬性和方法;對於任意一個對象,都可以調用它的任意一個方法和屬性;
這種動態獲取的信息以及動態調用對象的方法的功能稱爲java語言的反射機制。
jvm
一、獲取Class對象的三種方式學習
(1)經過調用forName(String className),注意className的格式爲:包名.類名得到Class對象。this
(2)經過類獲取Class對象,String.class、int.class這些字節碼是Class類的對象。spa
(3)經過類的對象獲取Class對象。線程
1 public static void getClass1() throws ClassNotFoundException { 2 //獲取Class的方法 3 //正射 4 Student stu=new Student(); 5 //第一種(優先選擇):傳的是包名.類名,經過包名和類名得到反射Class 6 Class cl1=Class.forName("day20.Student"); 7 //第二種:經過類來獲取Class對象 8 Class cl2=Student.class; 9 //第三種:經過對象獲取Class對象 10 Student s=new Student(); 11 Class cl3=s.getClass(); 12 //判斷三種方法是不是同一個Class對象 13 System.out.println(cl1==cl2); 14 System.out.println(cl2==cl3); 15 16 }
二、獲取構造方法3d
(1)獲取公開的構造方法
(2)獲取全部的構造方法
主要爲調取Student類中的私有方法。注意:不能得到Student類的父類Human中的構造方法。
(3)調用特定的構造方法
無參構造和有參構造方法Constructors1.newInstance();//實例化獲取的類
私有構造方法的調用,要注意要設置其訪問權限Constructors1.setAccessible(true)。
1 public static void getConstruction() throws Exception { 2 //獲取構造方法 3 Class cl=Class.forName("day20.Student"); 4 System.out.println("==========公開的構造方法=========="); 5 //得到公開的構造方法 6 Constructor[] cons=cl.getConstructors(); 7 for(Constructor con:cons) { 8 System.out.println(con); 9 } 10 System.out.println("==========全部的構造方法=========="); 11 //得到全部的構造方法 12 Constructor[] constructors=cl.getDeclaredConstructors(); 13 for (Constructor con:constructors 14 ) { 15 System.out.println(con); 16 } 17 System.out.println("==========調用構造方法=========="); 18 //調用無參構造方法 19 Constructor constructors1=cl.getConstructor(); 20 Student student=(Student)constructors1.newInstance(); 21 //調用有參構造方法 22 Constructor constructors2=cl.getConstructor(String.class); 23 Student student1=(Student) constructors2.newInstance("英語"); 24 //調用私有構造方法 25 Constructor constructors3=cl.getDeclaredConstructor(int.class); 26 constructors3.setAccessible(true);//由於是私有化的方法,因此要設置訪問權限 27 Student student2=(Student) constructors3.newInstance(2); 28 }
執行結果:
==========公開的構造方法========== |
三、獲取方法
私有屬性的調用,要注意要設置其訪問權限Constructors1.setAccessible(true)。
1 private static void getMethod1() throws Exception { 2 Class cl=Class.forName("day20.Student"); 3 //獲取全部公開的方法,包括Object中的類 4 Method[] method=cl.getMethods(); 5 for (Method m:method 6 ) { 7 System.out.println(m.getName()); 8 } 9 //獲取本類中全部的方法,不包括父類和eObject 10 System.out.println("==========私有方法=========="); 11 Method[] methods=cl.getDeclaredMethods(); 12 for (Method ms:methods 13 ) { 14 System.out.println(ms.getName()); 15 } 16 //調取方法 17 System.out.println("==========調取特有方法=========="); 18 //獲取非靜態的無參方法 19 Method method1=cl.getMethod("eat"); 20 //獲取Student類的成員 21 Constructor constructor=cl.getConstructor(); 22 Student student=(Student)constructor.newInstance(); 23 method1.invoke(student); 24 //獲取非靜態含參方法 25 Method method2=cl.getMethod("study", String.class); 26 method2.invoke(student,"物理"); 27 //獲取靜態無參方法 28 Method method3=cl.getMethod("sleep"); 29 method3.invoke(null); 30 //獲取靜態含參方法 31 try { 32 Method method4=cl.getMethod("saveMoney", double.class); 33 method4.setAccessible(true); 34 method4.invoke(null,100.0); 35 }catch (NoSuchMethodException e){ 36 e.getMessage(); 37 }catch(Exception e){ 38 e.getMessage(); 39 } 40 41 }
執行結果:
getName |
四、獲取屬性
1 private static void getAttribute1() throws Exception{ 2 Class cl=Class.forName("day20.Student"); 3 //獲取全部屬性 4 Field[] fields=cl.getFields(); 5 for (Field field:fields 6 ) { 7 System.out.println("屬性值有:"+field.getName()); 8 } 9 //獲取私有化屬性 10 Field field=cl.getDeclaredField("money"); 11 field.setAccessible(true); 12 //獲取Student類的成員 13 Constructor constructor=cl.getConstructor(); 14 Student student=(Student)constructor.newInstance(); 15 student.setMoney(100); 16 System.out.println("經過對象.方法進行屬性賦值:"+student.getMoney()); 17 field.set(student,200); 18 System.out.println("經過Field對象.方法進行賦值:"+student.getMoney()); 19 }
執行結果:
屬性值有:name |
Student類和父類
1 package day20; 2 3 public class Student extends Human{ 4 public String name; 5 int age; 6 private double money; 7 8 public Student() { 9 System.out.println("無參構造方法"); 10 } 11 public Student(String subject) { 12 System.out.println("有參構造方法"+subject); 13 } 14 15 private Student(int i) { 16 System.out.println("私有構造方法"+i); 17 } 18 public String getName() { 19 return name; 20 } 21 public void setName(String name) { 22 this.name = name; 23 } 24 public int getAge() { 25 return age; 26 } 27 public void setAge(int age) { 28 this.age = age; 29 } 30 public double getMoney() { 31 return money; 32 } 33 public void setMoney(double money) { 34 this.money = money; 35 } 36 37 public void eat(){ 38 System.out.println("吃飯"); 39 } 40 41 public void study(String subject){ 42 System.out.println("學習"+subject); 43 } 44 45 public static void sleep(){ 46 System.out.println("睡覺"); 47 } 48 49 private static void saveMoney(double money){ 50 System.out.println("存款"+money); 51 } 52 } 53 54 55 package day20; 56 57 public class Human { 58 private String sex; 59 public Human(){ 60 61 } 62 63 private Human(int i){ 64 65 } 66 67 public String getSex() { 68 return sex; 69 } 70 71 public void setSex(String sex) { 72 this.sex = sex; 73 } 74 }