java反射

Java反射涉及的幾個類分別爲Class,Filed,Methods,Constructor,Modifier,AccessibleObject的幾個類。java

咱們定義一個 Employee類web

package util;

import java.util.Date;
import java.util.GregorianCalendar;

public class Employee {
	private String name;
	private double salary;
	private Date hireDay;

	public Employee(String n, double s, int year, int month, int day) {
		name = n;
		salary = s;
		GregorianCalendar calendar = new GregorianCalendar(year, month - 1, day);
		hireDay = calendar.getTime();
	}

	public String getName() {
		return name;
	}

	public double getSalary() {
		return salary;
	}

	public Date getHireDay() {
		return hireDay;
	}

	public void raiseSalary(double byPercent) {
		double raise = salary * byPercent / 100;
		salary += raise;
	}
}

Employee爲一個類,而代碼apache

Employee harry=new Employee("Harry Hacker",3500,10,1,1989);

定義了一個 對象harry, 類Employee用來描述 對象harry的信息,而Java虛擬機在運行的時候須要一個類來描述 類Employee的信息,這個類就是 Class,稱之爲 類型,能夠用來獲取一個類的全部域 Field,構造器 Constructor,方法 Method。 反射的兩個很重要的兩個能力。分析一個類和執行任意方法。數組

分析一個類

package util;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Scanner;

import org.apache.commons.lang3.StringUtils;

public class ReflectionTest {
	public static void main(String[] args) {
		String name;
		if (args.length > 0) {
			name = args[0];
		} else {
			Scanner scanner = new Scanner(System.in);
			name = scanner.nextLine();
		}

		try {
			Class cl = Class.forName(name);
			Class supercl = cl.getSuperclass();
			String modifier = Modifier.toString(cl.getModifiers());
			if (modifier != null && modifier.length() > 0) {
				System.out.print(modifier + " ");
			}
			System.out.print("class " + name);
			Double aDouble = 0.0;
			if (supercl != null && supercl != Object.class) {
				System.out.print(" extends " + supercl.getName());
			}
			System.out.print("\n{\n");
			printConstructors(cl);
			printMethods(cl);
			printFields(cl);
			System.out.print("}\n");
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	//打印構造函數
	public static void printConstructors(Class cl) {
		Constructor[] constructors = cl.getDeclaredConstructors();
		for (Constructor constructor : constructors) {
			String name = constructor.getName();
			String modifier = Modifier.toString(constructor.getModifiers());
			System.out.print(" ");
			// System.out.print(modifier+" "+name+"(");
			if (modifier!=null&&modifier.length()>0) {
				System.out.print(modifier+" ");
			}
			System.out.print(name+" (");
			Class[] paraTypes=constructor.getParameterTypes();
			for(int i=0;i<paraTypes.length;i++){
				if (i>0) {
					System.out.print(",");
				}
				System.out.print(paraTypes[i].getName());
			}
			System.out.println(");");

		}
	}
	
	//打印成員變量
	public static void printFields(Class cl){
		
		Field[] fields=cl.getDeclaredFields();
		for (Field field : fields) {
			String modifier=Modifier.toString(field.getModifiers());
			Class type=field.getType();
			String name=field.getName();
			System.out.print(" ");
			if (modifier.length()>0) {
				System.out.print(modifier+"  ");
			}
			System.out.println(type.getName()+"  "+name+";");
		}
		
	}
	
	//打印方法名
	public static void printMethods(Class cl){
		 Method[] methods=cl.getDeclaredMethods();
		 for (Method method : methods) {
			 String name=method.getName();
			 String modifier=Modifier.toString(method.getModifiers());
			 System.out.print(" ");
			 if (modifier.length()>0) {
				System.out.print(modifier+" ");
			}
			 System.out.print(method.getName()+"(");
			 Class[] paraTypes=method.getParameterTypes();
			 for(int i=0;i<paraTypes.length;i++){
				 if (i>0) {
					System.out.print(",");
				}
				 System.out.print(method.getName());
			 }
			 System.out.println("};");
		}
	}
}

執行任意方法

package study_web;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class MethodTest {
	public static void main(String[] args) {
		/*System.out.println(Math.sqrt(4));*/
		try {
			Class cl=Class.forName("java.lang.Math");
			try {
				Method method=cl.getDeclaredMethod("sqrt", double.class);
				/*Class returnType=method.getReturnType();*/
				Double value=(Double) method.invoke(null, 4.0);
				System.out.println(value);
			} catch (NoSuchMethodException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (SecurityException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IllegalArgumentException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (InvocationTargetException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

在這個demo中咱們用反射執行了Math.sqrt方法函數

獲取一個域,並從新賦值

package study_web;

import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;

import util.Employee;

public class ReflectTest {
	public static void main(String[] args) {
		Employee harry=new Employee("Harry Hacker",3500,10,1,1989);
		Class cl=harry.getClass();
		try {
			Field field=cl.getDeclaredField("name");
			/*AccessibleObject[] array=new AccessibleObject[]{field};
			AccessibleObject.setAccessible(array, true);*/
			field.setAccessible(true);
			field.set(harry, "li yuahng");
			System.out.println(harry.getName());
		} catch (NoSuchFieldException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		}
	}
}

由於Java反射默認聽從Java訪問權限控制,因此咱們能夠使用代碼:code

AccessibleObject[] array=new AccessibleObject[]{field};
	    AccessibleObject.setAccessible(array, true);

或者代碼:對象

field.setAccessible(true);

使得Field域可被訪問。繼承

一些重要的API

java.lang.Class

  • public static Class<?> forName(String className)

返回描述類名className的Class對象接口

  • public T newInstance()

返回這個類的新實例字符串

  • public Field[] getFields()
  • public Field[] getDeclaredFields()

getFields方法返回一個包含Field對象的數組,這些對象記錄了這個類或其它超類的公有域。getDeclaredFields方法也將返回包含Field對象的數組,這些對象記錄了這個類的所有域。若是類中沒有域,或者Class對象描述的是基本類型或者數據類型,這些方法將返回一個長度爲0的數組

  • public Method[] getMethods()
  • public Method[] getDeclaredMethods()

返回包含 Method對象的數組:getMethods將返回全部的公有方法,包括從超類繼承來的公有方法;getDeclaredMethods返回這個類或接口的的所有方法,但不包括由超類繼承來的方法。

  • public Constructor<?>[] getDeclaredConstructors()
  • public Constructor<?>[] getConstructors()

同上,不作解釋

  • public native int getModifiers()

返回一個用於描述構造器、方法、域的修飾符的整型數值。使用Modifier類中的這個方法能夠分析這個返回值。

###java.lang.reflect.Modifier

  • public static String toString(int mod)

返回modifiers中位設置的修飾符的字符串表示

java.lang.reflect.AccessibleObject

  • public void setAccessible(boolean flag)

爲反射對象設置可訪問標誌。flag爲true,代表屏蔽Java語言的訪問檢查,使得對象的私有屬性也能夠被查詢和設置

  • public boolean isAccessible()

返回反射對象可訪問標誌的值

  • public static void setAccessible(AccessibleObject[] array, boolean flag)

是一種設置對象數組可訪問標誌的快捷方法

java.lang.reflect.Field

  • public void set(Object obj, Object value)

用一個新值設置obj對象中Field對象表示的域

java.lang.reflect.Method

  • public Object invoke(Object obj, Object... args)

對帶有指定參數的指定對象調用由此 Method 對象表示的底層方法。

相關文章
相關標籤/搜索