Java反射机制学习

什么是反射

在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

反射有什么用

1,在运行时判断任意一个对象所属的类;

2,在运行时构造任意一个类的对象;

3,在运行时判断任意一个类所具有的成员变量和方法;

4,在运行时调用任意一个对象的方法;

5,生成动态代理。

实现Java反射的类

1)Class:它表示正在运行的Java应用程序中的类和接口
2)Field:提供有关类或接口的属性信息,以及对它的动态访问权限
3)Constructor:提供关于类的单个构造方法的信息以及对它的访问权限
4)Method:提供关于类或接口中某个方法信息

注意:Class类是Java反射中最重要的一个功能类,所有获取对象的信息(包括:方法/属性/构造方法/访问权限)都需要它来实现

 

编写Java反射程序的步骤:

1)必须首先获取一个类的Class对象
例如:
  Class c1 = Test.class;
  Class c2 = Class.forName(“com.reflection.Test”);
  Class c3 = new Test().getClass();

2)然后分别调用Class对象中的方法来获取一个类的属性/方法/构造方法的结构 注意:如果要能够正常的获取类中方法/属性/构造方法应该重点掌握如下的反射类

  Field
  Constructor
  Method

在此给出一个总结性的例子:

package com.gbx;

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;

interface IBase{
	void show();
}
class Base{
	
}
class Person extends Base implements IBase{
	private int id;
	public String name;
	protected int[] ages;
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Person() {
		super();
		// TODO Auto-generated constructor stub
	}
	public Person(int id, String name, int[] ages) {
		super();
		this.id = id;
		this.name = name;
		this.ages = ages;
	}
	@Override
	public void show() {
		System.out.println("人物信息为:" +id + " " + name + " " + ages);
	}
}
public class Test {
	
	/*
	 * 动态获取指定类的各种信息
	 * 1,在运行时判断任意一个对象所属的类;
	 * 2,在运行时构造任意一个类的对象;
	 * 3,在运行时判断任意一个类所具有的成员变量和方法;
	 * 4,在运行时调用任意一个对象的方法;
	 */
	public static void test1() throws ClassNotFoundException{
		Class c1 = Class.forName("com.gbx.Person");
		Class c2 = Person.class;
		Class c3 = new Person().getClass();
		
		/*
		 * 获取类所在包名, 通过输出可以看到, 这三种方式得到的Class是一样的
		 */
		String packe1 = c1.getPackage().toString();
		String packe2 = c2.getPackage().toString();
		String packe3 = c3.getPackage().toString();
		System.out.println(" packe1 = " + packe1 + "\n packe2 = " + packe2 + "\n packe3 = " + packe3);
		System.out.println("c1 == c2 : " + (c1 == c2) + "c2 == c3" + (c2 == c3));
		
		/*
		 * 获得类的访问修饰符
		 */
		int mod = c1.getModifiers();
		//可以输出看看
		//System.out.println(Modifier.toString(0) + " : " + Modifier.toString(1) + " : " +Modifier.toString(2) + " : " + Modifier.toString(3) + ":" + Modifier.toString(4));
		System.out.println(Modifier.toString(mod));
		
		/*
		 * 获取制定类的完全限定名字
		 */
		String calssName = c1.getName();
		System.out.println("calssName = " + calssName);
		
		/*
		 * 获取指定类的父类
		 */
		Class superCalss = c1.getSuperclass();
		System.out.println("superClassName = " + superCalss.getName());
		
		/*
		 * 获取指定类的实现的接口
		 */
		Class[] interfaces = c1.getInterfaces();
		for (Class inf : interfaces) {
			System.out.println("interface name : " + inf.getName());
		}
		
		//一下三部分的获取对于我们来说至关重要。。分别是:构造函数, 成员变量, 成员方法
		
		/*
		 * 获取指定类的构造函数  涉及的类:Constructor
		 */
		Constructor[] constructors = c1.getConstructors();
		System.out.println("构造方法有:");
		for (Constructor c : constructors) {
			//访问修饰符
			mod = c.getModifiers();
			String modfier = Modifier.toString(mod);
			//构造函数名字
			String name = c.getName();
			System.out.print(modfier + " " + name + "(");
			//参数列表
			Class[] paramTypes = c.getParameterTypes();
			for (int i  = 0; i < paramTypes.length; ++i) {
				if (i > 0) {
					System.out.print(",");
				}
				if (paramTypes[i].isArray()) {
					System.out.print(paramTypes[i].getComponentType().getName() + " [] ");
				} else {
					System.out.print(paramTypes[i].getName());
				}
			}
			System.out.println(")");
		}
		
		/*
		 * 获取指定类的成员变量 涉及到的类 Field
		 */
		Field[] fields = c1.getDeclaredFields();
		System.out.println("声明的成员变量有:");
		for (Field field : fields) {
			mod = field.getModifiers();
			String modifier = Modifier.toString(mod);
			System.out.print(modifier + " ");
					
			Class type = field.getType();
			if (type.isArray()) {
				System.out.print(type.getComponentType().getName() + " ");
			} else {
				System.out.print(type.getName() + " ");
			}
			String name = field.getName();
			System.out.println(name);
		}
		
		/*
		 * 获取指定类的成员方法 涉及的类Method
		 */
		Method[] methods = c1.getDeclaredMethods();
		System.out.println("成员方法有:");
		
		for (Method method :methods) {
			mod = method.getModifiers();
			String modifer = Modifier.toString(mod);
			System.out.print(modifer + " ");
			
			Class returnType = method.getReturnType();
			if (returnType.isArray()) {
				System.out.print(returnType.getComponentType().getName() + " ");
			} else {
				System.out.print(returnType.getName() + " ");
			}
			String name = method.getName();
			System.out.print(name + " ( ");
			Class[] paramTypes = method.getParameterTypes();
			for (int i = 0; i < paramTypes.length; ++i) {
				if (i > 0){
					System.out.println(",");
				}
				if (paramTypes[i].isArray()) {
					System.out.print(paramTypes[i].getComponentType().getName());
				} else {
					System.out.print(paramTypes[i].getName());
				}
			}
			System.out.println(" )");
		}
	}
	/*
	 * 生成动态代理。
	 */
	public static void test2() throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {
		Class c1 = Class.forName("com.gbx.Person");
		Person p = (Person)c1.newInstance();
		System.out.println("id  = " + p.getId());
		System.out.println("name = " + p.getName());
		
		Method method = c1.getDeclaredMethod("setName", String.class);
		method.setAccessible(true); //通过这一步设置我们甚至可以访问private的成员
		method.invoke(p, "小明");
		System.out.println("id  = " + p.getId());
		System.out.println("name = " + p.getName());
		
		
		
	}
	public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {
		test1();
		test2();
	}
}

