Home

韧桂

思考,总结

通过反射调用类中的指定属性方法构造器

1.调用指定方法
通过反射,调用类中的方法,通过 Method 类完成。步骤:
1.通过 Class 类的 getMethod(String name,Class…parameterTypes) 方法取得一个 Method 对象,并设置此方法操作时所需要的参数类型。
2.之后使用 Object invoke(Object obj, Object[] args) 进行调用,并向方法中传递要设置的 obj 对象的参数信息。

Object invoke(Object obj, Object … args):
说明:
1.Object 对应原方法的返回值,若原方法无返回值,此时返回null
2.若原方法若为静态方法,此时形参Object obj可为null
3.若原方法形参列表为空,则Object[] args为null
4.若原方法声明为private,则需要在调用此invoke()方法前,显式调用方法对象的 setAccessible(true)方法,将可访问private的方法。

2.调用指定属性

  • 在反射机制中,可以直接通过Field类操作类中的属性,通过Field类提供的set()和get()方法就可以完成设置和取得属性内容的操作。
    • public Field getField(String name) 返回此Class对象表示的类或接口的指定的public的Field。
    • public Field getDeclaredField(String name)返回此Class对象表示的类或接口的指定的Field。
  • 在Field中:
    • public Object get(Object obj) 取得指定对象obj上此Field的属性内容
    • public void set(Object obj,Object value) 设置指定对象obj上此Field的属性内容
  • 注:在类中属性都设置为private的前提下,在使用set()和get()方法时,首先要使用Field类中的setAccessible(true)方法将需要操作的属性设置为可以被外部访问。
    • public void setAccessible(true)访问私有属性时,让这个属性可见。

代码一:

package nineteen;

@MyAnnotation(value = "rengui")
public class Person extends Creature<String> implements Comparable,MyInterface{
	public String name;
	private int age;
	int id;
	//创建类时,尽量保留一个空参的构造器。
	public Person() {
		super();
//		System.out.println("今天天气很闷热");
	}
	public Person(String name) {
		super();
		this.name = name;
	}
	private Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	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 int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	@MyAnnotation(value = "abc123")
	public void show(){
		System.out.println("我是一个人!");
	}
	
	private Integer display(String nation,Integer i) throws Exception{
		System.out.println("我的国籍是:" + nation);
		return i;
	}

	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}
	@Override
	public int compareTo(Object o) {
		// TODO Auto-generated method stub
		return 0;
	}
	
	public static void info(){
		System.out.println("中国人!");
	}
	
	class Bird {//内部类

	}
}

代码二:

package nineteen;

import org.junit.Test;

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

public class TestObtain {
    //(一)、调用运行时类中指定的属性
    @Test
    public void test1() throws Exception{
        Class clazz = Person.class;
        //1.获取指定的属性
        //getField(String fieldName):获取运行时类中声明为public的指定属性名为fieldName的属性
        Field name = clazz.getField("name");
        //2.创建运行时类的对象
        Person p = (Person)clazz.newInstance();
        System.out.println(p);
        //3.将运行时类的指定的属性赋值
        name.set(p,"Jerry");
        System.out.println(p);
        System.out.println("%"+name.get(p));

        System.out.println();
        //getDeclaredField(String fieldName):获取运行时类中指定的名为fieldName的属性
        Field age = clazz.getDeclaredField("age");

        //setAccessible 由于属性权限修饰符的限制,为了保证可以给属性赋值,需要在操作前使得此属性可被操作。
        age.setAccessible(true);
        age.set(p,10);
        System.out.println(p);

//		Field id = clazz.getField("id");
    }

    //(二)调用运行时类中指定的方法
    @Test
    public void test2() throws Exception{
        Class clazz = Person.class;
        //getMethod(String methodName,Class ... params):获取运行时类中声明为public的指定的方法
        Method m1 = clazz.getMethod("show");
        Person p = (Person)clazz.newInstance();
        //调用指定的方法:Object invoke(Object obj,Object ... obj)
        Object returnVal = m1.invoke(p);//我是一个人
        System.out.println(returnVal);//null

        Method m2 = clazz.getMethod("toString");
        Object returnVal1 = m2.invoke(p);
        System.out.println(returnVal1);//Person [name=null, age=0]
        //对于运行时类中静态方法的调用
        Method m3 = clazz.getMethod("info");
        m3.invoke(Person.class);

        //getDeclaredMethod(String methodName,Class ... params):获取运行时类中声明了的指定的方法
        Method m4 = clazz.getDeclaredMethod("display",String.class,Integer.class);
        m4.setAccessible(true);
        Object value = m4.invoke(p,"CHN",10);//我的国籍是:CHN
        System.out.println(value);//10
    }

    //(三)、调用指定的构造器,创建运行时类的对象
    @Test
    public void test3() throws Exception{
        String className = "nineteen.Person";
        Class clazz = Class.forName(className);

        Constructor cons = clazz.getDeclaredConstructor(String.class,int.class);
        cons.setAccessible(true);
        Person p = (Person)cons.newInstance("罗伟",20);
        System.out.println(p);
    }
}

韧桂 2020-01-11