通过 JAVA 提供的 API 实现一些反射操作

这是我参与11月更文挑战的第20天,活动详情查看:2021最后一次更文挑战

package reflecttest;

public class Person {
	public int age;
	private String name;
	
	public Person() {
		// TODO 自动生成的构造函数存根
	}
	
	public Person(String name) {
		super();
		this.name = name;
	}
	
	private Person(String name,int age) {
		super();
		this.name = name;
		this.age = age;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public String getName() {
		return name;
	}

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

	public void show(String name,int age) {
		System.out.println("迪迦,变身");
	}
    
   private void fly() {
		System.out.println("迪迦,飞行");
	}
    
   private String Work(String name,int age) {
		return name;	
	}

}

复制代码

获取Class的实例的三种方式

Class的实例就是运行时的类

  1. 通过类字面常量Class.class获取

    		Class clazz = Person.class;
    复制代码
  2. 通过Object类中的getClass()方法返回一个Class类型的实例

    		Person person = new Person();
    		Class clazz = person.getClass();
    复制代码
  3. 通过静态方法Class.forName("全类名")获取类名对应的Class对象

    		Class clazz = Class.forName("reflecttest.Person");
    复制代码

通过反射创建对象

反射创建类对象主要有两种方式,通过Class对象的newInstance()方法、通过Constructor对象的 newInstance()方法。

  1. 第一种:通过Class对象的newInstance()方法。

    		// 获取类的 Class 对象实例
    		Class clazz = Person.class;
    
    		//创建Person对象
    		Person person = (Person)clazz.newInstance();
    复制代码
  2. 第二种:通过Constructor对象的newInstance()方法

    		// 获取类的 Class 对象实例
    		Class clazz = Person.class;
    
    		//创建Person对象
    		Constructor constructor = clazz.getConstructor();
    		Person person = (Person)constructor.newInstance();
    复制代码

通过Constructor对象创建类对象可以选择特定构造方法,而通过 Class对象则只能使用默认的无参数构造方法。

示例:(调用有参构造方法进行类对象的初始化)

		// 获取类的 Class 对象实例
		Class clazz = Person.class;
		
		//创建Person对象
		Constructor constructor = clazz.getConstructor();
		Person person = (Person) constructor.newInstance("迪迦",16);
复制代码

通过反射调用对象属性

获取属性

获取所有属性的两种方式

  1. getFields()

    		// 通过getFields()获取Person.class及父类中所有 public 修饰的属性
    		Field[] fields = clazz.getFields();
    复制代码
  2. getDeclaredFields()

    		// 通过getDeclaredFields()获取Person.class中所有的属性
    		Field[] fields = clazz.getDeclaredFields();	
    复制代码

注:

getFields() 可以获取本类及父类中所有 public 修饰的属性 getDeclaredFields() 可以获取本类所有的属性。包括 public、private、protected、default 修饰的属性,不包括父类中的属性

获取指定属性的两种方式

  1. getField(String name)

    		// 通过getField()获取Person.class中的age属性		
    		Field field = clazz.getField("age");
    复制代码
  2. getDeclaredField(String name)

    		// 通过getDeclaredField()获取Person.class中的name属性
    		Field field = clazz.getDeclaredField("name");	
    复制代码

注:

getField(String name) 可以获取本类及父类中的 public 修饰的属性 getDeclaredField(String name) 可以获取本类的属性。包括 public、private、protected、default 修饰的属性,不包括父类中的属性

对属性的操作

设置属性值

		// 通过getDeclaredField()获取Person.class中的name属性
		Field field = clazz.getDeclaredField("name");

		//如果属性是private修饰的,则需要设置访问权限才能赋值
		field.setAccessible(true);

		//通过set(Object obj, Object value)设置person对象的name属性为"迪迦"
		field.set(person, "迪迦");
复制代码

注:如果属性是private修饰的,则需要设置setAccessible(true)才能赋值

获取属性值

		//通过get(Object obj)获取person对象的field属性
		String name = (String) field.get(person);
复制代码

获取属性的类型

		//通过getType()获取属性的类型
		Class type = field.getType();

		//获取属性的类型名
		String typename = field.getType().getName();
复制代码

获取属性名

