反射的基本用法

反射

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

一 获取Class类对象

获取Class类对象, 有三种方式:
1. Class Class.forName(“完整的包名.类名”);(最常用)
例如: sueyun.cn.reflect.Person
2. Class 类名.class
3. Class 类对象.getClass();

//首先创建 一个实体类用于演示反射的用法
public class Person {
	// 成员变量 Field
	private Integer id;
	private String name;

	public int test = 20;
	public static int testStatic = 30;

	public Person() {
	}

	public Person(Integer id) {
		super();
		this.id = id;
	}

	public Person(String name) {
		super();
		this.name = name;
	}

	public Person(Integer id, String name, int test) {
		super();
		this.id = id;
		this.name = name;
		this.test = test;
	}

	private Person(Integer id, String name) {
		super();
		this.id = id;
		this.name = name;
	}

	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	private void testPrivate() {
		System.out.println("私有化成员方法");
	}

	public static void testStaticMethod() {
		System.out.println("静态成员方法");
	}

	@Override
	public String toString() {
		return "Person [id=" + id + ", name=" + name + ", test=" + test + "]";
	}

	public void game() {
		System.out.println("pubg");
	}

	public void game(String name) {
		System.out.println(this.getName() + "玩" + name);
	}

}

下面通过反射方法获取Person类的Class类对象

public class GetClassObject {
	public static void main(String[] args) throws ClassNotFoundException {

		// Class.forName("完整的包名.类名");
		/*
		 * 最常用!!!
		 */
		Class cls1 = Class.forName("sueyun.cn.reflact.Person");

		// 类名.class
		Class cls2 = Person.class;

		// 类对象.getClass();
		Class cls3 = new Person().getClass();

		System.out.println(cls1);
		System.out.println(cls2);
		System.out.println(cls3);

		System.out.println(cls1 == cls2);
		System.out.println(cls2 == cls3);
		System.out.println(cls3 == cls1);
	}
}	

反射获取类对象

二 获取Constructor(构造器)

首先获取Class类对象,然后通过Class类对象获取该类的构造器。常用方法有:

  1. Constructor getConstructor(Class… parameterTypes);
    根据参数类型,获取指定参数类型的构造方法,只能获取非私有化的构造方法 Class类型 …不定长参数,要求参数的类型都是Class类型,但是参数的个数不受限制 要求参数的顺序,类型和个数必须一一对应,否则报NoSuchMethodException异常根据参数类型,获取指定参数类型的构造方法,只能获取非私有化的构造方法
    Class类型 …不定长参数,要求参数的类型都是Class类型,但是参数的个数不受限制 要求参数的顺序,类型和个数必须一一对应,否则报NoSuchMethodException异常

  2. Constructor[] getConstructors(); 获取当前类内的所有非私有化构造方法

  3. Constructor getDeclaredConstructor(Class… parameterTypes); 根据参数类型,获取指定参数类型的构造方法,可以获取私有化的构造方法
    Class类型 …不定长参数,要求参数的类型都是Class类型,但是参数的个数不受限制 Class类型 …不定长参数,要求参数的类型都是Class类型,但是参数的个数不受限制

  4. Constructor[] getDeclaredConstructors(); 获取当前类内的所有构造方法,包括私有化构造方法

  5. Object newInstance(Object… args); 通过Constructor类对象,调用newInstance方法,创建类对象 Object… 不定长参数,用于传入构造方法所需的参数

  6. setAccessible(boolean) ; 给予私有化构造方法,成员方法,成员变量操作权限

代码中有方法如何使用的详细注释:

/**
 * 通过Class类对象,来获取Constructor类对象
 * 
 */
public class GetConstructorObject {
	public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException,
			InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		// 首先获取Class类对象
		Class cls = Class.forName("sueyun.cn.reflact.Person");

		/*
		 * Constructor[] getConstructors(); 获取当前类内的所有非私有化构造方法
		 */
		Constructor[] allCons = cls.getConstructors();
		for (Constructor constructor : allCons) {
			System.out.println(constructor);
		}

