反射机制详解

一、反射机制图解

首先通过下图了解反射机制,然后会对各个部分结合示例详细解释。
在这里插入图片描述

二、获取Class类实例化对象的方式

1、Class.forName(“全类名”)

  • 将字节码文件加载进内存,返回Class对象。
  • 多用于配置文件,将类名定义在配置文件中。读取文件,加载类。
  • 推荐使用这种方式。

2、类名.class

  • 通过类名的属性class获取。
  • 多用于参数的传递。

3、对象.getClass()

  • getClass()方法在Object类中定义着。
  • 多用于对象的获取字节码文件的方式。

示例代码如下

package com.zzu.reflect;

public class Test {

	public static void main(String[] args) throws Exception {
		//1.Class.forName("全类名")
		Class class1 = Class.forName("com.zzu.reflect.Student");
		System.out.println(class1);
		//2.类名.class
		Class class2 = Student.class;
		System.out.println(class2);
		//3.对象.getClass()
		Class class3 = new Student().getClass();
		System.out.println(class3);
		
		System.out.println(class1==class2);
		System.out.println(class1==class3);
	}
}

运行结果如下图:
在这里插入图片描述
结论:同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,不论通过哪一种方式获取的Class对象都是同一个。

三、构造方法

1、获取构造方法

通过Class类中某些方法可以获取对应类中声明的构造方法实例对象,这些方法有:

  1. Constructor<?>[] getConstructors():返回该Class对象表示类中包含的所有public构造方法(不含继承)所对应的Constructor对象数组。
  2. Constructor getConstrutor(Class<?>… parameterTypes):返回与该Class对象表示类中参数列表相匹配的public构造方法(不含继承)对应的Constructor对象。
  3. Constructor<?>[] getDeclaredConstructors():返回该Class对象表示类中声明的所有构造方法(不区分访问权限)所对应的Constructor对象数组。
  4. Constructor<T> getDeclaredConstructor(Class<?>… parameterTypes):返回与该Class对象表示类中参数列表相匹配的构造方法(不区分访问权限)对应的Constructor对象。

示例代码如下:

Student类
package com.zzu.reflect;

public class Student {

	private String name;
	private String mobile;
	private String a;
	protected String b;
	String c;
	private String d;
	
	public Student() {

	}
	public Student(String name) {
		this.name = name;
	}
	public Student(String name, String mobile) {
		this.name = name;
		this.mobile = mobile;
	}
	
	public void study(String subject) throws Exception {
		System.out.println("学习......"+subject);
	}
	public void read() {
		System.out.println("读书......");
	}
	@Override
	public String toString() {
		return "Student [name=" + name + ", mobile=" + mobile + ", a=" + a + ", b=" + b + ", c=" + c + ", d=" + d + "]";
	}
}

package com.zzu.reflect;
import java.lang.reflect.Constructor;

public class Test {

	public static void main(String[] args) throws Exception {
		Class clazz = Student.class;
//		 1. Constructor<?>[] getConstructors()		
		Constructor[] constructors = clazz.getConstructors();
		for (Constructor constructor : constructors) {
			System.out.println(constructor);
		}
		System.out.println("——————————");
//		 2. Constructor getConstrutor(Class<?>... parameterTypes)
		Constructor constructor = clazz.getConstructor(String.class);
		System.out.println(constructor);
		System.out.println("——————————");
//		 3. Constructor<?>[] getDeclaredConstructors()
		Constructor[] constructors2 = clazz.getDeclaredConstructors();
		for (Constructor constructor2 : constructors2) {
			System.out.println(constructors2);
		}		
		System.out.println("——————————");
//		 4. Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
		Constructor constructor1 = clazz.getDeclaredConstructor(String.class,String.class);
		System.out.println(constructor1);
	}
}

运行结果如下图:
在这里插入图片描述

2、查看构造方法信息

通过Constructor类中某些方法可以获取某个构造方法的信息,这些方法如下:

  1. Class<T> getDeclaringClass():返回声明Constructor对象对应构造方法的类的Class对象。
  2. int getModifiers():以整数形式返回Constructor对象表示的构造方法的修饰符。
  3. String getName() :以字符串形式返回Constructor对象所表示的构造方法的名称。
  4. Class<?>[] getParameterTypes():返回由Constructor对象所表示的构造方法的形参类型对应Class对象组成的数组 。如果构造方法没有参数,则数组长度为0。

示例代码如下:

package com.zzu.reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;

public class Test {

	public static void main(String[] args) throws Exception {
		Class clazz = Student.class;
		Constructor constructor = clazz.getConstructor(String.class);
//		 1. Class\<T> getDeclaringClass()
		Class class1 = constructor.getDeclaringClass();
		System.out.println(class1);
		System.out.println("——————————");
//		 2. int getModifiers()
		int i = constructor.getModifiers();
		String string = Modifier.toString(i);
		System.out.println(string);
		System.out.println("——————————");
//		 3. String getName()
		String name = constructor.getName();
		System.out.println(name);
		System.out.println("——————————");
//		 4. Class<?>[] getParameterTypes()
		Class[] parameterTypes = constructor.getParameterTypes();
		for (Class class2 : parameterTypes) {
			System.out.println(class2);
		}
	}
}

