Java反射

本文详细介绍了Java反射的概念,包括反射的作用,如何通过反射获取和使用类的构造方法、属性和成员方法。此外,还讨论了在JDBC、ORM框架中的应用,以及处理私有构造方法的情况。
摘要由CSDN通过智能技术生成

Java反射

反射的作用

  1. 反编译:.class–>.java
  2. 通过反射机制访问java对象的属性,方法,构造方法等

哪些地方用到了反射

  1. Jdbc 加载驱动
  2. Spring IOC的底层
  3. Hibernate、Mybatis、等各种框架(基本上各种ORM框架都使用到了反射)

为什么已有class文件,却要用反射获得实例对象

  1. 反射是动态编译,new是静态编译
  2. 有时我们需要访问别人类中私有的构造方法、成员方法或属性。java反射可以对私有的构造参数实例化,私有构造参数是new不出来的

创建类对象的三种方式

类对象:指定类型为Class的某个类对象

类的对象:通过类new出来的实例,存放在堆空间中

方法1:

//1.通过对象进行获取
        Student student = new Student();
        Class<? extends Student> studentClass1 = student.getClass();//getClass()属于Object类中的方法
        System.out.println(studentClass1);//class com.shujia.day19.Student

方法2:

//2.通过类名.Class的形式获取
        Class<Student> studentClass2 = Student.class;
        System.out.println(studentClass2);//class com.shujia.day19.Student

方法3:

/3.通过反射的方式获取,Class.forName(),括号中需传入一个类路径
        // 类路径可能获取不到对应的类信息,所以可以抛出ClassNotFoundException
        Class<?> studentClass3 = Class.forName("com.shujia.day19.Student");
        System.out.println(studentClass3);//class com.shujia.day19.Student

通过反射获取构造方法从而获取对象

当有权限访问类的构造方法时

可以通过:

getConstructor:获取第一个构造方法

getConstructors:获取所有有权限的构造方法

getDeclaredConstructors:获取所有构造方法

等方法获取类的构造方法

//通过反射获取构造方法,从而获取对象
        Class<Student> studentClass = Student.class;

        //getConstructor->获取第一个构造方法
        Constructor<Student> constructor = studentClass.getConstructor();
        System.out.println(constructor);
        //->public com.shujia.day19.Student()

        //getConstructors获取所有有权限的构造方法
        Constructor<?>[] constructors = studentClass.getConstructors();
        System.out.println(Arrays.toString(constructors));
        //->[public com.shujia.day19.Student(java.lang.String,int), public com.shujia.day19.Student()]

        //getDeclaredConstructors,获取所有构造方法
        Constructor<?>[] declaredConstructors = studentClass.getDeclaredConstructors();
        System.out.println(Arrays.toString(declaredConstructors));
        //->[public com.shujia.day19.Student(java.lang.String,int), private com.shujia.day19.Student(int), private com.shujia.day19.Student(java.lang.String), public com.shujia.day19.Student()]

        //newInstance,获取类对象的实例,注意数组中的构造方法的顺序,取一个构造方法要传入对应的参数
        Constructor<?> declaredConstructorArr = declaredConstructors[0];
        Object o = declaredConstructorArr.newInstance("ww",18);
        System.out.println((Student)o);
        //->com.shujia.day19.Student@14ae5a5

当类的构造方法被private修饰无法构建其对象时

需要使用setAccessible(true)方法使其能够被使用

//获取没有权限的构造方法(private修饰)的实例
        Constructor<?> declaredConstructorByPrivate = declaredConstructors[1];
        //利用.setAccessible(true),使private修饰的构造方法可以被创建实例
        declaredConstructorByPrivate.setAccessible(true);
        Object o1 = declaredConstructorByPrivate.newInstance(20);
        System.out.println(o1);
        //com.shujia.day19.Student@7f31245a

通过反射获取类中的属性

通过反射的方式也可以获取类中的属性

要想获取属性先获取类对象,通过类对象名.getFiled、getFileds、getDeclareFileds等方式可以获取到属性。当属性被默认修饰符或private修饰符修饰外界无法访问时,需要通过setAccessible(true)的方式使其可以被外界使用,赋值时采用set()的方式传入类的对象和属性值,就可以给对应的属性赋值。

