JAVA 反射

1.Java反射

  • 機制是運行狀態中,對於任意一個類都能夠知道這個類的所有屬性和方法(包括私有的);對於任意一個對象,都能調用他的任意方法和屬性;這種動態獲取信息及動態調用對象方法的功能稱爲Java的反射機制

1.1 用途

  • 在運行時判斷任意一個對象所屬的類。

  • 在運行時構造任意一個類的對象。

  • 在運行時判斷任意一個類所具有的成員變量和方法。

  • 在運行時調用任意一個對象的方法。

  • 生成動態代理。**

2. 反射相關的類

類名 用途
java.lang.Class 代表類
java.lang.reflect.Field 代表類的成員變量
java.lang.reflect.Method 代表類的方法
java.lang.reflect.Constructor 代表類的構造

2. Class類

在Java程序中獲得Class對象通常有如下三種方式:

1.使用Class類的forName(String clazzName)靜態方法。該方法需要傳入字符串參數,該字符串參數的值是某個類的全限定名(必須添加完整包名)。

2.調用某個類的class屬性來獲取該類對應的Class對象。

3.調用某個對象的getClass()方法。該方法是java.lang.Object類中的一個方法。

3. Field

Field[] allFields = class2.getDeclaredFields();//獲取class對象的所有屬性
Field[] publicFields = class2.getFields();//獲取class對象的public屬性
Field ageField = class2.getDeclaredField("age");//獲取class指定屬性,可以獲得私有屬性
Field desField = class2.getField("des");//獲取class指定的public屬性

4. Method


Method[] methods = class2.getDeclaredMethods();//獲取class對象的所有聲明方法
Method[] allMethods = class2.getMethods();//獲取class對象的所有public方法 包括父類的方法
Method method = class2.getMethod("info", String.class);//返回次Class對象對應類的、帶指定形參列表的public方法
Method declaredMethod = class2.getDeclaredMethod("info", String.class);//返回次Class對象對應類的、帶指定形參列表的方法

5. Constructor


Constructor<?>[] allConstructors = class2.getDeclaredConstructors();//獲取class對象的所有聲明構造函數
Constructor<?>[] publicConstructors = class2.getConstructors();//獲取class對象public構造函數
Constructor<?> constructor = class2.getDeclaredConstructor(String.class);//獲取指定聲明構造函數
Constructor publicConstructor = class2.getConstructor(String.class);//獲取指定聲明的public構造函數


6. 通過反射 生成實例對象

  • 1.使用Class對象的newInstance()方法來創建該Class對象對應類的實例。這種方式要求該Class對象的對應類有默認構造器,而執行newInstance()方法時實際上是利用默認構造器來創建該類的實例。

  • 2.先使用Class對象獲取指定的Constructor對象,再調用Constructor對象的newInstance()方法來創建該Class對象對應類的實例。通過這種方式可以選擇使用指定的構造器來創建實例。

7. 調用方法

  • 1.通過Class對象的getMethods()方法或者getMethod()方法獲得指定方法,返回Method數組或對象。

  • 2.調用Method對象中的Object invoke(Object obj, Object… args)方法。第一個參數對應調用該方法的實例對象,第二個參數對應該方法的參數。

8. 示例代碼:

8.1 反射

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Properties;

/**
 * 反射:
 *     在類加載過程中,獲取類的屬性和方法構造方法等信息,可以調用其方法。
 *     
 *     
 * 克隆: 我們學習數據庫: 數據庫提供  《驅動器》driver    DriverManager  這個驅動器不允許new。
 *      會學習: Tomcat 內部組件需要反射。
 *      會學習: 框架:   內部組件也需要反射。
 * 
 * 通過反射:得到類的包名以及類名。
 *        Properties
 * 
 *
 */
public class Demo01 {

	public static void main(String[] args) throws Exception, IOException {
		Properties pro = new Properties();
		pro.load(new FileInputStream("aa.properties"));
		
		System.out.println(pro.get("name"));
		String str = (String) pro.get("name");
		Class  c=  Class.forName(str);
		Object obj = c.newInstance();
		Foo foo = (Foo)obj;
		System.out.println(foo.a);
		foo.show();
		
		/**
		 * Class   是每個類的字節碼對象。
		 */
		
		String str1 = "abc";// str1 Object  "abc"  Object
		Class c1 = str1.getClass();
		Class c2 = "abc".getClass();
		System.out.println(c1==c2);
		
		;Class c3 = String.class;
		Class c4 = Class.forName("java.lang.String");
		System.out.println(c3==c4);
	}

}

8.2 反射是什麼

1

package am;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;

import javax.activation.FileDataSource;

/**
 * 反射是什麼:
 *    java中的反射:就是在類的加載過程中,發現類的屬性和方法構造方法等信息。可以獲得類的屬性值,可以調用類的方法。
 *    
 * 
 * 反射獲得類的對象。
 *
 */
public class Demo01 {

	public static void main(String[] args) throws Exception{
		// 通過反射,獲取類的對象。
		Object obj = create("am.Foo");;
		Foo foo = (Foo)obj;
		System.out.println(foo.a);
		double dou = foo.show(12, "hello");
		System.out.println(dou);
		
		System.out.println("======================================");
		// 獲得類的屬性
		showField(obj);
		System.out.println("======================================");
		double a = (double)getFieldValue(obj, "b");
		System.out.println(a);
		System.out.println("========================================");
		// 通過反射調用方法。
		Object ob = getMethodValue(obj,"show",new Class[]{int.class,String.class},new Object[]{23,"abc"});
		double douValue = (double)ob;
		System.out.println(douValue);
		
	}
//通過反射調用方法,哪個對象,什麼名稱,參數類型,參數值