		//调用getName()获取属性名
		String fieldname = field.getName();
复制代码

获取修饰类型

		//调用getModifiers()获取修饰类型,
		int modifier = field.getModifiers();

		//Modifier.toString(int mod)转成public、private、protected、default
		String modifiername = Modifier.toString(modifier);
复制代码

注:0-default、1-public、2-private、4-protected

示例

		// 获取类的 Class 对象实例
		Class clazz = Person.class;
		
		//创建Person对象
		Person person = (Person) clazz.newInstance();
		
		// 通过getDeclaredField()获取Person.class中的name属性
		Field field = clazz.getDeclaredField("age");	
		field.setAccessible(true);
		//通过set()设置person对象的age属性为"12"
		field.set(person, 12);	
		
		//获取修饰符
		int modifier = field.getModifiers();
		String modifiername = Modifier.toString(modifier);
		//获取属性类型名
		String typename = field.getType().getName();
		//获取属性名
		String fieldname = field.getName();
		//获取属性值
		int fieldvalue = field.getInt(person);

		System.out.println(modifiername+" "+typename+" "+fieldname+" = "+fieldvalue+";");
		
复制代码

输出:public int age = 12;

通过反射调用对象方法

获取方法

获取所有方法的两种方式

  1. getMethods()

    		//通过getMethods()获取Person类及父类中所有的public修饰的方法		
    		Method[] methods =clazz.getMethods();
    复制代码
  2. getDeclaredMethods()

    		//通过getDeclaredMethods()获取Person类中所有的方法
    		Method[] methods = clazz.getDeclaredMethods();
    复制代码

注:

getMethods()可以获取本类及父类中所有 public 修饰的方法 getDeclaredMethods()可以获取本类所有的方法。包括 public、private、protected、default 修饰的方法,不包括父类中的方法

取指定方法的两种方式

用方法名和形参列表来确定获取的方法

  1. getMethod(String name, class<?>... parameterTypes)

    		//获取Person类中的show方法,参数为方法名,show()的形参列表
    		Method method =clazz.getMethod("show",String.class,int.class);
    复制代码
  2. getDeclaredMethod(String name, 类<?>... parameterTypes)

    		//获取Person类中的fly方法,参数为方法名,fly()无形参列表
    		Method method = clazz.getDeclaredMethod("fly");
    复制代码

注:

getMethod() 可以获取本类及父类中的 public 修饰的属性 getDeclaredMethod() 可以获取本类的属性。包括 public、private、protected、default 修饰的属性,不包括父类中的属性

对方法的操作

调用方法

		//获取Person类中的fly方法,参数为方法名,fly()无形参列表
		Method method = clazz.getDeclaredMethod("fly");

		//如果方法是private修饰的,则需要设置访问权限
		method.setAccessible(true);

		//调用person中的fly方法
		method.invoke(person);
		//如果方法是静态方法static时,除了上面的方式,也可用下面的方法,当前类调用方法
		//method.invoke(Person.class);
复制代码

注:invoke()方法的返回值和调用的方法的返回值一样

获取方法的参数列表

		//获取形参列表
		Class[] paramTypes =method.getParameterTypes();	
复制代码

获取方法名

		//获取方法名
		String methodname = method.getName();
复制代码

获取方法的修饰类型

		//获取方法修饰符
		int modifier = method.getModifiers();
		String modifiername = Modifier.toString(modifier);
复制代码

获取方法的返回值类型

		//获取返回值类型
		Class<?> returntype =method.getReturnType();

		//获取返回值类型名
		String returntypename = returntype.getName();
复制代码

示例

