Java反射

什么是反射 在spring项目中,只需要写个@Service或者@Component,然后在别的地方用@Autowired声明一个接口变量,Spring就能返回给我们一个实现了该接口的具体对象。这是如何实现的呢?它不可能在编译时就知道加了注解的类与类之间的关系,所以只能是在程序启动运行时,Spring动态地发现了这些类,读取了他们的结构,然后创建对象。这背后的技术支撑又是什么?答案就是反射。 反射是Java提供的一种在程序运行时 检查/获取类、接口、字段、方法、构造器等结构信息的能力。 操作/调用对象、字段、方法的能力。 它就像一面镜子,让程序在运行时“照见”自己的结构。 反射的基石:Class对象 编译器在编译 Java 源代码时会生成 .class 文件(字节码文件)。当 JVM 需要用到某个类时,它的类加载器会读取并解析对应的 .class 文件,在方法区(或元空间)构建该类的运行时数据结构,同时在堆内存中创建一个代表该类的 java.lang.Class 对象。每个被加载的类在 JVM 中都有且只有一个对应的 Class 对象(在同一个类加载器命名空间内)。 这里的Class是一个类的名字,不要和class关键字搞混。 有三种方法获取Class对象 Person person = new Person("me", 20); //法一:通过对象实例 Class< ? extends Person> clazz1 = person.getClass(); //法二:自带属性(基本数据类型也有) Class<Person> clazz2 = Person.class; //法三:Class类的静态方法 forName try { Class<?> clazz3 = Class.forName("org.myblog.reflection.Person"); } catch (ClassNotFoundException e) { throw new RuntimeException(e); } 解释一下这三种方法泛型的使用:法一使用Class<? extends Person> 因为Class对象是在运行时从Person实例获取的,而Person实例的具体类型只能在运行时创建和确定,编译阶段无法判断,所以使用通配符 ,又因为person可能是Person实例,也可能是Person的子类实例,所以最终写成Class< ? extends Person>;法二使用Class<Person>因为编译时已知具体类型;法三使用Class<?>因为通过字符串动态加载类,编译时无法确定具体类型,所以使用通配符。这三个 Class 对象都是同一个(上面也提到了,一个类唯一对应一个 Class 对象)。 ...

August 10, 2025 · 3 min · 518 words · Me

遇到的奇葩BUG

此篇博客记录我学习过程中遇到的奇葩BUG SpringBoot项目启动失败 如上图,SpringBoot项目启动失败。 虽然说是端口占用,但我执行相关命令后没有任何输出,修改启动端口不行,尝试了很多办法都未成功,那只好使出我的终极大招:重启idea。还是不行。幸好我还有终极终极大招:重启电脑。嘿,你猜怎么着,成了!🤣 接口测试报错getaddrinfo ENOTFOUND https 一次简单的接口测试,出现报错getaddrinfo ENOTFOUND https,搜索后得到答案:这通常意味着应用程序无法解析主机名或域名。这可能是由于DNS配置问题、网络连接问题或拼写错误等原因导致的。前两个果断排除,开始以为参数错,但一想那不应该试着错误,后来想可能域名错,但也没找到错误。最后发现是https:后面多了个空格。😑 mysql容器连接报错 情况描述:本机为windows系统,装有wsl。在配置一个项目时使用docker-compose命令构建项目所需容器。构建好容器后,我测试mysql是否连接成功,结果出现报错2013 - Lost connection to server at 'handshake: reading initial communication packet', system error: 0. 于是到网上搜索解决方案,有注释掉bind-address = 127.0.0.1的,有添加配置skip-name-resolve的,还有换系统的,但都无法解决我的问题。直到看见这篇博客CSDN博客。于是我直接修改docker-compose.yaml文件,添加network_mode: host,同时从豆包处得知:使用 host 网络模式后,容器会直接使用宿主机的网络栈,因此 ports 配置会被忽略。如果需要 MySQL 监听 3307 端口,需在 MySQL 配置文件(/etc/my.cnf 目录下的配置)中添加 port=3307,照做后问题解决。 还要记得修改application.yml中的端口设置。

August 2, 2025 · 1 min · 43 words · Me

Java序列化与反序列化

什么是序列化和反序列化 序列化,人话讲就是将对象转换为字节序列(也可以是JSON、XML等文本格式),反序列化就是把这个过程倒置。 下面是维基百科关于序列化的介绍 序列化(serialization)在计算机科学的资料处理中,是指将数据结构或对象状态转换成可取用格式(例如存成文件,存于缓冲,或经由网络中发送),以留待后续在相同或另一台计算机环境中,能恢复原先状态的过程。依照序列化格式重新获取字节的结果时,可以利用它来产生与原始对象相同语义的副本。对于许多对象,像是使用大量引用的复杂对象,这种序列化重建的过程并不容易。面向对象中的对象序列化,并不概括之前原始对象所关系的函数。这种过程也称为对象编组(marshalling)。从一系列字节提取数据结构的反向操作,是反序列化(也称为解编组、deserialization、unmarshalling)。 对于Java这种面向对象的编程语言来说,是对实例化后的对象进行序列化,而对于C++这种半面向对象的编程语言来说,序列化的目标不仅有对象(class)还有数据结构(struct) 序列化的使用场景 数据存储:比如序列化可以将存储在 JVM 堆区中的对象转换成字节序列,从而实现持久化。 网络通信:将对象转换为字节序列方便其在网络中进行传递和接收。 使用Java实现序列化 以 JDK 自带序列化方法为例,实现java.io.Serializable接口 @Data public class Cat implements Serializable { private int age; private String name; private Date birth; } 序列化演示: public class serializeTest { public static void main(String[] args) { Cat cat = new Cat(); cat.setName("tom"); cat.setAge(2); cat.setBirth(new Date()); //使用ObjectOutputStream将cat对象序列化并存入test1.txt文件中 try (FileOutputStream fileOutputStream = new FileOutputStream("test1.txt"); ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream)) { objectOutputStream.writeObject(cat); } catch (IOException e) { e.printStackTrace(); } } } 反序列化演示: ...

July 7, 2025 · 2 min · 340 words · Me

我的第一篇文章

简介 这是 粗体 文本,这是 斜体 文本。 访问 Hugo 网站!

November 20, 2022 · 1 min · 9 words · Me