//要想获取类的属性,先获取类对象
Class<?> studentClass = Class.forName("com.shujia.day19.Student");
System.out.println(studentClass);//class com.shujia.day19.Student

//getField()传入属性名 即可获取到对应的属性,指定属性的名称获取属性 ,注意默认类型的属性会获取不到
Field name = studentClass.getField("name");
System.out.println(name);
//->public java.lang.String com.shujia.day19.Student.name

//getFields,获取有权限获取到的属性,返回一个数组
Field[] fields = studentClass.getFields();
System.out.println(Arrays.toString(fields));
//->[public java.lang.String com.shujia.day19.Student.name, public int com.shujia.day19.Student.age]

//getDeclaredFields,获取所有类的属性
Field[] declaredFields = studentClass.getDeclaredFields();
System.out.println(Arrays.toString(declaredFields));
//->[public java.lang.String com.shujia.day19.Student.name, public int com.shuji
//对属性的使用,设置属性的值
        //要想设置属性的值需要先获取类的构造方法,通过构造方法获取类的实例
        Constructor<?>[] constructors = studentClass.getConstructors();
//        System.out.println(Arrays.toString(constructors));
        Object studentObj = constructors[1].newInstance();
        //通过属性名.set()的方式可以给对应的属性赋值,括号中传入要赋值的对象,和属性的值
        name.set(studentObj,"yz");
        System.out.println(studentObj);
        //->Student{name='yz', age=0, gender='null', identifyID=0}
//当属性的值被private修饰时
Constructor<?>[] declaredConstructors = studentClass.getDeclaredConstructors();
       System.out.println(Arrays.toString(declaredConstructors));
//        declaredConstructors[3].setAccessible(true);
        Object o = declaredConstructors[4].newInstance();
        System.out.println(o);

        Field gender = studentClass.getDeclaredField("gender");
        gender.setAccessible(true);
        gender.set(o,"man");
        System.out.println(o);

通过反射获取类中的成员方法

要想获取类的成员方法,首先要获得类对象,通过类对象名.getMethod、.getMethods、.getDeclaredMethods等方式获取类中的方法,再通过类对象获取类的对象,使用invoke的方式调用。当方法被private修饰符修饰外界无法访问时,需要通过setAccessible(true)的方式使其可以被外界使用,如果一个类的对象的一些属性在之前的操做中被赋值,在后续使用set时只需要传入对象和剩下未赋值的属性值即可,否则会报错。

Class<?> studentClass = Class.forName("com.shujia.day19.Student");

//getMethod()获取类一个的方法,()中传入方法名和参数列表
Method printInfo = studentClass.getMethod("printInfo", int.class);
System.out.println(printInfo);
//->public void com.shujia.day19.Student.printInfo(int)

//getMethods(),获取所有有权限访问的方法
Method[] methods = studentClass.getMethods();
System.out.println(Arrays.toString(methods));

//.getDeclaredMethods()获取类的所有方法
Method[] declaredMethods = studentClass.getDeclaredMethods();
System.out.println(Arrays.toString(declaredMethods));

//使被private修饰的方法可以被访问
Method skill = studentClass.getDeclaredMethod("skill");
skill.setAccessible(true);
System.out.println(skill);
//-》private void com.shujia.day19.Student.skill()
Field name = studentClass.getField("name");
//获取构造方法
Constructor<?>[] declaredConstructors = studentClass.getDeclaredConstructors();
System.out.println(Arrays.toString(declaredConstructors));
//        declaredConstructors[3].setAccessible(true);
Object o = declaredConstructors[4].newInstance();
//        Object o = constructors.newInstance();
name.set(o,"yz");
System.out.println(o);
//->Student{name='yz', age=0, gender='null', identifyID=0}

//invoke 方法 需要传入两个参数,一个是对象,一个是参数,若某个参数在之前设置过,则只需要传入一个对象,和剩下的未传入值的参数。
printInfo.invoke(o,4);
skill.invoke(o);
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值