空口說反射,很難理解這是個什麼東西,舉個例子就明瞭了。java
假設如今咱們有一張動漫的圖片,咱們經過這張圖片,在大腦中搜索有關記憶,就清楚這張圖片是什麼動漫裏的誰;假設咱們如今有一個名字,在大腦中搜索有關記憶,就天然而然地想到了該名字人物的具體形象,這種思惟過程就是反射。ide
假設一個類已經加載進JVM,那麼,給定該類名,咱們就能夠經過反射來獲取該類的相應信息。學習
具體定義:反射是被視爲動態語言的關鍵,反射機制容許程序在執行期藉助反射API取得任何類的內部信息,並能直接操做在任何對象的內部屬性和方法。this
java反射機制提供的功能:spa
反射相關的API:代理
一。class類code
在Object類中定義瞭如下的方法,此方法將被全部子類繼承:public final Class getClass()。對象
以上方法返回值是一個Class類,此類是java反射的源頭,實際上所謂反射從程序的運行結果來看也很好理解,即:經過對象反射求出類的名稱。blog
反射能夠獲得的信息:某個類的屬性、方法、構造器、某個類到底實現了哪些接口。對於每一個類而言,JRE都爲其保留一個Class類型的對象。一個Class對象包含了特定某個類的有關信息。繼承
實例化Class類的四種方式:
2、經過反射調用類的完整結構
Person.java
package ref; public class Person { public String name; public int age; }
Move.java
package ref; interface Move { void move(); }
Study.java
package ref; public interface Study { void study(); }
Student.java
package ref; public class Student extends Person implements Move,Study{ public String school; private String privateField; public void showInfo() { System.out.println("學校是"+this.school); } @Override public void study() { // TODO Auto-generated method stub System.out.println("學習到中學的知識"); } @Override public void move() { // TODO Auto-generated method stub System.out.println("騎自行車上學"); } public Student() { System.out.println("調用的是Student()"); } public Student(String school) { this.school = school; System.out.println("調用的是Student(String school)"); } private Student(String name,int age) { this.name = name; this.age = age; System.out.println("調用的是Student(String name,int age)"); } private void test(String name) {} public String testGetSchool() { return school; } }
test.java
package ref; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public class Test { public static void main(String[] args) { try { //這裏是相關代碼 } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
1.獲取類的父類和接口
Class clazz = Class.forName("ref.Student"); Class superClass = clazz.getSuperclass(); //獲取父類的名字 System.out.println("父類:"+superClass.getName()); //獲取實現的接口 Class[] interfaces = clazz.getInterfaces(); for(Class itf:interfaces) { System.out.println("接口名字:"+itf.getName()); }
父類:ref.Person
接口名字:ref.Move
接口名字:ref.Study
2.獲取類的構造方法
//獲取公有的構造方法 Constructor[] cons = clazz.getConstructors(); for(Constructor con:cons) { System.out.println("--------------------------"); System.out.println("構造方法:"+con.getName());//獲取構造方法名稱 //返回1表明public System.out.println("構造方法修飾符:"+con.getModifiers());//獲取構造方法修飾符 //獲取構造方法的參數類型 Class[] parameterClass = con.getParameterTypes(); for(Class param:parameterClass){ System.out.println("構造方法:"+con.getName()+"的參數類型爲"+param.getName()); } System.out.println("--------------------------"); } //獲取私有的構造方法 Constructor[] cons2 = clazz.getDeclaredConstructors(); for(Constructor con:cons2) { System.out.println("--------------------------"); System.out.println("構造方法:"+con.getName());//獲取構造方法名稱 System.out.println("構造方法修飾符:"+con.getModifiers());//獲取構造方法修飾符 //獲取構造方法的參數類型 Class[] parameterClass = con.getParameterTypes(); for(Class param:parameterClass){ System.out.println("構造方法:"+con.getName()+"的參數類型爲"+param.getName()); } System.out.println("--------------------------"); }
--------------------------
構造方法:ref.Student
構造方法修飾符:1
--------------------------
--------------------------
構造方法:ref.Student
構造方法修飾符:1
構造方法:ref.Student的參數類型爲java.lang.String
--------------------------
--------------------------
構造方法:ref.Student
構造方法修飾符:1
--------------------------
--------------------------
構造方法:ref.Student
構造方法修飾符:2
構造方法:ref.Student的參數類型爲java.lang.String
構造方法:ref.Student的參數類型爲int
--------------------------
--------------------------
構造方法:ref.Student
構造方法修飾符:1
構造方法:ref.Student的參數類型爲java.lang.String
--------------------------
3.經過反射來建立對象
//至關於調用無參構造方法 Object obj = clazz.newInstance(); Student stu = (Student) obj; //至關於調用Student(String school)構造方法 Constructor con = clazz.getConstructor(String.class); Student stu1 = (Student) con.newInstance("一中"); //經過反射機制能夠強制獲取私有方法 Constructor con2 = clazz.getDeclaredConstructor(String.class,int.class); //解除私有的封裝 con2.setAccessible(true); Student stu2 = (Student) con2.newInstance("jack",23); System.out.println(stu2.name); System.out.println(stu2.age);
調用的是Student()
調用的是Student(String school)
調用的是Student(String name,int age)
jack
23
4.獲取類的方法
//獲取全部公有方法 Method[] ms = clazz.getMethods(); for(Method m:ms) { System.out.println("--------------------------"); System.out.println("方法名:"+m.getName()); System.out.println("返回值類型:"+m.getReturnType()); System.out.println("修飾符:"+m.getModifiers()); Class[] mrs = m.getParameterTypes(); if(mrs!=null && mrs.length>0) { for(Class mr:mrs){ System.out.println("方法參數類型:"+mr.getName()); } } System.out.println("--------------------------"); } //獲取全部方法,包括公有和私有 Method[] ms2 = clazz.getDeclaredMethods(); for(Method m:ms2) { System.out.println("--------------------------"); System.out.println("方法名:"+m.getName()); System.out.println("返回值類型:"+m.getReturnType()); System.out.println("修飾符:"+m.getModifiers()); Class[] mrs = m.getParameterTypes(); if(mrs!=null && mrs.length>0) { for(Class mr:mrs){ System.out.println("方法參數類型:"+mr.getName()); } } System.out.println("--------------------------"); }
--------------------------
方法名:showInfo
返回值類型:void
修飾符:1
--------------------------
--------------------------
方法名:study
返回值類型:void
修飾符:1
--------------------------
--------------------------
方法名:move
返回值類型:void
修飾符:1
--------------------------
--------------------------
方法名:testGetSchool
返回值類型:class java.lang.String
修飾符:1
--------------------------
--------------------------
方法名:wait
返回值類型:void
修飾符:17
--------------------------
--------------------------
方法名:wait
返回值類型:void
修飾符:17
方法參數類型:long
方法參數類型:int
--------------------------
--------------------------
方法名:wait
返回值類型:void
修飾符:273
方法參數類型:long
--------------------------
--------------------------
方法名:equals
返回值類型:boolean
修飾符:1
方法參數類型:java.lang.Object
--------------------------
--------------------------
方法名:toString
返回值類型:class java.lang.String
修飾符:1
--------------------------
--------------------------
方法名:hashCode
返回值類型:int
修飾符:257
--------------------------
--------------------------
方法名:getClass
返回值類型:class java.lang.Class
修飾符:273
--------------------------
--------------------------
方法名:notify
返回值類型:void
修飾符:273
--------------------------
--------------------------
方法名:notifyAll
返回值類型:void
修飾符:273
--------------------------
--------------------------
方法名:test
返回值類型:void
修飾符:2
方法參數類型:java.lang.String
--------------------------
--------------------------
方法名:showInfo
返回值類型:void
修飾符:1
--------------------------
--------------------------
方法名:study
返回值類型:void
修飾符:1
--------------------------
--------------------------
方法名:move
返回值類型:void
修飾符:1
--------------------------
--------------------------
方法名:testGetSchool
返回值類型:class java.lang.String
修飾符:1
--------------------------
5.獲取類的屬性
//獲取公有屬性 Field[] fs = clazz.getFields(); for(Field f:fs) { System.out.println("--------------------------"); System.out.println("屬性名:"+f.getName()); System.out.println("屬性類型:"+f.getType()); System.out.println("修飾符:"+f.getModifiers()); System.out.println("--------------------------"); } //獲取全部屬性 Field[] fs2 = clazz.getDeclaredFields(); for(Field f:fs2) { System.out.println("--------------------------"); System.out.println("屬性名:"+f.getName()); System.out.println("屬性類型:"+f.getType()); System.out.println("修飾符:"+f.getModifiers()); System.out.println("--------------------------"); }
--------------------------
屬性名:school
屬性類型:class java.lang.String
修飾符:1
--------------------------
--------------------------
屬性名:name
屬性類型:class java.lang.String
修飾符:1
--------------------------
--------------------------
屬性名:age
屬性類型:int
修飾符:1
--------------------------
--------------------------
屬性名:school
屬性類型:class java.lang.String
修飾符:1
--------------------------
--------------------------
屬性名:privateField
屬性類型:class java.lang.String
修飾符:2
--------------------------
6.獲取類所在的包
//獲取類所在的包 Package p = clazz.getPackage(); System.out.println(p.getName());
ref
3、經過反射來調用類中指定的方法和屬性
向Student.java中插入如下方法:
private void test(String name) { System.out.println("這是私有的test(String name)方法"); } public void setInfo(String name,String school) { this.name = name; this.school = school; System.out.println("這是公有的setInfo(String name,String school)方法"); } public void setInfo(int age) { this.age = age; System.out.println("這是公有的setInfo(int age)方法"); }
1.調用類中指定的方法
Constructor con = clazz.getConstructor(); Object obj = con.newInstance(); //先獲取到方法 Method m = clazz.getMethod("setInfo", String.class,String.class); //再進行調用 m.invoke(obj, "tom","三中"); //若是想調用私有的方法 Method m2 = clazz.getDeclaredMethod("test", String.class); m2.setAccessible(true); m2.invoke(obj, "jack"); //調用重載的方法 Method m3 = clazz.getMethod("setInfo", int.class); m3.invoke(obj, 12); //調用具備返回值的方法 Method m4 = clazz.getMethod("testGetSchool"); String school = (String) m4.invoke(obj); System.out.println(school);
調用的是Student()
這是公有的setInfo(String name,String school)方法
這是私有的test(String name)方法
這是公有的setInfo(int age)方法
三中
2.調用類中指定的屬性
Constructor con = clazz.getConstructor(); Object obj = con.newInstance(); Student stu = (Student) obj; Field f = clazz.getField("school"); //對stu屬性school設置值 f.set(stu,"第三中學"); String school = (String) f.get(stu); System.out.println(school); //若是是私有的屬性 Field f2 = clazz.getDeclaredField("privateField"); f2.setAccessible(true); f2.set(stu,"私有屬性"); String privateField = (String) f2.get(stu); System.out.println(privateField);
調用的是Student()第三中學私有屬性