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);

		}

	}

}

  

 

 

你可能感兴趣的:(java反射机制)