原文地址java
反射簡單來講,就是動態加載對象,並對對象進行剖析。在Java中的反射機制是指在運行狀態中,對於任意一個類,都可以知道並獲取這個類的全部屬性和方法。函數
反射機制的優勢就是能夠實現動態建立對象和編譯,體現出很大的靈活性。性能
它的缺點是對性能有影響。使用反射基本上是一種解釋操做,咱們能夠告訴JVM,咱們但願作什麼而且它
知足咱們的要求。這類操做老是慢於只直接執行相同的操做。this
package com.gyl; public class Student { public int no; public String sex; private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } /* * 構造方法 */ Student(String str){ System.out.println("(默認)的構造方法 s = " + str); } //無參構造方法 public Student(){ System.out.println("調用了公有、無參構造方法執行了。。。"); } //有一個參數的構造方法 protected Student(char name){ System.out.println("姓名:" + name); } //有多個參數的構造方法 public Student(String name ,int age){ System.out.println("姓名:"+name+"年齡:"+ age);//這的執行效率有問題,之後解決。 } //私有構造方法 private Student(int age){ System.out.println("私有的構造方法 年齡:"+ age); } }
package com.gyl; import java.lang.reflect.Constructor; public class Main { public static void main(String[] args) throws ClassNotFoundException { Student student = new Student(); /* * JAVA反射--獲取Class對象的三種方式 */ // 經過對象名.getClass()方法獲取 Class stuClass = student.getClass(); System.out.println("stuClass is "+stuClass.getName()); // 經過類名.class方式得到 Class stuClass1 = Student.class; System.out.println("stuClass1 is "+stuClass1.getName()); System.out.println(stuClass == stuClass1); // 經過Class.forName()方法得到 Class stuClass2 = Class.forName("com.gyl.Student"); System.out.println("stuClass2 is "+stuClass2); System.out.println(stuClass1 == stuClass2); } } Output: stuClass is com.gyl.Student stuClass1 is com.gyl.Student true stuClass2 is class com.gyl.Student true
在運行期間,一個類,只有一個Class對象產生。三種方式經常使用第三種,第一種對象都有了還要反射干什麼。第二種須要導入類的包,依賴太強,不導包就拋編譯錯誤。通常都選第三種,一個字符串能夠傳入也可寫在配置文件中等多種方法。
// 返回指定參數類型 public的構造器。 Constructor<T> getConstructor(類<?>... parameterTypes) // 返回指定參數類型的構造器(public, protected, private)。 Constructor<T> getDeclaredConstructor(類<?>... parameterTypes) // 返回全部的public類型的構造器 Constructor<?>[] getConstructors() // 返回全部的構造器 Constructor<?>[] getDeclaredConstructors()
package com.gyl; import java.lang.reflect.Constructor; public class Main { public static void main(String[] args) throws ClassNotFoundException { // 經過Class.forName()方法得到Class對象 Class stuClass = Class.forName("com.gyl.Student"); System.out.println("************返回全部public構造方法************"); Constructor[] constructors = stuClass.getConstructors(); for (Constructor constructor : constructors) { System.out.println(constructor); } /* * Output: * ************返回全部public構造方法************ * public com.gyl.Student() * public com.gyl.Student(java.lang.String,int) */ System.out.println("************全部的構造方法(包括:私有、受保護、默認、公有)***************"); Constructor[] constructors2 = stuClass.getDeclaredConstructors(); for (Constructor constructor : constructors2) { System.out.println(constructor); } /* * Output: * ************全部的構造方法(包括:私有、受保護、默認、公有)*************** * private com.gyl.Student(int) * public com.gyl.Student() * protected com.gyl.Student(char) * public com.gyl.Student(java.lang.String,int) * com.gyl.Student(java.lang.String) */ Constructor constructor; System.out.println("************返回指定類型的 public構造器************"); try { constructor = stuClass.getConstructor(String.class, int.class); System.out.println(constructor); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } /* * Output: * ************返回指定類型的 public構造器************ * public com.gyl.Student(java.lang.String,int) * * 若是指定參數的構造器是非public類型的 則拋出java.lang.NoSuchMethodException異常 */ System.out.println("************返回指定類型的構造器************"); try { constructor = stuClass.getDeclaredConstructor(int.class); System.out.println(constructor); // char.class } catch (NoSuchMethodException e) { // String.class, int.class e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } /* * Output: * ************返回指定類型的構造器************ * public com.gyl.Student(java.lang.String,int) * protected com.gyl.Student(char) * private com.gyl.Student(int) */ } }
// 根據變量名得到對應的變量,訪問權限不限; Field getDeclaredField(String name) // 得到類中全部屬性變量 Field[] getDeclaredFields() // 根據變量名獲取對應public類型的屬性變量 Field getField(String name) // 獲取類中全部public類型的屬性變量 Field[] getFields()
package com.gyl; import java.lang.reflect.Field; public class Main { public static void main(String[] args) throws ClassNotFoundException { // 經過Class.forName()方法得到Class對象 Class stuClass = Class.forName("com.gyl.Student"); try { Field field1 = stuClass.getField("sex"); System.out.println(field1); Field field = stuClass.getDeclaredField("name"); System.out.println(field); } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } /* * Output: * public java.lang.String com.gyl.Student.sex * private java.lang.String com.gyl.Student.name * 若是使用getField方法指定了一個非public類型的屬性,則拋出java.lang.NoSuchFieldException異常 */ Field[] fields1 = stuClass.getFields(); Field[] fields = stuClass.getDeclaredFields(); System.out.println("************返回全部public屬性************"); for (Field field : fields1) { System.out.println(field); } /* * Output: * ************返回全部public屬性************ * public int com.gyl.Student.no * public java.lang.String com.gyl.Student.sex */ System.out.println("************返回全部屬性************"); for (Field field : fields) { System.out.println(field); } /* * Output: * ************返回全部屬性************ * public int com.gyl.Student.no * public java.lang.String com.gyl.Student.sex * private java.lang.String com.gyl.Student.name * private int com.gyl.Student.age */ } }
// 獲取「名稱是name,參數是parameterTypes」的public的函數(包括從基類繼承的、從接口實現的全部public函數) public Method getMethod(String name, Class[] parameterTypes) // 獲取所有的public的函數(包括從基類繼承的、從接口實現的全部public函數) public Method[] getMethods() // 獲取「名稱是name,參數是parameterTypes」,而且是類自身聲明的函數,包含public、protected和private方法。 public Method getDeclaredMethod(String name, Class[] parameterTypes) // 獲取所有的類自身聲明的函數,包含public、protected和private方法。 public Method[] getDeclaredMethods() // 若是這個類是「其它類中某個方法的內部類」,調用getEnclosingMethod()就是這個類所在的方法;若不存在,返回null。 public Method getEnclosingMethod()
package com.gyl; import java.lang.reflect.Method; public class Main { public static void main(String[] args) throws ClassNotFoundException { // 經過Class.forName()方法得到Class對象 Class stuClass = Class.forName("com.gyl.Student"); Method method; try { // method = stuClass.getMethod("getName"); method = stuClass.getDeclaredMethod("getAge"); System.out.println(method); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } System.out.println("*********輸出全部方法********"); Method[] methods = stuClass.getDeclaredMethods(); for (Method method2 : methods) { System.out.println(method2); } /* * Output: * public int com.gyl.Student.getAge() * *********輸出全部方法******** * public java.lang.String com.gyl.Student.getName() * public void com.gyl.Student.setName(java.lang.String) * void com.gyl.Student.print(java.lang.String) * public int com.gyl.Student.getAge() * public void com.gyl.Student.setAge(int) */ } }
泛型用在編譯期,編譯事後泛型擦除(消失掉)。因此是能夠經過反射越過泛型檢查的code
import java.lang.reflect.Method; import java.util.ArrayList; /* * 經過反射越過泛型檢查 * * 例如:有一個String泛型的集合,怎樣能向這個集合中添加一個Integer類型的值? */ public class Demo { public static void main(String[] args) throws Exception{ ArrayList<String> strList = new ArrayList<>(); strList.add("aaa"); strList.add("bbb"); // strList.add(100); //獲取ArrayList的Class對象,反向的調用add()方法,添加數據 Class listClass = strList.getClass(); //獲得 strList 對象的字節碼 對象 //獲取add()方法 Method m = listClass.getMethod("add", Object.class); //調用add()方法 m.invoke(strList, 100); //遍歷集合 for(Object obj : strList){ System.out.println(obj); System.out.println(obj.getClass()); } /* *Output: * aaa * class java.lang.String * bbb * class java.lang.String * 100 * class java.lang.Integer */ } }
其餘方法請參考Java jdk,本文參考自Java jdk1.8對象