输出:
 packe1 = package com.gbx
 packe2 = package com.gbx
 packe3 = package com.gbx
c1 == c2 : truec2 == c3true

calssName = com.gbx.Person
superClassName = com.gbx.Base
interface name : com.gbx.IBase
构造方法有:
public com.gbx.Person(int,java.lang.String,int [] )
public com.gbx.Person()
声明的成员变量有:
private int id
public java.lang.String name
protected int ages
成员方法有:
public void setId ( int )
public void show (  )
public java.lang.String getName (  )
public int getId (  )
public void setName ( java.lang.String )
id  = 0
name = null
id  = 0
name = 小明

  

 

反射调用参数维数组的方法:

public class DemoTest {
	/*
	 * 利用反射对参数是数组的方法的调用。
	 * 由于JDK5之前没有可变参数, 我们如果实现参数任意的话,就需要使用object[]来实现
	 * JDK5出现之后我们有了可变参数的就很方便了,但是为了兼容之前的代码,我们的可变参数接受数组,
	 * 然后将数组中的变量一个一个的放入对应的对应的变量。
	 * 如果方法参数是数组,例如public void show(String[] res)
	 * method.invoke(1,2);第二个参数接受的是的可变参数,我们传入一个数组的话,他会将数组中的第一
	 * 个值作为res的。后边的继续作为下一个参数。所以不会找到
	 */
	@Test
	public void test() throws ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		Class clazz =  Class.forName("com.cn.gbx.Person");
		Method method = clazz.getMethod("main",String[].class);
		method.invoke(null, new Object[]{new String[]{"a", "b"}});// 第一种解决方案
	}
	
	@Test
	public void test2() throws ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		Person p = new Person();
		Class<?> clazz =  Class.forName("com.cn.gbx.Person");
		Method method = clazz.getMethod("show", String[].class);
		method.invoke(p, (Object)new String[]{"aa","bb"}); //第二种解决方案
		
	}
}


package com.cn.gbx;

public class Person {
	
	public static void main(String[] args) {
		System.out.println("main invoke ...");
	}
	
	public void show(String[] res) {
		System.out.println("string[] res");
		for (String s : res) {
			System.out.println(s);
		}
	}
}

  

 

 

posted @ 2013-11-21 17:24  E_star  阅读(305)  评论(0编辑  收藏  举报