概念

反射:将类的各个组成部分封装为其他对象,这就是反射机制。
好处:

  1. 可以在程序运行过程中,操作这些对象。
  2. 可以解耦,提高程序的可扩展性。

第12章 反射 - 图1

获取Class对象的方式

  1. Class.forName(“全类名”):将字节码文件加载进内存,返回Class对象

    多用于配置文件,将类名定义在配置文件中。读取文件,加载类

  2. 类名.class:通过类名的属性class获取

    多用于参数的传递

  3. 对象.getClass():getClass()方法在Object类中定义着。

    多用于对象的获取字节码的方式

结论:同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,不论通过哪一种方式获取的Class对象都是同一个

示例1:

  1. package com.alpaak.part12;
  2. import com.alpaak.part12.demo5.MyAnno;
  3. public class Person {
  4. private String name;
  5. private int age;
  6. private static String city="广州";
  7. public String a;
  8. protected String b;
  9. String c;
  10. private String d;
  11. public Person() {
  12. }
  13. public Person(String name, int age) {
  14. this.name = name;
  15. this.age = age;
  16. }
  17. public void eat(){
  18. System.out.println("吃饭。。。。");
  19. }
  20. public void eat(String name){
  21. System.out.println(name + ",吃饭。。。。");
  22. }
  23. public void sleep(){
  24. System.out.println("睡觉。。。。");
  25. }
  26. @MyAnno
  27. public void test () {
  28. System.out.println("注解测试下");
  29. }
  30. }
  1. package com.alpaak.part12.demo1;
  2. import com.alpaak.part12.Person;
  3. /**
  4. * 获取Class对象的方式
  5. */
  6. public class ReflectDemo1 {
  7. public static void main(String[] args) {
  8. /*
  9. 1. Class.forName("全类名"):将字节码文件加载进内存,返回Class对象
  10. - 多用于配置文件,将类名定义在配置文件中。读取文件,加载类
  11. 2. 类名.class:通过类名的属性class获取
  12. - 多用于参数的传递
  13. 3. 对象.getClass():getClass()方法在Object类中定义着。
  14. - 多用于对象的获取字节码的方式
  15. */
  16. //1. Class.forName("全类名"):将字节码文件加载进内存,返回Class对象
  17. try {
  18. Class<?> aClass = Class.forName("com.alpaak.part12.Person");
  19. //类名.class:通过类名的属性class获取
  20. Class<Person> personClass = Person.class;
  21. //3. 对象.getClass():getClass()方法在Object类中定义着。
  22. Person person = new Person();
  23. Class<? extends Person> aClass2 = person.getClass();
  24. System.out.println("aClass==personClass:"+(aClass==personClass));
  25. System.out.println("aClass2==personClass:"+(aClass==personClass));
  26. } catch (ClassNotFoundException e) {
  27. e.printStackTrace();
  28. }
  29. }
  30. }

Class对象功能

获取成员变量

  • Field[] getFields() :获取所有public修饰的成员变量
  • Field getField(String name) 获取指定名称的 public修饰的成员变量
  • Field[] getDeclaredFields() 获取所有的成员变量,不考虑修饰符
  • Field getDeclaredField(String name)

    Field:成员变量

  1. 设置值 void set(Object obj, Object value)
  2. 获取值 get(Object obj)
  3. 忽略访问权限修饰符的安全检查(暴力反射) setAccessible(true)

    示例2:

    ```java package com.alpaak.part12.demo2;

import com.alpaak.part12.Person;

import java.lang.reflect.Field;

/**

  • 获取成员变量 */ public class ReflectDemo2 {

    public static void main(String[] args) throws Exception{

     /*
     - Field[] getFields() :获取所有public修饰的成员变量
     - Field getField(String name)   获取指定名称的 public修饰的成员变量
     - Field[] getDeclaredFields()  获取所有的成员变量,不考虑修饰符
     - Field getDeclaredField(String name)
    
      */
     Class<Person> personClass = Person.class;
     //
     Field[] fields = personClass.getFields();
     for (Field field : fields) {
         System.out.println(field);
     }
     System.out.println("-----------");
    
     Field[] declaredFields = personClass.getDeclaredFields();
     for (Field declaredField : declaredFields) {
         System.out.println(declaredField);
     }
    
     /*
     1. 设置值
    
     - void set(Object obj, Object value)
    
     2. 获取值
    
     - get(Object obj)
    
     3. 忽略访问权限修饰符的安全检查
    
     - setAccessible(true):暴力反射
    
      */
     System.out.println("------------------");
     Field a = personClass.getField("a");
    
     Person p = new Person();
    
     a.set(p,"zhongguo");
    
     //获取值
     Object o = a.get(p);
     System.out.println("o:"+o);
    
     //a.setAccessible(true);
     Field name = personClass.getDeclaredField("name");
     /*
     报错
     Class com.alpaak.part12.demo2.ReflectDemo2 can not access a member of class com.alpaak.part12.Person with modifiers "private"
      */
     System.out.println("name:"+name.get(p));
    

    } }

<a name="qGa22"></a>
## 获取构造方法

- Constructor<?>[] getConstructors()  
- Constructor<T> getConstructor(Class<?>... parameterTypes)  
- Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)  
- Constructor<?>[] getDeclaredConstructors()  
<a name="oxpnr"></a>
### Constructor:构造方法
创建对象:T newInstance(Object... initargs)  <br />如果使用空参数构造方法创建对象,操作可以简化:**Class对象的newInstance方法**
<a name="ZlSVq"></a>
### 示例3:
```java
package com.alpaak.part12.demo3;

