初学反射笔记

反射初学笔记

概念

JAVA反射 (reflection)机制是指在程序的运行状态中,可以构造任意一个类的对象,可以了解任意一个对象所属的类,可以了解任意一个类的成员变量和方法,可以调用任意一个对象的属性和方法。这种动态获取程序信息以及动态调用对象的功能称为Java语言的反射机制。反射被视为动态语言的关键

案例中的Person类

	public class Person {
		private String name;
		private int age;
		public Person() {
			super();

		}
		public 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;
		}
	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}

	public void eat() {
		System.out.println("今天吃了一顿金钱豹");
	}
	private void eat(String name) {
			System.out.println("吃了" + name);
	}
	public void eat(int num) {
		System.out.println("今天吃了" + num + "顿金钱豹");
	}
}

获取字节码对象

  1. 使用类路径获取

    Class clazz = Class.forName("com.pretext.reflect.Person");
    
  2. 使用类名获取

    Class clazz2 = Person.class;
    
  3. 使用对象获取

    Person person = new Person();
    Class clazz3 = person.getClass();
    

    三个字节码对象属于同一个对象

通过字节码来创建实例对象

  1. 直接使用newInstance()方法调用无参构造创建对象

            Class aClass = Class.forName("com.pretext.reflect.Person");
            Person p = (Person) aClass.newInstance();
    

    等价于Person p = new Person();

  2. 使用构造器来调用有参构造方法创建对象

            Class clazz = Class.forName("com.pretext.reflect.Person");
            Constructor constructor = clazz.getConstructor(String.class, int.class);
            Person person = (Person) constructor.newInstance("zhang", 23);
    

    等价于Person p = new Person(“zhang”, 23);

通过反射来更改属性的值

  • 对于public属性,使用Class.getField(String)获取类中的指定字段

    扫描二维码关注公众号,回复: 10697263 查看本文章
            Class aClass = Class.forName("com.pretext.reflect.Person");
            Constructor constructor = aClass.getConstructor(String.class, int.class);
            Person person = (Person) constructor.newInstance("zhang", 23);
            Field name = aClass.getField("name");
    

    由于程序中使用的Person类的name属性时private的,因此运行后程序会报NoSuchFieldException

  • 对于private属性,使用getDeclaredField()方法来获取Field对象

            Class aClass = Class.forName("com.pretext.reflect.Person");
            Constructor constructor = aClass.getConstructor(String.class, int.class);
            Person person = (Person) constructor.newInstance("zhang", 23);
            // Field name = aClass.getField("name");
            // System.out.println(name.toString());
            // name.set(person, "lisi");
            Field field = aClass.getDeclaredField("name");
            field.setAccessible(true);
            field.set(person, "lisi");
            System.out.println(person);
     
    

    在set前必须使用==field.setAccessible(true);==设置访问权限,否则会报IllegalAccessException

通过反射来执行类中的方法

​ 跟获取Field对象类似

  • 对于public方法,直接使用getMethod()

             Class aClass = Class.forName("com.pretext.reflect.Person");
             Constructor constructor = aClass.getConstructor(String.class, int.class);
             Person person = (Person) constructor.newInstance("zhang", 23);
             Method method = aClass.getMethod("eat");
             method.invoke(person);
    
  • 对于private方法,使用getDeclaredMethod()

    		Class aClass = Class.forName("com.pretext.reflect.Person");
            Constructor constructor = aClass.getConstructor(String.class, int.class);
            Person person = (Person) constructor.newInstance("zhang", 23);
            Method method = aClass.getMethod("eat");
            method.invoke(person);
            Method method1 = aClass.getMethod("eat", int.class);
            method1.invoke(person, 10);
            Method method2 = aClass.getDeclaredMethod("eat", String.class);
            method2.setAccessible(true);
            method2.invoke(person, "狗肉");
    

    同样别忘了setAccessible(true);

方法名包含declared的方法用于访问private属性或方法

发布了8 篇原创文章 · 获赞 3 · 访问量 186

猜你喜欢

转载自blog.csdn.net/qq_42641075/article/details/105314798