反射机制

什么是反射?

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;
对于任意一个对象,都能够调用它的任意一个方法和属性;
这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

反射技术的应用场景

1、JDBC加载驱动连接 class.forName()。

2、Spring容器框架IOC实例化对象。

3、自定义注解 (反射+aop)。

4、第三方核心框架。

创建一个UserEntity类,并创建一个有参构造方法和一个无参构造方法。使用反射去实例化UserEntity类。

public class UserEntity {

    public String publicProperty;

    private String name;

    private int age;

    public UserEntity() {
        System.out.println("这是无参构造方法");
    }

    public UserEntity(String name, int age) {
        this.name = name;
        this.age = age;
        System.out.println("这是有参构造方法:" + this.toString());
    }

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

    private int getNextYearAge() {
        return ++age;
    }


    public Integer getNextYearAge(Integer age) {
        return ++age;
    }

}

 

使用反射实例化对象。

public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        //使用反射获取UserEntity类
        Class<?> aClass = Class.forName("com.exambner.reflection.UserEntity");
        //通过Class调用该类的无参构造方法,去实例化类
        UserEntity user = (UserEntity) aClass.newInstance();
        //通过参数类型调用该类指定有参构造方法
        Constructor<?> constructor = aClass.getConstructor(String.class, int.class);
        UserEntity u = (UserEntity) constructor.newInstance("小明", 18);
        //获取该类中所有的公共构造方法
        Constructor<?>[] constructors = aClass.getConstructors();
        for (Constructor c:constructors){
            System.out.println(c);
        }
    }

运行结果

这是无参构造方法
这是有参构造方法:UserEntity{name='小明', age=18}
public com.exambner.reflection.UserEntity()
public com.exambner.reflection.UserEntity(java.lang.String,int)

 

使用反射给属性赋值

public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException {        //使用反射获取UserEntity类
        Class<?> aClass = Class.forName("com.exambner.reflection.UserEntity");
        //通过Class调用该类的无参构造方法,去实例化类
        UserEntity user = (UserEntity) aClass.newInstance();

        //获取class中所有的公共属性(public),包括父类中的属性
        System.out.println("-------------------------获取class中所有的公共属性,包括父类中的属性----------------------------");
        Field[] fields = aClass.getFields();
        for (Field field : fields) {
            System.out.println(field);
        }
        //获取class中的所有属性,即包括public、private和proteced,但是不包括父类的属性。
        System.out.println("--------------------------获class中的所有属性,即包括public、private和proteced,但是不包括父类的属性。--------------------------------");
        Field[] declaredFields = aClass.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println(declaredField);
        }

        //获取UserEntity中的属性
        System.out.println("-----------------------获取UserEntity中的属性--------------------------------");
        Field name = aClass.getDeclaredField("name");
        Field age = aClass.getDeclaredField("age");
        System.out.println(name);
        System.out.println(age);
        //给属性赋值
        System.out.println("-------------------------给属性赋值---------------------------------------");
        //访问私有属性(private)需先设置访问权限(setAccessible(),为true则可访问,false则不可访问)。否则不可访问:
        //Class com.exambner.reflection.TextReflection can not access a member of class com.exambner.reflection.UserEntity with modifiers "private"
        name.setAccessible(true);
        name.set(user, "小明");
        age.setAccessible(true);
        //赋值时要根据属性对应类型赋相对应类型的值,否则会发生错误:
        //Can not set int field com.exambner.reflection.UserEntity.age to java.lang.String
        age.set(user, 18);
        System.out.println(user.toString());
    }

输出结果

这是无参构造方法
-------------------------获取class中所有的公共属性,包括父类中的属性----------------------------
public java.lang.String com.exambner.reflection.UserEntity.publicProperty
--------------------------获class中的所有属性,即包括public、private和proteced,但是不包括父类的属性。--------------------------------
public java.lang.String com.exambner.reflection.UserEntity.publicProperty
private java.lang.String com.exambner.reflection.UserEntity.name
private int com.exambner.reflection.UserEntity.age
-----------------------获取UserEntity中的属性--------------------------------
private java.lang.String com.exambner.reflection.UserEntity.name
private int com.exambner.reflection.UserEntity.age
-------------------------给属性赋值---------------------------------------
UserEntity{name='小明', age=18}

使用反射调用方法

public class TextReflection {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException, NoSuchMethodException, InvocationTargetException {        //使用反射获取UserEntity类
        Class<?> aClass = Class.forName("com.exambner.reflection.UserEntity");
        //通过Class调用该类的无参构造方法,去实例化类
        UserEntity user = (UserEntity) aClass.newInstance();