运行结果如下图:
在这里插入图片描述

3、操作构造方法

通过Constructor类中某些方法可以创建对象,这些方法如下:

  1. void setAccessible(boolean flag):调用构造方法时是否忽略访问权限的影响,true表示忽略,false表示不忽略。
  2. T newInstance(Object… initargs):使用此Constructor对象表示的构造方法来创建声明该构造方法类的新对象。initargs为传入该构造方法中的参数,如果该构造方法没有参数,则可设定为null或一个长度为0的数组。

示例代码如下:

package com.zzu.reflect;
import java.lang.reflect.Constructor;

public class Test {

	public static void main(String[] args) throws Exception {
		Class clazz = Student.class;
		Constructor constructor = clazz.getConstructor(String.class);
		Object object = constructor.newInstance("帅帅");
		System.out.println(object);
	}
}

运行结果如下图:
在这里插入图片描述

四、成员方法

1、获取成员方法

借助Class类中某些方法可以获取对应类中声明的成员方法实例对象,这些方法有:

  1. Method[] getMethods():返回该Class对象表示类或接口中所有public方法(含继承的)对应的Method对象数组。
  2. Method getMethod(String methodName, Class<?>… parameterTypes):返回与该Class对象表示类或接口中方法名和方法形参类型相匹配的public方法(含继承的)的Method对象。
  3. Method[] getDeclaredMethods():返回该Class对象表示类或接口内声明定义的所有访问权限的方法(不含继承的)对应的Method对象数组。
  4. Method getDeclaredMethod(String methodName,Class<?>… parameterTypes) :返回与该Class对象表示类或接口中方法名和方法形参类型相匹配方法(不含继承的)对应的Method对象。

示例代码如下:

package com.zzu.reflect;
import java.lang.reflect.Method;

public class Test {

	public static void main(String[] args) throws Exception {
		Class clazz = Student.class;
//		 1. Method[] getMethods()
		Method[] methods = clazz.getMethods();
		for (Method method : methods) {
			System.out.println(method);
		}
		System.out.println("——————————");
//		 2. Method getMethod(String methodName, Class<?>... parameterTypes)
		Method method = clazz.getMethod("study", String.class);
		System.out.println(method);
		System.out.println("——————————");
//		 3. Method[] getDeclaredMethods()
		Method[] methods2 = clazz.getDeclaredMethods();
		for (Method method2 : methods2) {
			System.out.println(method2);
		}
		System.out.println("——————————");
//		 4. Method getDeclaredMethod(String methodName,Class<?>... parameterTypes)
		Method method2 = clazz.getDeclaredMethod("study", String.class);
		System.out.println(method2);		
	}
}

运行结果如下图:
在这里插入图片描述

2、查看成员方法信息

通过Method类中某些方法可以获取某个成员方法的信息,这些方法如下:

  1. Class<?> getDeclaringClass():返回声明Method对象表示方法的类或接口的 Class 对象。
  2. int getModifiers():以整数形式返回此Method对象所表示方法的修饰符。应该使用Modifier类中的toString方法对所返回的整数进行解码。
  3. Class<?> getReturnType():返回Method对象所表示的方法的返回值类型所对应的Class对象。
  4. String getName():返回方法名。
  5. Class<?>[] getParameterTypes():返回由Method对象代表方法的形参类型对应Class对象组成的数组。如果方法没有参数,则数组长度为 0。
  6. Class<?>[] getExceptionTypes():返回由Method对象表示方法抛出异常类型对应Class对象组成的数组。如果此方法没有在其 throws子句中声明异常,则返回长度为 0 的数组。

示例代码如下:

package com.zzu.reflect;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

public class Test {

	public static void main(String[] args) throws Exception {
		Class clazz = Student.class;
		Method method = clazz.getMethod("study",String.class);
//		 1. Class<?> getDeclaringClass()
		Class class1 = method.getDeclaringClass();
		System.out.println(class1);
		System.out.println("——————————");
//		 2. int getModifiers()
		int i = method.getModifiers();
		String string = Modifier.toString(i);
		System.out.println(string);
		System.out.println("——————————");
//		 3. Class<?> getReturnType()
		Class returnType = method.getReturnType();
		System.out.println(returnType);
		System.out.println("——————————");
//		 4. String getName()
		String name = method.getName();
		System.out.println(name);
		System.out.println("——————————");
//		 5. Class<?>[] getParameterTypes()
		Class [] types = method.getParameterTypes();
		for (Class class2 : types) {
			System.out.println(class2);
		}
		System.out.println("——————————");
//		 6. Class<?>[] getExceptionTypes()	
		Class [] types2 = method.getExceptionTypes();
		for (Class class2 : types2) {
			System.out.println(class2);
		}
	}
}