		/*
		 * 暴力反射 Constructor[] getDeclaredConstructors(); 获取当前类内的所有构造方法,包括私有化构造方法
		 */
		Constructor[] allC = cls.getDeclaredConstructors();
		for (Constructor constructor : allC) {
			System.out.println(constructor);
		}

		/*
		 * Constructor getConstructor(Class... parameterTypes);
		 * 根据参数类型,获取指定参数类型的构造方法,只能获取非私有化的构造方法 Class类型 ...
		 * 不定长参数,要求参数的类型都是Class类型,但是参数的个数不受限制 要求参数的顺序,类型和个数必须一一对应,否则
		 * NoSuchMethodException
		 */
		Constructor nullParamCon = cls.getConstructor(null);
		Constructor tParamCon = cls.getConstructor(Integer.class, String.class, int.class);
		// cls.getConstructor(Integer.class, String.class);
		System.out.println(nullParamCon);
		System.out.println(tParamCon);

		/*
		 * 暴力反射 Constructor getDeclaredConstructor(Class... parameterTypes);
		 * 根据参数类型,获取指定参数类型的构造方法,可以获取私有化的构造方法 Class类型 ...
		 * 不定长参数,要求参数的类型都是Class类型,但是参数的个数不受限制
		 */
		Constructor privateCon = cls.getDeclaredConstructor(Integer.class, String.class);
		System.out.println(privateCon);

		/*
		 * Object newInstance(Object... initargs);
		 * 通过Constructor类对象,调用newInstance方法,创建类对象 Object... 不定长参数,用于传入构造方法所需的参数
		 */
		Person p1 = (Person) nullParamCon.newInstance(null);
		p1.setId(1);
		p1.setName("张三");
		System.out.println(p1);

		Person p2 = (Person) tParamCon.newInstance(1, "他很帅", 10);
		System.out.println(p2);

		/*
		 * setAccessible(boolean) 给予私有化构造方法,成员方法,成员变量操作权限
		 */
		privateCon.setAccessible(true);
		Person p3 = (Person) privateCon.newInstance(2, "演示");
		System.out.println(p3);
	}
}

在这里插入图片描述

三 获取Field成员变量

  1. Field getField(String fieldName); 根据指定的成员变量名,获取指定的成员变量,只能获取非私有化成员变量
  2. Field getDeclaredField(String fieldName); 根据指定的成员变量名,获取指定的成员变量,可以获取私有化成员变量
  3. Field[] getFields(); 获取类内的所有非私有化成员变量
  4. Field[] getDeclaredFields(); 获取类内的所有成员变量,包括私有化成员变量
  5. set(Object obj, Object value); Obj: 执行或者说调用当前成员变量的类对象 value: 需要给成员变量赋的值
public class GetFieldObject {
	public static void main(String[] args)
			throws ClassNotFoundException, NoSuchFieldException, SecurityException, IllegalArgumentException,
			IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException {
		Class cls = Class.forName("sueyun.cn.reflact.Person");

		/*
		 * Field[] getFields(); 获取类内的所有非私有化成员变量
		 */
		Field[] fields = cls.getFields();
		for (Field field : fields) {
			System.out.println(field);
		}
		System.out.println();

		/*
		 * Field[] getDeclaredFields(); 获取类内的所有成员变量,包括私有化成员变量
		 */
		Field[] declaredFields = cls.getDeclaredFields();
		for (Field field : declaredFields) {
			System.out.println(field);
		}

		/*
		 * Field getField(String fieldName); 根据指定的成员变量名,获取指定的成员变量,只能获取非私有化成员变量
		 */
		Field test = cls.getField("test");
		System.out.println(test);
		System.out.println();
		/*
		 * Field getDeclaredField(String fieldName); 根据指定的成员变量名,获取指定的成员变量,可以获取私有化成员变量
		 */
		Field id = cls.getDeclaredField("id");
		Field name = cls.getDeclaredField("name");

		System.out.println(id);
		System.out.println(name);

		/*
		 * set(Object obj, Object value); Obj: 执行或者说调用当前成员变量的类对象 value: 给成员变量赋值
		 */
		Person p = (Person) cls.getConstructor(null).newInstance(null);
		test.set(p, 100);
		System.out.println(p.test);

		id.setAccessible(true);
		name.setAccessible(true);

		id.set(p, 1);
		name.set(p, "12345678");

		System.out.println(p);

		Field testStatic = cls.getField("testStatic");
		testStatic.set(null, 10);
		System.out.println(p.testStatic);
	}
}

