Java-反射(有图有例子,清晰易懂)

  • 3、Class对象功能

  • 4、案例

反射:框架设计的灵魂


1、概念

Java反射就是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;并且能改变它的属性。

  • 框架:半成品软件,可以在框架的基础上进行软件开发,简化编码

  • 反射:将类的各个组成部分封装成其他对象(Field,Constructor,Method),这就是反射机制

好处(见第四点)

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

看到这里是不是一脸懵逼,放心看到最后就会豁然开朗的!

2、获取Class对象的方式

什么是Class类?

Class类是一个特殊类,它用于表示JVM运行时类或接口的信息。一个类只有被JVM加载后才能使用,当类被虚拟机加载后都会在内存中创建一个该类的Class对象,用于存储该类的各种信息。

什么是Class对象?

​在Java里万物皆对象,那么每个类除了有自己的对象,这些类其实也都是Class类的对象

Class对象的由来

​磁盘中的字节码文件是无法直接使用的,需要JVM内存中的才可以使用,而加载类时就是在本地磁盘中找到这个类的字节码文件将其加载到JVM内存中并生成对应的Class对象

反射机制允许程序在运行时取得任意一个类的内部信息,那么是怎样获得其信息的呢,就需要我们首先先得到这个类对应的字节码对象,即Class对象。而Class类的构造方法属于私有方法,故无法直接使用new来生成对象,而是使用以下三种方法。

  1. Class.forName(“全类名”):将字节码文件加载进内存,返回Class对象
  • 多用于配置文件,将类名定义在配置文件中,读取文件来加载类
  1. 类名.class():通过类名的属性class获取
  • 多用于参数的传递
  1. 对象.getClass():getClass()方法在Object类中定义着
  • 多用于对象的获取字节码的方式

常用的是第一种方法

以下为各种方式获取Class对象的示例

package com.reflect;

import com.domain.Person;

public class ReflectDemo1 {

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

Class cls = Class.forName(“com.domain.Person”);

System.out.println(cls);

Class cls2 = Person.class;

System.out.println(cls2);

Person p = new Person();

Class cls3 = p.getClass();

System.out.println(cls3);

System.out.println(cls == cls2); // true

System.out.println(cls == cls3); // true

}

}

结论

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

3、Class对象功能

Class对象存储着该类的各种信息,我们可以通过Class类的各种get方法来获取原本类的变量,构造方法以及成员方法等信息,获取方式如下

  1. 获取成员变量们
  • Field[ ] getFields( ):获取所有public修饰的成员变量

  • Field getField(String name):获取指定名称的public修饰的成员变量

  • Field[ ] getDeclaredFields( ):获取所有的成员变量,不考虑修饰符

  • Field getDeclaredField(String name)

  1. 获取构造方法们
  • Constructor<?>[ ] getConstructors( ):获取所有public修饰的构造函数

  • Constructor<?> getConstructor(类<?>… parameterTypes)

  • Constructor<?>[ ] getDeclaredConstructors( ):获取所有构造函数,不考虑修饰符

  • Constructor<?> getDeclaredConstructor(类<?>… parameterTypes)

  1. 获取成员方法们
  • Method[ ] getMethods( ):获取所有public方法(包括父类的方法)

  • Method getMethod(类<?>… parameterTypes)

  • Method[ ] getDeclaredMethods( ):获取所有方法(不包括父类的方法)

  • Method getDeclaredMethod(类<?>… parameterTypes)

  1. 获取类名
  • String getName( ):获取完整类名

获取到类的各个组成部分封装出来的对象之后,就可以通过这个对象来操作类了

Field:成员变量

  1. 设置值:void set(Object obj, Object value)

  2. 获取值:Object get(Object obj)

  3. 忽略访问权限修饰符的安全检查:seeAccessible(true)——暴力反射

package com.reflect;

import com.domain.Person;

import java.lang.reflect.Field;

