反射机制-Reflected

一、java的反射机制提供的功能:

  • 在运行时判断任意一个对象所属的类
  • 在运行时构造任意一个类的对象
  • 在运行时判断任意一个类所具有的成员变量和方法
  • 运行时获取泛型信息
  • 在运行时调用任意一个对象的成员变量和方法
  • 在运行时处理注解
  • 生成动态代理

二、反射相关的主要API:

  • java.lang.Class : 代表一个类
    1.程序经过javac.exe命令以后,会生成一个或多个字节码文件(.calss后缀)。
    接着我们使用就java.exe命令对猴哥字节码文件进行解释运行,此过程相当于将某个字节码文件加载带内存中。上述过程称之为累的加载。
    加载到内存中的类为运行时的类,运行时的类就作为Class的一个实例

    2.获取Class的实例方式
    方式1(掌握):Class<> c = 类名.class
    方式2(掌握):类名 对象名 = new 类名()
    Class c = 对象名.getClass()
    方式3(掌握):Class c = Class.forName(String classPath)(注意:会抛异常)

    3.那些类型可以有Class对象
    1.class :外部类、成员内部类、静态内部类、局部内部类、匿名类
    2.interface : 接口
    3.[] : 数组
    4.enum : 枚举
    5.annotation : 注解@interface
    6.primitive type : 基本数据类型
    7.void

  • java.lang.reflect.Constructor : 代表类的构造器
    1.获取当前类的public构造器
    Constructor[] 构造器对象名 = Class的实例名.getConstructors()

    2.获取当前类的所有的构造器
    Constructor[] 构造器对象名 = Class的实例名.getDecleardConstructors()

    3.获取指定的构造器
    Constructor 构造器对象名 = Class的实例名.getConstructor(参数1类型.class,…)

  • 创建运行时类的实例对象
    方式1:使用的是类中的指定的构造器创建的类对象【不常用】
    Constructor 构造器对象名 = Class的实例名.getConstructor(参数1类型.class,…) 获取指定构造器对象
    构造器对象名.setAccessible(true) 表示允许操作private成员
    Object obj = 构造器对象名.newInstance(参数1,…) 通过指定构造器对象创建类的对象

    方式2:这样直接使用的是类中的空参构造器创建的类对象【常用】
    Object obj = Class的实例名.newInstance()

  • java.lang.reflect.Field : 代表类的成员变量
    1.获取到类中public属性(包含父类)【不建议使用
    方法1:
    Field[] f = Class的实例名.getFields()
    方法2:
    Field f = Class的实例名.getField(属性名)

    2.获取到类中自己的所有属性(不含有父类):【建议使用】
    方法1:
    Field[] f = Class的实例名.getDeclaredFields()
    方法2:
    Field f = Class的实例名.getDeclaredField(属性名)

    3.获取到属性的权限修饰符、数据类型、变量名。(了解)
    int f.getModifiers() : 权限修饰符(0代表默认,1代表public,2代表private)

    Class f.getType().getName() : 数据类型

    String f.getName() : 变量名

    4.设置、获取 属性的值
    非静态的属性:
    前提操作:f.setAccessible(true) 表示允许操作private成员
    设置:f.set(obj,value) obj表示给哪个对象的属性设置,value为设置的值
    获取:f.get(obj) obj表示获取哪个对象的属性值,有返回值

    静态的属性:
    前提操作:f.setAccessible(true) 表示允许操作private成员
    设置:f.set(类.class,value) 类.class:表示当前类的静态,value为设置的值
    获取:f.get(类.class) 类.class:表示当前类的静态,有返回值

  • java.lang.reflect.Method : 代表类的方法
    1.获取到类中public方法(包含父类)【不推荐使用】
    方法1:
    Method[] m = Class的实例名.getMethods()

    方法2:
    Method m = Class的实例名.getMethod(方法名,形参列表(默认为空))

    2.获取到类中自己的所有方法(不含有父类)【推荐使用】
    方法1:
    Method[] m = Class的实例名.getDeclaredMethods()
    方法2:
    Method m = Class的实例名.getDeclaredMethod(方法名,形参列表(默认为空)) 例:String型的形参列表:String.class

    3.调用方法
    非静态方法:
    前提操作:m.setAccessible(true) 表示允许操作private成员
    调用:m.invoke(obj,实参1,…) obj表示给哪个对象的属性设置,实参对应的方法的形参。invoke()返回值就是类中方法的返回值

    静态方法:
    前提操作:m.setAccessible(true) 表示允许操作private成员
    调用:m.invoke(类.class,实参1,…) 类.class:表示当前类的静态,实参对应的方法的形参。invoke()返回值就是类中方法的返回值