在这里插入图片描述

四 获取Method成员方法

  1. Method getMethod(String methodName, Class… parameterTypes);
    根据方法名和参数类型,获取指定的非私有化成员方法 methodName:当前方法的名字 parameterTypes: 不定长参数,用于约束方法的参数
  2. Method getDeclaredMethod(String methodName, Class… parameterTypes);
    根据方法名和参数类型,可以获取指定的私有化成员方法 methodName:当前方法的名字 parameterTypes: 不定长参数,用于约束方法的参数
  3. Method[] getMethods(); 获取类内所有非私有化成员方法,和从父类继承而来的可以在子类使用的成员方法
  4. Method[] getDeclaredMethods(); 获取当前类的所有成员方法,包括私有化成员方法,但是不包含从父类继承而来的方法
  5. invoke(Object obj, Object… args); 指定Method类对象方法
    obj: 执行当前方法的类对象
    args:不定长参数,是当前执行方法所需的实际参数列表
public class GetMethodObject {
	public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException,
			IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException {
		Class cls = Class.forName("sueyun.cn.reflact");

		/*
		 * Method[] getMethods(); 获取类内非私有化成员方法,和从父类继承而来的可以在子类使用的成员方法
		 */
		Method[] allMethods = cls.getMethods();
		for (Method method : allMethods) {
			System.out.println(method);
		}
		System.out.println();

		/*
		 * Method[] getDeclaredMethods(); 获取当前类的所有成员方法,包括私有化成员方法,但是不包含从父类继承而来的方法
		 */
		Method[] declaredMethods = cls.getDeclaredMethods();
		for (Method method : declaredMethods) {
			System.out.println(method);
		}
		System.out.println();

		/*
		 * Method getMethod(String methodName, Class... parameterTypes);
		 * 根据方法名和参数类型,获取指定的非私有化成员方法 methodName:当前方法的名字 parameterTypes: 不定长参数,用于约束方法的参数
		 */
		Method gameMethos1 = cls.getMethod("game", null);
		Method gameMethos2 = cls.getMethod("game", String.class);

		System.out.println(gameMethos1);
		System.out.println(gameMethos2);

		/*
		 * Method getDeclaredMethod(String methodName, Class.. parameterTypes);
		 * 根据方法名和参数类型,可以获取指定的私有化成员方法 methodName:当前方法的名字 parameterTypes: 不定长参数,用于约束方法的参数
		 */
		Method privateMethod = cls.getDeclaredMethod("testPrivate", null);
		System.out.println(privateMethod);
		System.out.println();
		/*
		 * invoke(Object obj, Object... args); 指定Method类对象方法 obj: 执行当前方法的类对象 args:
		 * 不定长参数,是当前执行方法所需的实际参数列表
		 * 
		 * cls.getConstructor(null).newInstance(null) 通过反射获取构造方法,并且创建对象
		 */
		gameMethos1.invoke(cls.getConstructor(null).newInstance(null), null);
		gameMethos2.invoke(cls.getConstructor(Integer.class, String.class, int.class).newInstance(1, "反射没有那么难", 20),
				"张三");

		privateMethod.setAccessible(true);
		privateMethod.invoke(cls.getConstructor(null).newInstance(null), null);

		// 执行类内的静态成员方法,invoke第一个参数可以是null
		cls.getMethod("testStaticMethod", null).invoke(null, null);
	}
}

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/Sueyun/article/details/83654708