运行结果如下图:
在这里插入图片描述

3、操作成员方法

通过Method类中某些方法可以调用成员方法,这些方法如下:

  1. void setAccessible(boolean flag):调用方法时是否忽略访问权限的影响,true表示忽略,false表示不忽略。
  2. Object invoke(Object obj, Object… args):调用Method对象指代的方法并返回Object类型结果。obj表示该方法所在类实例,如果方法时静态的则obj可以指定为null; args表示传入该方法的参数,如果方法没有参数,则args数组长度可以为0或null 。

示例代码如下:

package com.zzu.reflect;
import java.lang.reflect.Method;

public class Test {

	public static void main(String[] args) throws Exception {
		Class clazz = Student.class;
		Student student = new Student();
		Method method = clazz.getMethod("study",String.class);
		method.invoke(student, "Math");		
	}
}

运行结果如下图:
在这里插入图片描述

五、成员变量

1、获取成员变量

通过Class类中某些方法可以获取对应类中声明的成员变量实例对象,这些方法有:

  1. Field[] getFields():返回该Class对象表示类或接口中所有public属性(含继承的)对应的Field对象数组。
  2. Field getField(String fieldName):返回该Class对象表示类或接口中与指定属性名(含继承的)相同的public 属性对应的Field对象。
  3. Field[] getDeclaredFields():返回该Class对象表示类或接口内定义的所有属性(不含继承的)对应的Field对象数组。
  4. Field getDeclaredField(String fieldName) :返回与该Class对象表示类或接口内定义的属性名(不含继承的)相匹配的属性相对应的Field对象。

示例代码如下:

package com.zzu.reflect;
import java.lang.reflect.Field;

public class Test {

	public static void main(String[] args) throws Exception {
		Class clazz = Student.class;
//		 1. Field[] getFields()
		Field[] fields = clazz.getFields();
		for (Field field : fields) {
			System.out.println(field);
		}
		System.out.println("——————————");
//		 2. Field getField(String fieldName)
		Field field = clazz.getField("a");
		System.out.println(field);
		System.out.println("——————————");
//		 3. Field[] getDeclaredFields()
		Field[] fields2 = clazz.getDeclaredFields();
		for (Field field2 : fields2) {
			System.out.println(field2);
		}
		System.out.println("——————————");
//		 4. Field getDeclaredField(String fieldName)
		Field field2 = clazz.getDeclaredField("d");
		System.out.println(field2);
	}
}

运行结果如下图:
在这里插入图片描述

2、查看成员变量信息

通过Field类中某些方法可以获取某个成员变量的信息,这些方法如下:

  1. Class<?> getDeclaringClass():返回声明Field对象表示字段的类或接口所对应的Class对象。
  2. int getModifiers():以整数形式返回Field对象表示的字段的修饰符。
  3. Class<?> getType():返回Field对象所表示字段的数据类型所对应的Class对象(推荐)。
  4. Type getGenericType():返回此Field对象所表示字段的声明类型。
  5. String getName():返回Field对象表示字段的名称。

示例代码如下:

package com.zzu.reflect;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;

public class Test {

	public static void main(String[] args) throws Exception {
		Class clazz = Student.class;
		Field field = clazz.getDeclaredField("d");
//		 1. Class<?> getDeclaringClass()
		Class class1 = field.getDeclaringClass();
		System.out.println(class1);
		System.out.println("——————————");
//		 2. int getModifiers()
		int i = field.getModifiers();
		String string = Modifier.toString(i);
		System.out.println(string);
		System.out.println("——————————");
//		 3. Class<?> getType()
		Class type = field.getType();
		System.out.println(type);
		System.out.println("——————————");
//		 4. Type getGenericType()
		Type type2 = field.getGenericType();
		System.out.println(type2);
		System.out.println("——————————");
//		 5. String getName()
		String name = field.getName();
		System.out.println(name);
	}
}

运行结果如下图:
在这里插入图片描述

3、操作成员变量

通过Field类中某些方法获取及设置成员变量的值,这些方法如下:

  1. void setAccessible(boolean flag):设置或获取属性值时是否忽略访问权限的影响,true表示忽略,false表示不忽略。
  2. Object get(Object obj):返回Field表示字段的Object类型的值。obj为该属性所在类创建的对象,如果该属性是静态的,则可设置为null。
  3. void set(Object obj, Object value):为Field对象表示属性设置新值。obj为该属性所在类创建的对象,如果该属性为静态的则设置为null;value为该属性新值。

示例代码如下:

package com.zzu.reflect;
import java.lang.reflect.Field;

public class Test {

	public static void main(String[] args) throws Exception {
		Class<Student> clazz = Student.class;
		Student student = (Student) clazz.newInstance();
		Field field = clazz.getDeclaredField("d");
		field.setAccessible(true);
		field.set(student, "Tom");
		Object object = field.get(student);
		System.out.println(object);
	}
}

运行结果如下图:
在这里插入图片描述

  • 6
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值