import com.alpaak.part12.Person;

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

/**
 * 获取构造方法
 */
public class ReflectDemo3 {
    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        /*
        2. 获取构造方法们

        - Constructor<?>[] getConstructors()
        - Constructor<T> getConstructor(类<?>... parameterTypes)
        - Constructor<T> getDeclaredConstructor(类<?>... parameterTypes)
        - Constructor<?>[] getDeclaredConstructors()

         */
        Class<Person> personClass = Person.class;

        //获取有参的构造方法
        Constructor<Person> constructor = personClass.getConstructor(String.class, int.class);
        System.out.println(constructor);
        //创建对象1
        Person person1 = constructor.newInstance("张三", 23);
        System.out.println(person1);

        //获取无参的构造方法
        Constructor<Person> constructor2 = personClass.getConstructor();
        System.out.println("constructor2:"+constructor2);

        //创建对象2
        Person person2 = constructor2.newInstance();
        System.out.println("person2:"+person2);


        //创建对象3
        Person person3 = personClass.newInstance();
        System.out.println("person3:"+person3);

        System.out.println("------------");
        Constructor<?>[] declaredConstructors = personClass.getDeclaredConstructors();
        for (Constructor<?> declaredConstructor : declaredConstructors) {
            System.out.println(declaredConstructor);
        }

        System.out.println("-------------");
        //构造器暴力访问
        //constructor2.setAccessible(true);


    }
}

获取成员方法

  • Method[] getMethods() :获取类里面所有的public方法,包括父类里面的public方法
  • Method getMethod(String name, 类<?>… parameterTypes)
  • Method[] getDeclaredMethods() :获取类里面声明的所有的方法,不包括父类的方法
  • Method getDeclaredMethod(String name, 类<?>… parameterTypes)

    Method:方法对象

    执行方法:Object invoke(Object obj, Object… args)
    获取方法名称:String getName

    示例4:

    ```java package com.alpaak.part12.demo4;

import com.alpaak.part12.Person;

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

/**

  • 获得成员方法 */ public class ReflectDemo4 { public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {

     /*
     3. 获取成员方法们:
    
     - Method[] getMethods()
     - Method getMethod(String name, 类<?>... parameterTypes)
     - Method[] getDeclaredMethods()
     - Method getDeclaredMethod(String name, 类<?>... parameterTypes)
    
      */
    
     Class<Person> personClass = Person.class;
    
     //获取指定名称的方法
     Method eat = personClass.getMethod("eat");
     //
     Person p = new Person();
     //执行方法
     eat.invoke(p);
    
     //获取指定名称,并且带参数的方法
     Method eat2 = personClass.getMethod("eat", String.class);
     //执行带参数的方法
     eat2.invoke(p,"wowo");
     System.out.println("--------------");
    
     //获取所有public修饰的方法
     Method[] methods = personClass.getMethods();
     for (Method method : methods) {
         System.out.println(method);
         //方法名
         System.out.println(method.getName());
     }
    
     System.out.println("-----------------");
     //获取类名
     String name = personClass.getName();
     System.out.println("类名:"+name);
    

    } } ```

    在程序使用(解析)注解

    在程序使用(解析)注解:获取注解中定义的属性值

  1. 获取注解定义的位置的对象 (Class,Method,Field)
  2. 判断注解是否存在
  • isAnnotationPresent(Class)
  1. 获取指定的注解
  • getAnnotation(Class)
  1. 调用注解中的抽象方法获取配置的属性值

    示例5:

    ```java package com.alpaak.part12.demo5;

import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;

/**

  • 定义注解 */ @Target({ElementType.METHOD}) //@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface MyAnno { int age() default 0; } java package com.alpaak.part12.demo5;

import com.alpaak.part12.Person;

import java.lang.reflect.Method;

/**

  • 在程序使用(解析)注解 */ public class Demo5 { public static void main(String[] args) throws NoSuchMethodException {

     /*
     - 在程序使用(解析)注解:获取注解中定义的属性值
    
     1. 获取注解定义的位置的对象  (Class,Method,Field)
    
     - isAnnotationPresent(Class)
    
     1. 获取指定的注解
    
     - getAnnotation(Class)
    
     3. 调用注解中的抽象方法获取配置的属性值
    
      */
     Class<Person> personClass = Person.class;
     //
    

    // System.out.println(personClass.isAnnotationPresent(MyAnno4.class)); // //获取类上面的注解,获取注解定义的位置的对象 // MyAnno4 annotation = personClass.getAnnotation(MyAnno4.class); // // //获取注解中定义的属性值 // int age = annotation.age(); // System.out.println(“age:”+age);

     System.out.println("------------");
    
     Method test = personClass.getMethod("test");
     System.out.println(test.isAnnotationPresent(MyAnno.class));
     //获取方法上定义的注解
     if (test.isAnnotationPresent(MyAnno.class)) {
         System.out.println("test方法有定义注解");
         MyAnno annotation2 = test.getAnnotation(MyAnno.class);
         int age2 = annotation2.age();
         System.out.println("age2:" + age2);
     }
    
}

}

```