	public static void main(String[] args) throws Exception, IllegalAccessException {
		// 获取类的 Class 对象实例
		Class clazz = Person.class;
		
		//创建Person对象
		Person person = (Person) clazz.newInstance();
		
		//获取Person类中的方法
		Method method = clazz.getDeclaredMethod("Work",String.class,int.class);
		
		//设置权限
		method.setAccessible(true);
		
		//获取方法名
		String methodname = method.getName();
		
		//获取方法修饰符
		int modifier = method.getModifiers();
		String modifiername = Modifier.toString(modifier);
		
		//获取返回值类型
		Class<?> returntype =method.getReturnType();		
		//获取返回值类型名
		String returntypename = returntype.getName();
		
		//获取形参列表
		Class[] paramTypes =method.getParameterTypes();	
		
		System.out.print(modifiername+" "+returntypename+" "+methodname+"(");
		
		//打印方法参数
		printParamTypes(paramTypes);
			
	}
    /**
     * 打印方法参数
     * @param paramTypes
     */
    private static void printParamTypes(Class[] paramTypes) {
        for (int j = 0; j < paramTypes.length; ++j) {
            if (j > 0) {
                System.out.print(",");
            }
            System.out.print(paramTypes[j].getName());
        }
        System.out.println(");");
    }
复制代码

输出:private java.lang.String Work(java.lang.String,int);


通过反射调用对象构造方法

获取构造方法

获取所有构造方法的两种方式

  1. getConstructors()

    		//获取所有public修饰的构造方法,不包括父类
    		Constructor[] constructors = clazz.getConstructors();
    复制代码
  2. getDeclaredConstructors()

    		//获取所有构造方法,包括public、private、protected、default 修饰,不包括父类
    		Constructor[] constructors = getDeclaredConstructors();
    复制代码

注:

getConstructors()可以获取本类中所有 public 修饰的构造方法,不包括父类 getgetDeclaredConstructors()可以获取本类所有的构造方法。包括 public、private、protected、default 修饰的方法,不包括父类

获取指定构造方法的两种方式

对构造器的选择是依赖于形参列表的类型

  1. clazz.getConstructor()

    		//获取无参数的构造方法
    		Constructor constructor = clazz.getConstructor();
    复制代码
  2. getDeclaredConstructor()

    		//获取形参为(String,int)类型的构造方法
    		Constructor constructor = clazz.getDeclaredConstructor(String.class,int.class);
    复制代码

注:

getConstructor()只可以获取本类 public 修饰的构造方法,不包括父类 getDeclaredConstructor()可以获取本类所有的构造方法。包括 public、private、protected、default 修饰的方法,不包括父类

对构造方法的操作

创建对象

对构造器的选择是依赖于形参列表的类型

		//获取空参的构造器
		//Constructor constructor = clazz.getDeclaredConstructor();
		Constructor constructor = clazz.getDeclaredConstructor(String.class,int.class);
	
		//如果构造方法是private修饰的,设置权限
		constructor.setAccessible(true);
		
		//创建person对象
		Person person = (Person)constructor.newInstance("迪迦",20);
复制代码

获取构造方法的参数列表

		//获取构造方法形参列表
		Class[] paramTypes = constructor.getParameterTypes();
复制代码

获取构造方法名

		//获取构造方法名
		String constructorname = constructor.getName();
复制代码

获取构造方法的修饰类型

		//获取构造方法的修饰符
		int modifier = constructor.getModifiers();
		String modifiername = Modifier.toString(modifier);
复制代码

示例

public static void main(String[] args) throws Exception, IllegalAccessException {
		// 获取类的 Class 对象实例
		Class clazz = Person.class;

		//获取带参的构造器
		Constructor constructor = clazz.getDeclaredConstructor(String.class,int.class);
	
		//如果构造方法是private修饰的,设置权限
		constructor.setAccessible(true);
		
		//创建person对象
		Person person = (Person)constructor.newInstance("迪迦",20);
		
		//获取构造方法名
		String constructorname = constructor.getName();
		
		//获取构造方法的修饰符
		int modifier = constructor.getModifiers();
		String modifiername = Modifier.toString(modifier);
		
		//获取构造方法形参列表
		Class[] paramTypes = constructor.getParameterTypes();
		
		System.out.print(modifiername+" "+constructorname+"(");
		
		//打印方法参数
		printParamTypes(paramTypes);
		
	}
    /**
     * 打印方法参数
     * @param paramTypes
     */
    private static void printParamTypes(Class[] paramTypes) {
        for (int j = 0; j < paramTypes.length; ++j) {
            if (j > 0) {
                System.out.print(",");
            }
            System.out.print(paramTypes[j].getName());
        }
        System.out.println(");");
    }
复制代码

输出:private test1.Person(java.lang.String,int);

猜你喜欢

转载自juejin.im/post/7035468235252170766
今日推荐