public class ReflectDemo2 {

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

// 获取person的class对象

Class cls = Person.class;

// 获取所有public修饰的成员变量

Field[] fields = cls.getFields();

for(Field field : fields){

System.out.println(field);

}

// 获取指定名的成员变量

Field field = cls.getField(“height”);

Person p = new Person();

// 获取p对象中名为height的成员变量的值

Object value = field.get§;

System.out.println(value); // 因为是没有设置数据的整形,故默认为0

// 为p对象的height成员变量设置值

field.set(p,150);

System.out.println§;

Field field2 = cls.getDeclaredField(“name”); // 获取private成员变量

field2.setAccessible(true); // 获取或设置非public的成员前需要暴力反射,忽略访问权限修饰符的安全检查

field2.set(p,“cyh”); // 为name成员变量设置值

Object value2 = field2.get§;

System.out.println(value2);

}

}

Constructor:构造方法

  • 创建对象:T newInstance(Object… initargs)

  • 如果使用空参数构造方法创建对象,操作可以简化:使用Class对象的newInstance()方法

package com.reflect;

import com.domain.Person;

import java.lang.reflect.Constructor;

public class ReflectDemo3 {

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

Class personClass = Person.class;

// 获取含三个参数的构造函数

Constructor constructor = personClass.getConstructor(String.class,int.class,int.class);

// 根据这个构造函数创建一个对象

Object person1 = constructor.newInstance(“cyh”,19,170);

System.out.println(person1);

// 获取无参构造函数

Constructor constructor1 = personClass.getConstructor();

// 无参创建一个对象

Object person2 = constructor1.newInstance();

System.out.println(person2);

// 简化无参构造创建对象的方法

Object person3 = personClass.newInstance();// 此法已被抛弃

}

}

Method:方法对象

  • 执行方法:Object invoke(Object obj, Object… args)

  • 获取方法名称:String getName:获取方法名

package com.reflect;

import com.domain.Person;

import java.lang.reflect.Method;

public class ReflectDemo4 {

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

Class personClass = Person.class;

// 获取person类中的所有公有方法(包括父类的方法)

Method[] methods = personClass.getMethods();

for(Method method : methods){

System.out.println(method);

System.out.println(method.getName());

}

System.out.println(“======================”);

// 获取person类中的所有方法(不包括父类的方法)

Method[] methods1 = personClass.getDeclaredMethods();

感受:

其实我投简历的时候,都不太敢投递阿里。因为在阿里一面前已经过了字节的三次面试,投阿里的简历一直没被捞,所以以为简历就挂了。

特别感谢一面的面试官捞了我,给了我机会,同时也认可我的努力和态度。对比我的面经和其他大佬的面经,自己真的是运气好。别人8成实力,我可能8成运气。所以对我而言,我要继续加倍努力,弥补自己技术上的不足,以及与科班大佬们基础上的差距。希望自己能继续保持学习的热情,继续努力走下去。

也祝愿各位同学,都能找到自己心动的offer。

分享我在这次面试前所做的准备(刷题复习资料以及一些大佬们的学习笔记和学习路线),都已经整理成了电子文档

拿到字节跳动offer后,简历被阿里捞了起来,二面迎来了P9"盘问"

Method[] methods1 = personClass.getDeclaredMethods();

感受:

其实我投简历的时候,都不太敢投递阿里。因为在阿里一面前已经过了字节的三次面试,投阿里的简历一直没被捞,所以以为简历就挂了。

特别感谢一面的面试官捞了我,给了我机会,同时也认可我的努力和态度。对比我的面经和其他大佬的面经,自己真的是运气好。别人8成实力,我可能8成运气。所以对我而言,我要继续加倍努力,弥补自己技术上的不足,以及与科班大佬们基础上的差距。希望自己能继续保持学习的热情,继续努力走下去。

也祝愿各位同学,都能找到自己心动的offer。

分享我在这次面试前所做的准备(刷题复习资料以及一些大佬们的学习笔记和学习路线),都已经整理成了电子文档

[外链图片转存中…(img-HTRFjJTk-1714321103177)]

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值