Java反射

10 篇文章 0 订阅

1. 概述

  • 反射是Java中操作对象的一种机制,它允许程序在执行期间获取任何类的内部信息,并直接操作任意对象的内部属性及方法,这使得Java语言具有一定的动态性,运用更加灵活。
  • 使用反射可以降低代码的耦合度、实现动态代理等
  • 使用反射会降低一定的性能,使用不当会造成很高的资源消耗。

 


 

2. Class对象

  • Class对象是实现反射的关键,它包含了一个类的完整的结构信息
  • 一个类只有一个Class对象
  • Clas对象的声明:Class Class对象名
  • Class本身也是一个类
  • Class对象只能由系统建立
  • 同一个类创建的不同实例对象指向同一个Class对象
  • 一个Class对象对应一个加载到JVM中的一个.class文件
  • 通过反射可以获取类的结构:
    • Field:属性(字段)
    • Method:方法
    • Constructor:构造器
    • Superclass:父类对象
    • interface:接口
    • Annotation:注解

 


 

3. 获取Class对象

  • 获取Class对象有五种方式:

    • 通过”类名.class“获取
    • 通过实例对象调用getClass()方法获取
    • 通过Class.forName()方法传入类的全名获取
    • 通过”类名.TYPE“获取,只适用于基本数据类型
    • 利用ClassLoder获取
    // 获取类的Class对象
    public class ReflectionDemo01 {
    
        public static void main(String[] args) throws ClassNotFoundException {
    
            // 通过类获取Class对象
            Class personClass1 = Person.class;
    
            // 通过实例获取Class对象
            Class personClass2 = new Person().getClass();
    
            // 通过类的全类名获取Class对象,会抛出一个ClassNotFoundException异常
            Class personClass3 = Class.forName("com.example.reflection.Person");
    
            // “类名.TYPE”获取Class对象,只适用于内置基本数据类型
            Class integerClass = Integer.TYPE;
    
            System.out.println(personClass1.hashCode());
            System.out.println(personClass2.hashCode());
            System.out.println(personClass3.hashCode());
            System.out.println(integerClass.hashCode());
    
            /*
            一个结果:
            356573597
            356573597
            356573597
            1735600054
            (前三个hashCode一样,说明一个类只有一个Class对象)
             */
    
        }
    
    }
    
    // 一个实体类pojo
    class Person {
    
        // 属性
        private String name;
        private int age;
    
        // 无参构造
        public Person() {}
    
        // 全参构造
        public Person(String name, int age) {
            this.name = name;
            this.age = age;
        }
    
        // Set/Get方法
        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;
        }
    
        // 重写toString方法
        @Override
        public String toString() {
            return "Person{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    
    }
    
  • 能够获取Class对象的类型:

    • class(外部类、成员内部类、静态内部类、局部内部类、匿名内部类)
    • interface(接口)
    • [](数组)
    • enum(枚举)
    • @interface(注解)
    • primitive_type(基本数据类型)
    • void
    import java.lang.annotation.ElementType;
    
    // 有Class对象的类型
    public class ReflectionDemo02 {
    
        public static void main(String[] args) throws ClassNotFoundException {
    
            // class(外部类、成员内部类、静态内部类、局部内部类、匿名内部类)
            Class objectClass = Object.class;
    
            // interface(接口)
            Class runnableClass = Runnable.class;
    
            // [](数组)
            Class arrayClass = int[].class;
    
            // enum(枚举)
            Class elementTypeClass = ElementType.class;
    
            // @interface(注解)
            Class overrideClass = Override.class;
    
            // primitive_type(基本数据类型)
            Class integerClass = int.class;
    
            // void
            Class voidClass = void.class;
    
        }
    
    }
    

 


 

