Java基礎回顧 : 反射機制相關知識

★ . 反射機制的相關知識 : 

在Object 類之中定義了以下一個方法:

public final Class<?> getClass()

final修飾,所以此方法不能夠被子類所覆寫。這個方法上返回的是一個Class 類對象.

Class 類是一切反射的起源,而對於這個類的對象實例化方式一共分爲三種:
· 第一種:利用對象中的getClass()方法;
· 第二種:利用“類.class”實現實例化,在WEB 開發的框架中會用到;
· 第三種:利用Class 類的一個靜態方法操作:
public static Class<?> forName(String className) throws ClassNotFoundException    參數接收完整的“包.類”名稱。

★ . Class 類之中定義的一個方法:

public T newInstance()throws InstantiationException,IllegalAccessException
此方法的主要功能是進行新對象的實例化操作。

比如說正常情況下,肯定是直接利用關鍵字new 進行對象的實例化,而現在除了使用 new 之外 , 還可以使用另外一種方式實例化 —— 反射機制。

從開發而言,使用最多的還是關鍵字new,或者在考慮代碼進行解耦合性操作時纔會考慮到使用反射。

★ . Class 類裏面定義瞭如下的兩個取得構造方法的操作:

public Constructor<?>[] getConstructors()throws SecurityException
public Constructor<T> getConstructor(Class<?>... parameterTypes)throws NoSuchMethodException,SecurityException

★ . Class 類之中定義有如下的取得類之中方法的操作:

· 取得類之中的全部普通方法
public Method[] getMethods() throws SecurityException
· 取得類之中的指定方法
public Method getMethod(String name,Class<?>... parameterTypes)throws NoSuchMethodException,SecurityException

Method 類之中有一個非常重要的方法:
public Object invoke(Object obj,Object... args)throws IllegalAccessException,IllegalArgumentException,InvocationTargetException
invoke 的單詞表示的是調用,實際上指的就是調用指定的對象操作方法。

eg : 

package example;

import java.lang.reflect.Method;

class Book{
	private String title;
	
	public Book(){}
	
	public Book(String title){
		this.title = title;
	}

	public String getTitle() {
		return title;
	}

	public void setTitle(String title) {
		this.title = title;
	}
	
	@Override
	public String toString() {
		return "書名 : " + this.title;
	}
	
}

public class TestDemo {
	public static void main(String[] args) throws Exception {
		Class<?> clazz = Class.forName("example.Book");
		
		Object obj = clazz.newInstance();
		
		//已經知道要操作屬性的名稱
		String attributeName = "title";
		Method setMet = clazz.getMethod("set" + initCap(attributeName), String.class);
		Method getMet = clazz.getMethod("get" + initCap(attributeName));
		
		setMet.invoke(obj, "Java開發"); //相當於對象.setTitle
		System.out.println(getMet.invoke(obj));
	}
	
	/**
	 * 將一個字符串首字母大寫
	 * @param str
	 * @return
	 */
	public static String initCap(String str){
		return str.substring(0,1).toUpperCase() + str.substring(1);
	}
}

★ . Class 類裏面定義了可以取得類中屬性的操作:

· 取得本類中定義的全部屬性:
public Field[] getDeclaredFields()throws SecurityException
· 取得本類中定義的一個指定的屬性
public Field getDeclaredField(String name)throws NoSuchFieldException,SecurityException

· 取得本類中public修飾的屬性

public Field getField(String name)throws NoSuchFieldException,SecurityException


Field 類之中有如下兩個主要的方法:
· 設置屬性內容:
public void set(Object obj,Object value)throws IllegalArgumentException,IllegalAccessException
· 取得屬性內容:
public Object get(Object obj)throws IllegalArgumentException,IllegalAccessException


如果現在屬性進行了封裝,那麼要想操作就必須取消封裝,使用如下方法完成:
public void setAccessible(boolean flag)throws SecurityException


★ . 最後寫一個利用反射機制的工廠設計模式:

package example;

interface Fruit{
	public void eat();
}

class Apple implements Fruit {
	@Override
	public void eat() {
		System.out.println("喫蘋果.");
	}
}
class Orange implements Fruit {
	@Override
	public void eat() {
		System.out.println("喫橘子.");
	}
}
class Cherry implements Fruit {
	@Override
	public void eat() {
		System.out.println("喫櫻桃.");
	}
}

class FruitFactory {
	public static Fruit getInstance(String className){
		Fruit f = null;
		try {
			Class<?> clazz = Class.forName(className);
			f = (Fruit) clazz.newInstance();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return f;
	}
}

public class TestDemo {
	public static void main(String[] args) throws Exception {
		Fruit f = FruitFactory.getInstance("example.Cherry");
		f.eat();
	}
	
}


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