1.java反射的概念
JAVA反射機制是在運行狀態中,對於任意一個類,都能夠知道這個類的所有屬性和方法;對於任意一個對象,都能夠調用它的任意方法和屬性;這種動態獲取信息以及動態調用對象方法的功能稱爲java語言的反射機制。通俗的講就是反射可以在運行時根據指定的類名獲得類的信息。
2.反射的作用
首先我們先明確兩個概念,靜態編譯和動態編譯。
靜態編譯:在編譯時確定類型,綁定對象,即通過。
動態編譯:運行時確定類型,綁定對象。動態編譯最大限度發揮了java的靈活性,體現了多態的應用,有以降低類之間的藕合性。我們可以明確的看出動態編譯的好處,而反射就是運用了動態編譯創建對象。
在我們創建數據庫鏈接時,這句代碼Class tc = Class.forName("com.java.dbtest.TestConnection")就是告訴JVM去加載這個類,而加載的過程是在程序執行過程中動態加載的。通過類的全類名讓jvm在服務器中找到並加載這個類,而如果是使用別的數據庫,那就要換一個類了,如果是傳統寫死的方法創建,就要修改原來類的代碼,而對於反射,則只是傳入的參數就變成另一個了而已,可以通過修改配置文件,而不是直接修改代碼。
在框架設計中常常用到反射機制,比如在spring中,我們將所有的類Bean交給spring容器管理,無論是XML配置Bean還是註解配置,當我們從容器中獲取Bean來依賴注入時,容器會讀取配置,而配置中給的就是類的信息,spring根據這些信息,需要創建那些Bean,spring就動態的創建這些類
簡單來理解,使用反射能有效減低代碼耦合。
3.反射的原理
JAVA語言編譯之後會生成一個.class文件,反射就是通過字節碼文件找到某一個類、類中的方法以及屬性等,具體如何實現就先不管
4.反射的使用
直接上代碼
package com.reflex;
/**
*
* 類名稱: Student
* 類描述:
* 創建人: zzh
* 修改時間:2018年9月10日 下午2:40:12
* 修改備註:
* @version 1.0.0
*/
public class Student{
private int age;
public String name;
public Student(){}
public Student(String name,int age){
this.name=name;
this.age=age;
}
public String test1(){
return "test1";
}
public String test2(){
return "test2";
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Student [age=" + age + ", name=" + name + "]";
}
}
package com.reflex;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
public class ClassReflexUtil {
private Class c;
public ClassReflexUtil() {
}
public ClassReflexUtil(String className) throws ClassNotFoundException {
//1.獲取Class對象
c = Class.forName(className);
}
//獲取構造函數的所有內容
private void getConstruction() {
System.out.println("************構造函數的所有內容(包括私有、受保護、默認的)********************");
Constructor[] constructors=c.getDeclaredConstructors();
for (Constructor constructor : constructors) {
System.out.print(Modifier.toString(constructor.getModifiers())+" ");//獲取構造函數的修飾符
System.out.print(constructor.getName()+"("); //獲取構造函數的名稱
Class[] p=constructor.getParameterTypes();
for(int k=0;k<p.length;k++){
System.out.print(p[k].getName()+" ");
}
System.out.println(" );");
}
}
//獲取相應類的所有屬性
public void getParameter() throws ClassNotFoundException{
//獲取屬性
System.out.println("************獲取所有的字段(包括私有、受保護、默認的)********************");
Field[] fieldArray = c.getDeclaredFields();
for(Field f : fieldArray){
System.out.println(f);
}
/*
System.out.println("************獲取所有公有的字段********************");
Field[] fieldArray = stuClass.getFi elds();
for(Field f : fieldArray){
System.out.println(f);
}*/
}
//獲取相應類裏面的所有申明的方法
private void getDeclaredFields() {
System.out.println("************獲取所有的方法(包括私有、受保護、默認的)********************");
Method field[]=c.getDeclaredMethods();
for (Method method : field) {
System.out.print(Modifier.toString(method.getModifiers())+" "); //獲取函數的修飾符權限
System.out.print(method.getReturnType()+" "+method.getName()+"("); //獲取函數的名稱
Class type[]= method.getParameterTypes();
for (Class aClass : type) {
System.out.print(aClass.getName()+" ");
}
System.out.println(");");
}
}
//設置相應類的屬性值
public void setParameter(String parameter,String value) throws NoSuchFieldException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException{
Field field=c.getField(parameter);
System.out.println(field);
//獲取一個對象
Object obj = c.getConstructor().newInstance();
//爲字段設置值
field.set(obj, value);
//驗證
Student stu = (Student)obj;
System.out.println("驗證姓名:" + stu.name);
}
public static void main(String[] args) throws Exception {
ClassReflexUtil cReflexUtil=new ClassReflexUtil("com.reflex.Student");
cReflexUtil.getParameter();
cReflexUtil.getConstruction();
cReflexUtil.getDeclaredFields();
}
}