4. 反射获取类的属性、方法、构造器

  • 获取属性:
    • Class对象.getFields():获取本类所有(包括继承的)公共属性(字段)
    • Class对象.getDeclaredFields():获取本类所有属性(字段)
    • Class对象.getField():获取本类指定的一个(包括继承的)公共属性(字段)
    • Class对象.getDeclaredField():获取本类指定的一个属性(字段)
  • 获取方法:
    • Class对象.getMethods():获取本类所有(包括继承的)公共方法
    • Class对象.getDeclaredMethods():获取本类所有方法
    • Class对象.getMethod():获取本类指定的一个(包括继承的)公共方法
    • Class对象.getDeclaredMethod():获取本类指定的一个方法
  • 获取构造器:
    • Class对象.getConstructors():获取本类所有公共构造器
    • Class对象.getDeclaredConstructors():获取本类所有构造器
    • Class对象.getConstructor():获取本类指定的一个公共构造器
    • Class对象.getDeclaredConstructor():获取本类指定的一个构造器
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

// 获取Class对象的属性、方法、构造器
public class ReflectionDemo03 {

    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {

        // 获取一个Class对象
        Class person2Class = Person2.class;

        // 属性(字段)
        System.out.println("========属性(字段)========");
        Field[] fields;

        fields = person2Class.getFields();  // 获取本类所有(包括继承的)公共属性(字段)
        for (Field field : fields) {
            System.out.println("getFields:"+field);
        }

        fields = person2Class.getDeclaredFields();  // 获取本类所有属性(字段)
        for (Field field : fields) {
            System.out.println("getDeclaredFields:"+field);
        }

        Field field;

        field = person2Class.getField("alias"); // 获取本类指定的一个(包括继承的)公共属性(字段)
        System.out.println("getField:"+field);

        field = person2Class.getDeclaredField("name"); // 获取本类指定的一个属性(字段)
        System.out.println("getDeclaredField:"+field);

        // 方法
        System.out.println("========方法========");
        Method[] methods;

        methods = person2Class.getMethods();    // 获取本类所有(包括继承的)公共方法
        for (Method method : methods) {
            System.out.println("getMethods:"+method);
        }

        methods = person2Class.getDeclaredMethods();    // 获取本类所有方法
        for (Method method : methods) {
            System.out.println("getDeclaredMethods:"+method);
        }

        Method method;

        method = person2Class.getMethod("setName", String.class);    // 获取本类指定的一个(包括继承的)公共方法
        System.out.println("getMethod:"+method);

        method = person2Class.getDeclaredMethod("test");    // 获取本类指定的一个方法
        System.out.println("getDeclaredMethod:"+method);

        // 构造器
        System.out.println("========构造器========");
        Constructor[] constructors;

        constructors = person2Class.getConstructors();  // 获取本类所有的公共构造器
        for (Constructor constructor : constructors) {
            System.out.println("getConstructors:"+constructors);
        }

        constructors = person2Class.getDeclaredConstructors();  // 获取本类所有的构造器
        for (Constructor constructor : constructors) {
            System.out.println("getDeclaredConstructors:"+constructors);
        }

        Constructor constructor;

        constructor = person2Class.getConstructor(String.class,int.class);  // 获取本类指定的一个公共构造器
        System.out.println("getConstructor:"+constructor);

        constructor = person2Class.getDeclaredConstructor(String.class);  // 获取本类指定的一个构造器
        System.out.println("getDeclaredConstructor:"+constructor);

        /*
        结果:
        ========属性(字段)========
        getFields:public java.lang.String com.example.reflection.Person2.alias
        getDeclaredFields:private java.lang.String com.example.reflection.Person2.name
        getDeclaredFields:public java.lang.String com.example.reflection.Person2.alias
        getDeclaredFields:private int com.example.reflection.Person2.age
        getField:public java.lang.String com.example.reflection.Person2.alias
        getDeclaredField:private java.lang.String com.example.reflection.Person2.name
        ========方法========
        getMethods:public java.lang.String com.example.reflection.Person2.toString()
        getMethods:public java.lang.String com.example.reflection.Person2.getName()
        getMethods:public void com.example.reflection.Person2.setName(java.lang.String)
        getMethods:public int com.example.reflection.Person2.getAge()
        getMethods:public void com.example.reflection.Person2.setAge(int)
        getMethods:public final void java.lang.Object.wait() throws java.lang.InterruptedException
        getMethods:public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
        getMethods:public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
        getMethods:public boolean java.lang.Object.equals(java.lang.Object)
        getMethods:public native int java.lang.Object.hashCode()
        getMethods:public final native java.lang.Class java.lang.Object.getClass()
        getMethods:public final native void java.lang.Object.notify()
        getMethods:public final native void java.lang.Object.notifyAll()
        getDeclaredMethods:public java.lang.String com.example.reflection.Person2.toString()
        getDeclaredMethods:public java.lang.String com.example.reflection.Person2.getName()
        getDeclaredMethods:public void com.example.reflection.Person2.setName(java.lang.String)
        getDeclaredMethods:private void com.example.reflection.Person2.test()
        getDeclaredMethods:public int com.example.reflection.Person2.getAge()
        getDeclaredMethods:public void com.example.reflection.Person2.setAge(int)
        getMethod:public void com.example.reflection.Person2.setName(java.lang.String)
        getDeclaredMethod:private void com.example.reflection.Person2.test()
        ========构造器========
        getConstructors:[Ljava.lang.reflect.Constructor;@14ae5a5
        getConstructors:[Ljava.lang.reflect.Constructor;@14ae5a5
        getDeclaredConstructors:[Ljava.lang.reflect.Constructor;@7f31245a
        getDeclaredConstructors:[Ljava.lang.reflect.Constructor;@7f31245a
        getDeclaredConstructors:[Ljava.lang.reflect.Constructor;@7f31245a
        getConstructor:public com.example.reflection.Person2(java.lang.String,int)
        getDeclaredConstructor:private com.example.reflection.Person2(java.lang.String)
         */

    }

}

