1. 程式人生 > >Java -- 類載入器&反射&代理

Java -- 類載入器&反射&代理

類載入&類載入器

類的載入描述:

反射&reflect

JAVA反射機制是在執行狀態中,對於任意一個類,都能夠知道這個類的所有屬性和方法;對於任意一個物件,都能夠呼叫它的任意一個方法和屬性;這種動態獲取的資訊以及動態呼叫物件的方法的功能稱為java語言的反射機制。

要想解剖一個類,必須先要獲取到該類的位元組碼檔案物件。而解剖使用的就是Class類中的方法.所以先要獲取到每一個位元組碼檔案對應的Class型別的物件。

  • Class類的獲取

    /*for example*/
    public class TestClass {
    	public static void main(String[] args) throws ClassNotFoundException {
    		/* 類的三種獲取方式 */
    		/* the first... */
    		Person p = new Person();
    		Class pClass = p.getClass();
    		System.out.println(pClass);
    
    		/* the second... */
    		Class sClass = Person.class;
    		System.out.println(sClass);
    
    		/* the third... */
    		Class tClass = Class.forName("ReflectionTools.Person");
    		System.out.println(tClass);
    	}
    }
    
  • Class類構造方法的獲取

    /*for example*/
    /* 僅僅顯示由public修飾的構造方法 */
    	Constructor[] con = tClass.getConstructors();
    	for (Object obj : con)
    		System.out.println(obj);
    	Constructor[] conAll = tClass.getDeclaredConstructors();
    	System.out.println("------- this is a dividing line --------");
    
    /* 所有的構造方法都顯示出來. */
    	for (Object obj : conAll)
    		System.out.println(obj);
    	System.out.println("------- this is a dividing line --------");
    
  • Class類欄位的獲取

    /*for example*/
    與構造方法完全一樣,用Field替換對應的部分即可。
    
  • Class類成員方法的獲取

    /*for example*/
    不同之處在於getMethods方法獲取的是獲取的所有方法,包括父類的的public修飾的。
    getDeclaredMethods是自己的所有修飾符修飾的成員方法。
    
  • 使用帶Declared的函式獲取的函式是完整的,但是若需要使用指定的成員變數與成員方法,則可以利用反射。使用對應的帶引數的函式+函式名稱即可呼叫,若是非公有的,可以使用setAccessiable強制呼叫。

    /*for example   非區域性的使用*/
    
    /*PJO定義一個簡單的類*/
    package ReflectionTools;
    
    import java.lang.reflect.Constructor;
    import java.lang.reflect.Field;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    
    class Person {
    	private String name;
    	private int age;
    	private String address;
    
    	/* 私有的帶參構造方法。 */
    	private Person(String name, int age) {
    		this.name = name;
    		this.age = age;
    	}
    
    	public Person(String name) {
    		this.name = name;
    	}
    
    	public Person(String name, int age, String address) {
    		super();
    		this.name = name;
    		this.age = age;
    		this.address = address;
    	}
    
    	/* 無參構造方法. */
    	Person() {
    	}
    
    	public String getName() {
    		return name;
    	}
    
    	public void setName(String name) {
    		this.name = name;
    	}
    
    	public int getAge() {
    		return age;
    	}
    
    	private void setAge(int age) {
    		this.age = age;
    	}
    
    	public String getAddress() {
    		return address;
    	}
    
    	public void setAddress(String address) {
    		this.address = address;
    	}
    
    	@Override
    	public String toString() {
    		return "Person [name=" + name + ", age=" + age + ", address=" + address
    				+ "]";
    	}
    }
    
    
    /*測試主函式*/
    public class TestClass {
    
    	public static void main(String[] args) throws ClassNotFoundException,
    			NoSuchMethodException, SecurityException, InstantiationException,
    			IllegalAccessException, IllegalArgumentException,
    			InvocationTargetException, NoSuchFieldException {
    		/* 類的三種獲取方式 */
    		/* the first... */
    		Person p = new Person();
    		Class pClass = p.getClass();
    		System.out.println(pClass);
    
    		/* the second... */
    		Class sClass = Person.class;
    		System.out.println(sClass);
    
    		/* the third... */
    		Class tClass = Class.forName("ReflectionTools.Person");
    		System.out.println(tClass);
    
    		System.out.println("-------this is a dividing line--------");
    
    		/* 僅僅顯示由public修飾的構造方法 */
    		Constructor[] con = tClass.getConstructors();
    		for (Object obj : con)
    			System.out.println(obj);
    		Constructor[] conAll = tClass.getDeclaredConstructors();
    		System.out.println("------- this is a dividing line --------");
    		/* 所有的構造方法都顯示出來. */
    		for (Object obj : conAll)
    			System.out.println(obj);
    		System.out.println("------- this is a dividing line --------");
    
    		/* 無引數構造方法的使用。 */
    		Constructor conSpecific = tClass.getDeclaredConstructor();
    		Object obj = conSpecific.newInstance();
    		
    		/*呼叫private修飾的變數*/
    		Field fieldSpecific = tClass.getDeclaredField("name");
    		fieldSpecific.setAccessible(true);
    		fieldSpecific.set(obj, "Tom");
    
    		/* 呼叫非public修飾的成員方法 */
    		Method methodSpecific = tClass.getDeclaredMethod("setAge", int.class);
    		methodSpecific.setAccessible(true);
    		methodSpecific.invoke(obj, 5);
    		System.out.println(obj);
    	}
    }
    
    /*控制檯輸出結果為:*/
    	class ReflectionTools.Person
    	class ReflectionTools.Person
    	class ReflectionTools.Person
    	-------this is a dividing line--------
    	public ReflectionTools.Person(java.lang.String,int,java.lang.String)
    	public ReflectionTools.Person(java.lang.String)
    	------- this is a dividing line --------
    	private ReflectionTools.Person(java.lang.String,int)
    	ReflectionTools.Person()
    	public ReflectionTools.Person(java.lang.String,int,java.lang.String)
    	public ReflectionTools.Person(java.lang.String)
    	------- this is a dividing line --------
    	Person [name=Tom, age=5, address=null]
    
  • 反射的應用

    • 構造一個動態的物件呼叫動態的方法:

      /*for example*/
      /**config.ini是配置class類和對應方法的。/
      
      package ReflectionTools;
      
      import java.io.FileReader;
      import java.io.IOException;
      import java.lang.reflect.Constructor;
      import java.lang.reflect.InvocationTargetException;
      import java.lang.reflect.Method;
      import java.util.Properties;
      
      /*config.ini*/
      	/*content:
      	 className = ReflectionTools.personTest
      	 classValue = hobby
      	 */
      
      class animal {
      	private String name;
      
      	public animal() {
      	}
      
      	public void show() {
      		System.out.println(this.name + "this is animailShow!");
      	}
      }
      
      class personTest {
      	private String name;
      	private int age;
      	private String address;
      
      	public personTest() {
      	}
      
      	public void hobby() {
      		System.out.println(this.name + "this is a personHobby!" + this.age
      				+ this.address);
      	}
      }
      
      public class ReflectionApp {
      	public static void main(String[] args) throws IOException,
      			ClassNotFoundException, InstantiationException,
      			IllegalAccessException, IllegalArgumentException,
      			InvocationTargetException, NoSuchMethodException, SecurityException {
      		/* 使用throws不必初始化,直接異常彈出,這樣的目的是為了防止空指標異常。 */
      
      		FileReader fileReader = new FileReader("config.ini");
      		Properties keyValue = new Properties();
      		keyValue.load(fileReader);
      		fileReader.close();
      
      		String getNameID = keyValue.getProperty("className");
      		String getValueID = keyValue.getProperty("classValue");
      		Class classFiles = Class.forName(getNameID);
      
      		Constructor con = classFiles.getConstructor();
      		Object obj = con.newInstance();
      		Method meTest = classFiles.getDeclaredMethod(getValueID);
      		meTest.invoke(obj);
      
      	}
      }		
      
    • 反射修改泛型

      import java.lang.reflect.InvocationTargetException;
      import java.lang.reflect.Method;
      import java.util.ArrayList;
      
      /*
       * 我給你ArrayList<Integer>的一個物件,要求在這個集合中新增一個字串資料。
       */
      public class ArrayLis{
      	public static void main(String[] args) throws NoSuchMethodException,
      			SecurityException, IllegalAccessException,
      			IllegalArgumentException, InvocationTargetException {
      
      		/*建立集合物件*/
      		ArrayList<Integer> array = new ArrayList<Integer>();
      
      		Class classfile = array.getClass(); /*集合ArrayList的class檔案物件*/
      		Method me = classfile.getMethod("add", Object.class);
      
      		me.invoke(array, "hello"); /*呼叫array的add方法,傳入的值是hello.*/
      		me.invoke(array, "world");
      		System.out.println(array);
      	}
      		}
      
  • Proxy代理物件

    • 描述:代理一個物件的操作,結合InvocationHandler介面,只能實現對介面的代理。若要對類進行代理需要使用cglib。
    • tip:該類代理不會再框架中使用,故而略…