1 package java_reflect; 2 3 public class Person { 4 public String name; 5 private int age; 6 7 8 static{ 9 System.out.println("我是static的靜態代碼塊!!"); 10 } 11 public Person(){} 12 public Person(String name,int age){ 13 this.name=name; 14 this.age=age; 15 } 16 private Person(String name){ 17 this.name=name; 18 } 19 @Override 20 public String toString() { 21 return "Person [name=" + name + ", age=" + age + "]"; 22 } 23 public void eat(){ 24 System.out.println("人在吃飯!"); 25 } 26 private void sleepPrivate(){ 27 System.out.println("我正在睡覺!!!!!"); 28 } 29 30 public boolean action(String name,int age){ 31 32 System.out.println("我是帶有參數的方法,經過反射能執行!"); 33 return true; 34 } 35 36 private void playGame(String name,int age){ 37 System.out.println("人在打遊戲:"+name+" "+age); 38 } 39 40 }
1 package java_reflect; 2 /** 3 * 獲取一個類class文件對象的三種方式: 4 * 1.類名字 5 * 2.對象 6 * 3.class類的靜態方法獲取 7 * */ 8 public class ReflectDemo { 9 10 public static void main(String[] args) throws ClassNotFoundException { 11 //1.對象獲取 12 Person p=new Person(); 13 Class c=p.getClass(); 14 System.out.println(c); 15 16 //2.類名獲取 17 //每個類型,包括基本和引用,都會賦予這個類型一個靜態的屬性,屬性名字class 18 Class c1= Person.class; 19 System.out.println(c1); 20 21 //person這個類的class文件只有一個,虛擬機只會給這個文件建立一個惟一的Class類 22 //因此c1和p的內存地址都是相等的 23 System.out.println(c1==c);//true 24 System.out.println(c1.equals(c));//true 25 26 //3.Class類的靜態方法獲取forname(字符串的類名) 27 Class c3=Class.forName("java_reflect.Person"); 28 System.out.println(c3); 29 30 //這三個方法拿到的對象都是惟一的一個對象 31 } 32 }
1 package java_reflect; 2 3 import java.lang.reflect.Constructor; 4 5 /** 6 * 經過反射獲取class文件中的構造方法,運行構造方法 7 * 運行構造方法,建立對象 8 * 獲取class文件對象 9 * 從class文件對象中,獲取須要的成員 10 * 11 * Constructor 描述構造方法對象的類 12 * */ 13 public class ReflectDemo2 { 14 15 public static void main(String[] args) throws Exception, NoSuchMethodException { 16 Class c=Class.forName("java_reflect.Person"); 17 //使用Class文件對象,獲取類中的構造方法,找到類class,獲取構造器 18 //getConstructors()獲取class文件對象中的全部公共的構造方法 19 System.out.println("得到共有的全部的構造方法:"); 20 Constructor[] cons= c.getConstructors(); 21 for(Constructor con:cons){ 22 System.out.println(con); 23 /** 24 * public java_reflect.Person() 25 public java_reflect.Person(java.lang.String,int) 26 * */ 27 System.out.println("獲取指定的構造方法!"); 28 //空參數的構造方法 29 System.out.println("空參數:"); 30 Constructor conss= c.getConstructor(); 31 System.out.println(conss); 32 //運行空參數的構造方法,newInstence 33 Object objPerson=conss.newInstance(); 34 System.out.println(objPerson); 35 Object obj1=conss.newInstance(); 36 System.out.println(obj1); 37 } 38 } 39 }
1 package java_reflect; 2 /** 3 *關於反射和new:知識點 4 *1.ram和rom 2.對內存和棧內存的區別,以及數據結構的方式,以及存儲的究竟是什麼 5 *3.new 和反射是2中不一樣的設計方式:關鍵字;動態開闢一個對象和直接開闢多個對象 6 * 7 * */ 8 import java.lang.reflect.Constructor; 9 10 public class ReflectDemo3 { 11 12 public static void main(String[] args) throws Exception { 13 Class c=Class.forName("java_reflect.Person"); 14 //Class...parameterTypes基本數據類型的Class文件 15 //1.獲取帶有參數的構造函數的參數列表 16 Constructor con= c.getConstructor(String.class,int.class); 17 System.out.println(con); 18 //2.運行構造方法:initargs(實際參數) 19 Person p=(Person) con.newInstance("haha",35); 20 System.out.println(p); 21 } 22 }
1 package java_reflect; 2 /** 3 * 反射獲取構造方法並運行,有快捷的方式 4 * 有前提: 5 * 被反射的類,必須是有空參數構造方法 6 * 構造方法的權限必須是public 7 * */ 8 public class ReflectDemo4 { 9 10 public static void main(String[] args) throws Exception{ 11 Class c=Class.forName("java_reflect.Person"); 12 //Class類中定義了一個方法,newInstance() 13 14 //注意這個Class類中的方法newInstance是不能傳遞參數的 15 //這樣也使得構造方法必須是有一個空參數的構造方法 16 //因此咱們在寫類的時候若是用到反射,最好也是寫上空參數構造器 17 Object obj=c.newInstance(); 18 System.out.println(obj); 19 } 20 }
1 package java_reflect; 2 3 import java.lang.reflect.Constructor; 4 5 /** 6 * 反射獲取私有的構造方法運行 7 * 不推薦,破壞了程序的封裝性 8 * 9 * 咱們能夠使用暴力反射,強行打破Java中的類在運行時的權限 10 * */ 11 public class ReflectDemo6 { 12 13 public static void main(String[] args) throws Exception { 14 Class c=Class.forName("java_reflect.Person"); 15 //得到私有的構造器getDeclaredConstructors() 16 Constructor [] cons=c.getDeclaredConstructors(); 17 for(Constructor con:cons){ 18 System.out.println(con); 19 } 20 System.out.println("私有的指定的一個私有構造器!"); 21 Constructor conPrivate=c.getDeclaredConstructor(String.class); 22 System.out.println(conPrivate); 23 // Person p2=(Person)conPrivate.newInstance("李澤博!"); 24 //錯誤,main中沒法訪問私有的構造器 25 26 //1.使用暴力反射 27 /** 28 * AccessibleObject 類是 Field、Method 和 Constructor 對象的基類。它提供了將反射的對象標記爲在使用時取消默認 Java 語言訪問控制檢查的能力。 29 * 對於公共成員、默認(打包)訪問成員、受保護成員和私有成員, 30 * 在分別使用 Field、Method 或 Constructor 31 * 對象來設置或獲取字段、調用方法,或者建立和初始化類的新實例的時候, 32 * 會執行訪問檢查。 33 * */ 34 Constructor con=c.getDeclaredConstructor(String.class); 35 con.setAccessible(true); 36 //運行私有的構造器!! 37 con.newInstance("李澤博!!!!!!!!!"); 38 } 39 }
1 package java_reflect; 2 3 import java.lang.reflect.Field; 4 5 public class ReflectDemo7 { 6 7 public static void main(String[] args) throws Exception{ 8 Class c=Class.forName("java_reflect.Person"); 9 Object obj=c.newInstance(); 10 //獲取成員變量的Clas變量的方法getField class文件中全部公共的成員變量 11 //返回值是Field[] Fiel類描述成員變量對象的類 12 13 //拿的是公有的成員變量 14 System.out.println("拿的是私有的成員變量"); 15 Field[] fields= c.getFields(); 16 for(Field field:fields){ 17 System.out.println(field); 18 } 19 //私有的,公有的一塊兒,也便是聲明瞭的變量 20 System.out.println("私有的 :"); 21 Field [] fiels1=c.getDeclaredFields(); 22 for(Field fiels:fiels1){ 23 System.out.println(fiels); 24 } 25 //獲取指定的一個成員變量 26 System.out.println("獲取指定的一個成員變量"); 27 Field fieldss=c.getField("name"); 28 System.out.println(fieldss); 29 30 System.out.println("改掉變量值爲'王五'"); 31 fieldss.set(obj, "王五!!"); 32 33 System.out.println(obj); 34 //這裏若是咱們不是用obj,上面建立的對象,那麼使用c.newInstance()會使得 35 //你建立了2個對象,使得結果是null,0 36 } 37 }
1 package java_reflect; 2 3 import java.lang.reflect.Method; 4 5 public class ReflectDemo8 { 6 7 public static void main(String[] args) throws Exception { 8 Class c=Class.forName("java_reflect.Person"); 9 Object obj=c.newInstance(); 10 //獲取到成員方法 11 //Method []getMethods()獲取的是Class文件的全部公共的成員方法,包括繼承的 12 //Method是描述成員方法的對象類 13 System.out.println("成員方法:"); 14 Method [] methods= c.getMethods(); 15 for(Method method:methods){ 16 System.out.println(method); 17 } 18 System.out.println("利用反射使用method:"); 19 Method method= c.getMethod("eat"); 20 System.out.println(method); 21 method.invoke(obj); 22 } 23 }
1 package java_reflect; 2 3 import java.lang.reflect.Constructor; 4 import java.lang.reflect.Method; 5 6 public class ReflectDemo9 { 7 8 public static void main(String[] args) throws Exception { 9 Class c=Class.forName("java_reflect.Person"); 10 Object obj=c.newInstance(); 11 12 Method method= c.getMethod("action", String.class,int.class); 13 boolean bool=(Boolean) method.invoke(obj,"李澤博",23); 14 System.out.println(bool); 15 //經過反射獲取私有的帶參數的方法 16 System.out.println("經過反射獲取私有的帶參數的方法"); 17 Object obj1=c.newInstance(); 18 Method method1=c.getDeclaredMethod("playGame", String.class,int.class); 19 //在使用反射式,取消Java中權限 20 method1.setAccessible(true); 21 method1.invoke((Person)obj1, "李澤博sdf",23); 22 23 } 24 }
反射進行的泛型擦除:java
1 package java_reflect; 2 3 import java.lang.reflect.Method; 4 import java.util.ArrayList; 5 6 /** 7 * 定義集合類,泛型String 8 * 要求向集合中添加Integer類型 9 * 10 * 反射方式,獲取 出集合ArrayList類的class文件對象 11 * 經過class文件都對象,經過調用add()方法 12 * 13 *爲何能夠使用這種方式:由於在編譯器中是沒有泛型這種類型的,因此在.class文件對象中能夠使用這種方式 14 * */ 15 public class ReflectDemo10 { 16 17 public static void main(String[] args) throws Exception{ 18 ArrayList<String> array=new ArrayList<String>(); 19 array.add("例子莪"); 20 //反射方式進行泛型擦除,在ArrayList源碼中實際上是一個對象數組,因此能夠進行儲存各類類型, 21 //可是經過泛型又有了約束 22 Class c=Class.forName("java.util.ArrayList"); 23 Method method= c.getMethod("add",Object.class); 24 System.out.println(method); 25 System.out.println("使用反射技術~運行方法"); 26 27 //Object obj=c.newInstance(); 28 method.invoke(array, 1500); 29 method.invoke(array, 200); 30 System.out.println(array); 31 } 32 }
使用反射可讓代碼變得很靈活,好比讀取配置文件,只須要修改配置文件的鍵值對就可讓程序運行不一樣的類和方法數組
1 package java_reflect_two; 2 3 public class Person { 4 5 public void eat(){ 6 System.out.println("人在吃飯~"); 7 } 8 }
1 package java_reflect_two; 2 3 public class Student { 4 5 public void study(){ 6 System.out.println("學生在學習!"); 7 } 8 }
1 package java_reflect_two; 2 3 public class Worker { 4 5 public void job(){ 6 System.out.println("上班族在工做!"); 7 } 8 }
1 #className=java_reflect_two.Person 2 #methodName=eat 3 4 #className=java_reflect_two.Student 5 #methodName=study 6 7 className=java_reflect_two.Worker 8 methodName=job
1 package java_reflect_two; 2 3 import java.io.FileReader; 4 import java.lang.reflect.Method; 5 import java.util.Properties; 6 7 /** 8 * 調用Person方法,調用Student,調用Worker中的方法,也就是說 9 * 運行哪一個類是不肯定的,類不清楚,方法也不清楚。 10 * 11 * 經過配置文件實現此功能,以鍵值對的形式,寫在文本中 12 * 運行那個類,讀取配置文集那便可 13 * 實現步驟: 14 * 1.準備配置文件,鍵值對 15 * 2.IO流讀取配置文件 Reader 16 * 3.文件中的價值對存儲到集合中:Properties 17 * 4.直接用反射獲取指定類的,class文件的對象 18 * 5.獲取方法,執行方法 19 */ 20 public class Test { 21 22 public static void main(String args[]) throws Exception{ 23 24 //IO讀取配置文件 25 FileReader r=new FileReader("config.properties"); 26 //建立集合對象 27 Properties pro=new Properties(); 28 pro.load(r); 29 r.close(); 30 //經過鍵獲取值 31 32 String className=pro.getProperty("className"); 33 String methodName=pro.getProperty("methodName"); 34 //測試:System.out.println(className+": "+methodName); 35 36 Class c=Class.forName(className); 37 Object obj=c.newInstance(); 38 Method method=c.getMethod(methodName); 39 method.invoke(obj); 40 } 41 }