class Person2 {

    private String name;
    public String alias;
    private int age;

    public Person2() {}

    private Person2(String name) {
        this.name = name;
    }

    public Person2(String name, int age) {
        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;
    }

    private void test() {
        System.out.println("test");
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

}

 


 

5. 动态的创建对象及操作

  • 通过反射动态创建对象有两种方法:
    • 通过Class对象直接创建对象(本质上是调用无参构造器创建对象)
    • 先通过Class对象获取构造器,再通过构造器创建对象
  • 反射操作方法:Class对象获取方法后,通过invoke(对象,参数值)调用方法
  • 反射操作属性:Class对象获取属性后,通过set(对象,参数值)方法给属性赋值
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

// 通过反射动态的创建对象及操作对象(属性、方法)
public class ReflectionDemo04 {

    public static void main(String[] args) throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {

        // 获取一个Class对象
        Class person3Class = Person3.class;

        /* ********创建对象******** */

        // 通过Class对象直接创建对象
        Person3 person1 = (Person3)person3Class.newInstance();  // 本质上是调用无参构造器创建对象
        System.out.println(person1);

        // 先通过Class对象获取构造器,再通过构造器创建对象
        Constructor constructor = person3Class.getDeclaredConstructor(String.class, int.class);
        Person3 person2 = (Person3)constructor.newInstance("小明", 18);
        System.out.println(person2);

        /* ********操作方法******** */
        // 获取方法
        Method setName = person3Class.getDeclaredMethod("setName", String.class);
        // 通过invoke(对象,参数值)调用方法
        setName.invoke(person1,"张三");
        System.out.println(person1.getName());

        /* ********操作属性(字段)******** */
        // 获取属性(字段)
        Field age = person3Class.getDeclaredField("age");
        // 若属性的访问权限有限制,还需要打开访问权限(关闭Java程序的安全检测):setAccessible(true)
        age.setAccessible(true);    // setAccessible还可以提高效率
        // 通过set(对象,参数值)方法给属性赋值
        age.set(person1,20);
        System.out.println(person1.getAge());

        /*
        结果:
        Person{name='null', age=0}
        Person{name='小明', age=18}
        张三
        20
         */

    }

}

class Person3 {

    private String name;
    public String alias;
    private int age;