	public static Object getMethodValue(Object obj,String method,Class[] paramType,Object[] param)
	throws Exception{
		Class cla = obj.getClass();
		Method me = cla.getDeclaredMethod(method, paramType);
		Object o = me.invoke(obj, param);
		return o;
	}
	
	
	// 獲取類的屬性值:
	public static Object getFieldValue(Object obj,String name)throws Exception{
		Class cla = obj.getClass();// 獲取字節碼對象。
		Field field = cla.getDeclaredField(name);// 通過屬性的名稱。獲取當前屬性。
		Object result = field.get(obj);
		return result;
	}
	
	
	// 通過反射,可以獲得類的屬性信息以及方法信息。
	public static void showField(Object obj){
		// java中對屬性類。 Field   方法類:Method
		Class cla = obj.getClass();
		System.out.println("獲取類名:"+cla.getName());
		System.out.println("======================================");
		// 獲取類的屬性:
		Field[] fields = cla.getDeclaredFields();// 獲取公開的屬性。
		for(Field field : fields){
			System.out.println("獲取類的屬性類型"+field.getType());
			System.out.println("獲取類的屬性名稱:"+field.getName());
		}
		System.out.println("======================================");
		// 獲取類的方法。
		Method[] methods = cla.getDeclaredMethods();
		for(Method method : methods){
			System.out.println("獲取方法的返回值類型:"+method.getReturnType());
			System.out.println("獲取方法名稱:"+method.getName());
			System.out.println("獲取方法的參數類型。"+Arrays.toString(method.getParameterTypes()));
		}
		
		System.out.println("=======================================");
		
		// 獲取類的構造方法:
		Constructor[] cons = cla.getDeclaredConstructors();
		for(Constructor con : cons){
			System.out.println("構造方法的名字:"+con.getName());
			System.out.println("構造方法參數類型:"+Arrays.toString(con.getParameterTypes()));
		}
		
	}
	
	
	// 如何反射類的實例。
	public static Object create(String name) throws Exception{
		// 反射的方法。Class.forName();
		Class cla = Class.forName(name);
		// 如何獲得Object類型對象。
		Object obj = cla.newInstance();
		return obj;
	}

}
// 模擬類。
class Foo{
	int a = 10;
	double b = 20;
	
	public double show(int p,String str){
		System.out.println("調用方法傳入的值是:"+str);
		return a+b+p;
	}
	
	public Foo(){
		
	}
	
	public Foo(int a,int b){
		
		
	}
	
}

2


package am1;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Properties;

public class ReFactory {

	
	// 兩個方法。通過key 返回value。
	public static String getVal(String name,String fileName){
		Properties pro = new Properties();
		try {
			pro.load(new FileInputStream(fileName));
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		String value = pro.getProperty(name);
		return value;
	}
	
	// 反射方法。
	public static Object getObj(String name){
		Class forName;
		Object obj = null;
		try {
			forName = Class.forName(name);
			obj = forName.newInstance();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return obj;
	}
	
	
	
}

8.3 反射 代碼塊

1


* Object  超類,所有
* 類的超類。 對象。
 * Class   字節碼對象,永遠唯一。
、
```java

public class Demo {

	public static void main(String[] args) throws Exception {
		String str1 = "abc";
		Class class1 = str1.getClass();
		Class  class2 = "abc".getClass();
		System.out.println(class1==class2);
		
		Foo foo = new Foo();
		Foo foo2 = new Foo();
		Class cFoo1 = foo.getClass();
		Class cFoo2 = foo2.getClass();
		System.out.println("******"+(foo==foo2));
		System.out.println("%%%%%%%%%%%%%"+(cFoo1==cFoo2));
		
		// 使用Class 對象進行 Object對象的反射。
		String fooName = "am.Foo";
		// Class.forName 就是反射。通過名稱反射出字節碼對象。
		Class forName = Class.forName(fooName);
		Object obj = forName.newInstance();
		Foo foo3 = (Foo)obj;
		System.out.println(foo3.a);
		Class forName1 = Class.forName(fooName);
		Object obj1 = forName1.newInstance();
		Foo foo4 = (Foo)obj1;
		System.out.println(foo4.a);
		
		System.out.println(foo3==foo4);
		System.out.println(forName==forName1);

	}

}

class Foo{
	public int a = 10;
}

2


/**
 * 
 * 反射:
 * 在開發中,框架插件數據庫等等第三方應用會提供包。比如數據庫驅動包。無法使用object創建對象。
 * 可以使用包名類名進行反射。從而得到對象。
 * 需要將第三方應用的包名.類名進行統一管理。所以使用properites文件進行管理。
 *
 */
public class Demo02 {

	public static void main(String[] args) throws Exception, Exception {
		// Properties 對象。
		Properties pro = new Properties();
		pro.load(new FileInputStream("db.properties"));
		// 通過文件的加載,可以獲得key value
		System.out.println(pro.getProperty("name"));
		
		// 通過名稱進行反射。
		Class forName = Class.forName(pro.getProperty("name"));
		Object obj = forName.newInstance();
		Student student = (Student)obj;
		System.out.println(student.a);
		student.show();

	}

}

3

package am;

public class Student {
	
	public int a = 10;
	
	public void show(){
		System.out.println("hello student"+a);
	}

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章