Java反射

Java反射

什么是Java的反射机制?

java反射就是在运行状态中,对于任意一个类都知道这个类的所有属性和方法;对于任何一个对象都能调用它的属性和方法,这种动态调用对象的方法、获取类的信息的功能称为Java语言的反射机制。
优点:运行时期动态加载类,和类的判断,提高了代码的灵活性。
缺点:反射相当于一系列解释的操作,通知jvm要做的事情,性能比直接Java代码慢。

如何实现反射?


package com.reflection;

public class GetClass {
    public static void main(String[] args) {
        //方法一 通过创建的对象
        Student student = new Student();
        Class<? extends Student> aClass1 = student.getClass();//获取运行时类

        //方法二 通过相对路径,包名.类名
        try {
            Class<?> aClass2 = Class.forName("com.reflection.Student");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

        //方法三 通过类名
        Class<Student> aClass3 = Student.class;
    }
}
class Student {
    private String name;
    private int age;
    private String sex;
}

注意:一个类在JVM中只有一个Class实例,所以上面这三个Class实例调用equals()方法结果为true。

通过反射去调用方法和属性

package com.reflection;

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

/**
 * @Description 反射机制
 * @author RAy-LlT
 * @date 2021/8/24 15:37
 */
public class GetClass {
    public static void main(String[] args) throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
        Class<Student> aClass = Student.class;

        //获取类名称com.Reflection.Student
        aClass.getName();

        //获取类及其父类中的所有public属性
        Field[] fields = aClass.getFields();
        //获取指定public类型的属性,也就是fields中包含的属性
        Field age = aClass.getField("age");
        //获取该类中声明所有类型的属性
        Field[] declaredFields = aClass.getDeclaredFields();
        //获取指定的属性,也就是declaredFields中包含的属性
        Field name = aClass.getDeclaredField("name");

        //通过类的不带参数的构造方法创建这个类的一个对象,因此要想在任意地方直接通过此方法去实例化,那么你的修饰符必须为public
        Student student = aClass.newInstance();
        //获得类的public类型的构造方法
        Constructor<?>[] constructors = aClass.getConstructors();
        //获取指定的构造方法(public),此处获取的为private类型,所以会抛出NoSuchMethodException异常
        try {
            Constructor<Student> constructor1 = aClass.getConstructor(String.class, int.class, String.class);
        } catch (NoSuchMethodException e) {
            System.out.println(e);
        }
        //获取所有类型的构造方法
        Constructor<?>[] declaredConstructors = aClass.getDeclaredConstructors();
        //获取指定的任意构造方法
        Constructor<Student> declaredConstructor = aClass.getDeclaredConstructor(String.class, int.class, String.class);
        //值为true则指示反射的对象在使用是应该取消Java语言访问检查,就可以暴力调用私有方法进行实例化
        declaredConstructor.setAccessible(true);
        //此处的student实例并不能访问其私有类型的属性,除非设置私有属性取消java语言的访问检查
        Student student1 = declaredConstructor.newInstance("碎涛", 21, "男");
        //通过反射生成的实例,只能直接  对象.它的public属性和方法,其他的只能单独去获取,设置其取消java语言的访问检查
        student1.age = 20;
        name.setAccessible(true);
        name.set(student1, "java长征记");
        name.get(student1);

        //获取Student类的public方法以及其所继承的父类的public方法,当然也包括Object类中的一些方法
        Method[] methods = aClass.getMethods();
        //获取指定的public类型的方法,也就是上面methods中的所有方法
        Method print1 = aClass.getMethod("print1", int.class);
        //调用invoke( )方法执行获取到的方法
        print1.invoke(student1, 1314);
        //获取该类中声明的除构造方法之外的所有方法,不包含父类
        Method[] declaredMethods = aClass.getDeclaredMethods();
        //获取指定的任意类型的方法(该类中),也就是上面declaredMethods中包含的方法
        Method print2 = aClass.getDeclaredMethod("print2", String.class);
        
        //获取其父类,想获取其父类的的私有属性和方法就可以先获取其父类Class实例,然后再去按照上面的方法获取就可以了
        Class<? super Student> superclass = aClass.getSuperclass();
    }

}

class Person {
    private String birth;
    public int height;
    protected int weight;

    public void ppp() {
        System.out.println("WX搜索:java长征记");
    }

    protected void aaa() {
        System.out.println("WX搜索:java长征记");
    }

    private String lll() {
        return "WX搜索:java长征记";
    }
}

class Student extends Person {
    private String name;
    public int age;
    private String sex;


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

    private Student(String name, int age, String sex) {
        this.name = name;
        this.age = age;
        this.sex = sex;
        System.out.println("private 有参的构造方法");
    }

    public void print1(int a) {
        System.out.println(a);
    }

    private void print2(String s) {
        System.out.println(s);
    }
}

注意:使用反射可以打破封装性,导致了Java对象的属性不安全。因此,String类中的对象不可变其实是可以通过反射去改变的。

package com.reflection;

import java.lang.reflect.Field;

/**
 * @Description 反射修改String对象不可变
 * @Author RAy-LlT
 * @Date 2021/11/18 14:40
 */
public class ChangeString {
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
        //创建字符串"Hello World", 并赋给引用s
        String s = "Hello World";
        System.out.println("s=" + s);//s = Hello World
        // 获取String类中的value字段
        Field valueFieldOfString = String.class.getDeclaredField("value");
        // 改变value属性的访问权限
        valueFieldOfString.setAccessible(true);
        // 获取s对象上的value属性的值
        char[] value = (char[]) valueFieldOfString.get(s);
        // 改变value所引用的数组中的第5个字符
        value[5] = '_';
        System.out.println("s = " + s); // s = Hello_World
    }
}

反射的应用场景

1.加载数据库的驱动;

Class.forName("com.mysql.jdbc.Driver");

2.获取对象的属性,方法,类和类的构造方法等;
3.instanceof 关键字是通过反射来实现的;
4.IDEA、Eclipse在输入“.”之后会自动弹出相应的方法和属性,是通过反射来实现的;
5.Spring框架里面的xml装配文件等。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值