    public Person3() {}

    private Person3(String name) {
        this.name = name;
    }

    public Person3(String name, int age) {
        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;
    }

    private void test() {
        System.out.println("test");
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

}

 


 

6. 反射获取泛型

  • 获取泛型:Class对象.getGenericParameterTypes()
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;

// 通过反射获取泛型
public class ReflectionDemo05 {

    // 参数值为泛型的方法
    public void test01(Map<String,Integer> map, List<String> list) {
        System.out.println("test01");
    }

    // 返回值为泛型的方法
    public List<String> test02() {
        return null;
    }

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

        // 获取一个Class对象
        Class aClass = ReflectionDemo05.class;

        /* ********获取参数值为泛型的方法的泛型信息******** */
        // 获取方法
        Method test01 = aClass.getMethod("test01", Map.class, List.class);
        // 获取泛型参数类型
        Type[] genericParameterTypes = test01.getGenericParameterTypes();
        for (Type genericParameterType : genericParameterTypes) {
            System.out.println(genericParameterType);
            if(genericParameterType instanceof ParameterizedType) {
                Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments();
                for (Type actualTypeArgument : actualTypeArguments) {
                    System.out.println(actualTypeArgument);
                }
            }
        }

        /* ********获取返回值为泛型的方法的泛型信息******** */
        // 获取方法
        Method test02 = aClass.getMethod("test02", null);
        // 获取泛型参数类型
        Type genericReturnType = test02.getGenericReturnType();
        System.out.println(genericReturnType);
        if(genericReturnType instanceof ParameterizedType) {
            Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();
            for (Type actualTypeArgument : actualTypeArguments) {
                System.out.println(actualTypeArgument);
            }
        }

        /*
        结果:
        java.util.Map<java.lang.String, java.lang.Integer>
        class java.lang.String
        class java.lang.Integer
        java.util.List<java.lang.String>
        class java.lang.String
        java.util.List<java.lang.String>
        class java.lang.String
         */

    }

}

 


 

7. 反射获取注解

  • 获取注解:Class对象.getAnnotations()
import java.lang.annotation.*;
import java.lang.reflect.Field;

// 通过反射获取注解
public class ReflectionDemo06 {

    public static void main(String[] args) {

        // 获取一个Class对象
        Class studentClass = Student.class;

        /* ********获取类的注解******** */
        // 获取注解
        Annotation[] annotations = studentClass.getAnnotations();
        System.out.println(annotations);

        // 获取注解的值
        for (Annotation annotation : annotations) {
            AnnoTable annoTable = (AnnoTable)annotation;
            System.out.println(annoTable.value());
        }

        /* ********获取属性(字段)的注解******** */
        // 获取字段
        Field[] fields = studentClass.getDeclaredFields();

        for (Field field : fields) {
            // 获取注解
            Annotation[] annotations1 = field.getAnnotations();
            System.out.println(annotations1);

            // 获取注解的值
            for (Annotation annotation : annotations1) {
                AnnoField annoField = (AnnoField)annotation;
                System.out.println(annoField.columnName());
                System.out.println(annoField.type());
                System.out.println(annoField.length());
            }
        }

        /*
        结果:
        [Ljava.lang.annotation.Annotation;@60e53b93
        student
        [Ljava.lang.annotation.Annotation;@6f94fa3e
        id
        int
        8
        [Ljava.lang.annotation.Annotation;@5e481248
        name
        varchar
        8
        [Ljava.lang.annotation.Annotation;@66d3c617
        age
        int
        4
         */

    }

}

@AnnoTable("student")
class Student {
    @AnnoField(columnName = "id", type = "int", length = 8)
    private int id;
    @AnnoField(columnName = "name", type = "varchar", length = 8)
    private String name;
    @AnnoField(columnName = "age", type = "int", length = 4)
    private int age;

    public Student() {}

    public Student(int id, String name, int age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    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 "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

}

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface AnnoTable {
    String value();
}

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface AnnoField {
    String columnName();
    String type();
    int length();
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值