        //获取class中所有的公共方法(public),包括父类方法。
        System.out.println("---------------------获取class中所有的公共方法(public),包括父类方法------------------------");
        Method[] methods = aClass.getMethods();
        for (Method method : methods) {
            System.out.println(method);
        }
        //获取类中所有的方法,包括(public、protected、private)。不包括父类中的方法。
        System.out.println("-------------获取类中所有的方法,包括(public、protected、private)。不包括父类中的方法-------------------------");
        Method[] declaredMethods = aClass.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            System.out.println(declaredMethod);
        }
        //调用无参方法
        System.out.println("---------------------------调用无参方法----------------------------------");
        //根据方法名称获取方法实例
        Method getNextYearAge = aClass.getDeclaredMethod("getNextYearAge");
        //通过方法实例调用方法
        //访问私有方法时,需使用使用.setAccessible(true)赋予访问权限,否则不能访问:
        //Class com.exambner.reflection.TextReflection can not access a member of class com.exambner.reflection.UserEntity with modifiers "private"
        getNextYearAge.setAccessible(true);
        Object invoke = getNextYearAge.invoke(user);
        System.out.println(invoke);

        //调用有参方法
        System.out.println("---------------------------调用有参方法----------------------------------");
        //通过方法名称及参数类型获取方法实例
        Method nextYearAge = aClass.getDeclaredMethod("getNextYearAge", Integer.class);
        //执行方法调用
        //这里 public int getNextYearAge(int age) 是一个公共方法,所以不需要去设置访问权限
        Object o = nextYearAge.invoke(user, 18);
        System.out.println(o);

    }
}

输出结果

这是无参构造方法
---------------------获取class中所有的公共方法(public),包括父类方法------------------------
public java.lang.String com.exambner.reflection.UserEntity.toString()
public java.lang.String com.exambner.reflection.UserEntity.getName()
public void com.exambner.reflection.UserEntity.setName(java.lang.String)
public java.lang.Integer com.exambner.reflection.UserEntity.getNextYearAge(java.lang.Integer)
public void com.exambner.reflection.UserEntity.setAge(int)
public int com.exambner.reflection.UserEntity.getAge()
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public boolean java.lang.Object.equals(java.lang.Object)
public native int java.lang.Object.hashCode()
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()
-------------获取类中所有的方法,包括(publicprotectedprivate)。不包括父类中的方法-------------------------
public java.lang.String com.exambner.reflection.UserEntity.toString()
public java.lang.String com.exambner.reflection.UserEntity.getName()
public void com.exambner.reflection.UserEntity.setName(java.lang.String)
private int com.exambner.reflection.UserEntity.getNextYearAge()
public java.lang.Integer com.exambner.reflection.UserEntity.getNextYearAge(java.lang.Integer)
public void com.exambner.reflection.UserEntity.setAge(int)
public int com.exambner.reflection.UserEntity.getAge()
---------------------------调用无参方法----------------------------------
1
---------------------------调用有参方法----------------------------------
19

 

获取方法中的自定义注解

@Retention(RetentionPolicy.RUNTIME)
public @interface MyClass {
    String value() default "";
}
@Retention(RetentionPolicy.RUNTIME)
public @interface MyParams {

    String value() default "";
}
public class TextReflection {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException, NoSuchMethodException, InvocationTargetException {        //使用反射获取UserEntity类
        Class<?> aClass = Class.forName("com.exambner.reflection.UserEntity");
        //通过Class调用该类的无参构造方法,去实例化类
        UserEntity user = (UserEntity) aClass.newInstance();

        //调用有参方法
        System.out.println("---------------------------调用有参方法----------------------------------");
        //通过方法名称及参数类型获取方法实例
        Method nextYearAge = aClass.getDeclaredMethod("getNextYearAge", Integer.class);
        //执行方法调用
        //这里 public int getNextYearAge(int age) 是一个公共方法,所以不需要去设置访问权限
        Object o = nextYearAge.invoke(user, 18);
        System.out.println(o);
        //获取方法参数上的注解
        System.out.println("---------------------------获取方法参数上的注解----------------------------------");
        Annotation[][] parameterAnnotations = nextYearAge.getParameterAnnotations();
        for (Annotation[] parameterAnnotation : parameterAnnotations) {
            for (Annotation annotation : parameterAnnotation) {
                MyParams myParams = (MyParams) annotation;
                System.out.println(myParams.value());
            }
        }
        //获取该方法上的所有注解
        System.out.println("---------------------------获取该方法上的所有注解----------------------------------");
        Annotation[] declaredAnnotations = nextYearAge.getDeclaredAnnotations();
        for (Annotation declaredAnnotation : declaredAnnotations) {
            MyClass myClass = (MyClass) declaredAnnotation;
            System.out.println(myClass.value());
        }
        //根据注解class,获取该方法上注解信息
        System.out.println("---------------------------根据注解class,获取该方法上注解信息----------------------------------");
        MyClass myClass = nextYearAge.getDeclaredAnnotation(MyClass.class);
        //如要做判空,防止方法上不存在该注解,以至于调用注解属性异常
        if (myClass != null) {
            System.out.println(myClass.value());
        }
    }
}

输出结果

这是无参构造方法
---------------------------调用有参方法----------------------------------
19
---------------------------获取方法参数上的注解----------------------------------
age
---------------------------获取该方法上的所有注解----------------------------------
getNextYearAge
---------------------------根据注解class,获取该方法上注解信息----------------------------------
getNextYearAge

Process finished with exit code 0

 

posted @ 2022-12-18 02:30  Amireux-126  阅读(20)  评论(0)    收藏  举报