三、方法的补充:

1.获取运行时类的父类
Class sp = Class的实例名.getSuperclass()

2.获取运行时类的带泛型的父类
Type sgp = Class的实例名.getGenericSuperclass()

3.获取运行时类的带泛型的父类的泛型(需要4步)
①Type sgp = Class的实例名.getGenericSuperclass(). : 获取运行时类的带泛型的父类
②ParameterizedType paramType = (parameterizedType)sgp : 强转
③Type[] actTypeArg = paramType.getActualTypeArguments() : 获取到实际的类型参数(也就是泛型)
④actTypeArg.getTypeName() : 获取泛型名

4.获取到当前运行时类的接口
Class[] interface = Class的实例名.getInterface()
如果想获取到其父类的接口,那么得到父类然后在getInterface()

5.获取当前运行时类所在的包
Package pk = Class的实例名.getPackage()

6.获取当前运行时类声明的注解
Annotation[] anno = Class的实例名.getAnnotations()

四、使用反射之前能对Person的操作:

  • 创建Person类的实例化
  • 通过对象当调用类中的非private类型的属性、方法

五、使用反射之后能对Person的操作

  • 创建Person类的实例化(调用构造器)
  • 调用Person中的属性
  • 调用Person中的方法
  • 调用Person中private的属性、方法、构造器

上述过程的相关代码举例:

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

public class ReflectionTest {
	public static void main(String[] args) throws Exception {
		Person p1 = new Person("Joney",18);
		System.out.println(p1.age);
		System.out.println(p1.toString()+"\n");
		
		System.out.println("**************************");
		
		
		
		//1.通过反射创建Person的对象obj
		Class c = Person.class;
		Object newInstance = c.newInstance();
		System.out.println(newInstance.toString());
		
		//通过getConstructor(参数1类型.class,...)获取构造器对象
		Constructor constructor = c.getConstructor(String.class,int.class);//获取构造器对象
		Object obj = constructor.newInstance("Mike",22);//通过构造器对象实例化Person
		//通过对象调用Person的方法
		System.out.println(obj.toString()+"\n"); //通过反射创建Person的对象obj调用方法
		
		
		
		//2.调属性
		Field age = c.getDeclaredField("age"); //通过getDeclaredField("属性")获取到该属性的对象
		age.set(obj, 20); //修改属性值
		System.out.println(obj.toString()+"\n");
		
		
		
		//3.调方法
		Method print = c.getDeclaredMethod("print");//通过getDeclaredMethod()获取到该方法的对象
		print.invoke(obj); //调用该print()
		System.out.println();
		
		
		
		//4.调用private结构
		//4.1通过getDeclaredConstructor((参数1类型.class,...)获取私有构造器对象
		Constructor privateConstructor = c.getDeclaredConstructor(String.class);//获取私有构造器对象
		privateConstructor.setAccessible(true);
		Object obj2 = privateConstructor.newInstance("Tom");//创建对象
		System.out.println(obj2.toString());
		//4.2通过getDeclaredField("属性名")获取到私有属性的对象
		Field name = c.getDeclaredField("name");
		name.setAccessible(true);
		name.set(obj2, "Aimy");//修改属性值
		System.out.println(obj2.toString());
	}
}     

class Person{
	private String name;
	public int age;
	
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	private Person(String name) {
		super();
		this.name = name;
	}
	public Person() {
		super();
	}
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	
	public void print() {
		System.out.println("我是Person的print()");
	}
	
	
	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}
	
	
	
}

在这里插入图片描述

©️2020 CSDN 皮肤主题: 点我我会动 设计师:上身试试 返回首页