一、反射
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象.
1.1 反射的理解
Java 中 的 反 射 首 先 是 能 够 获 取 到 Java 中 要 反 射 类 的 字 节 码 , 获 取 字 节 码 有 三 种 方 法 :
1.Class.forName(className)
2.类名.class
3.this.getClass()
然后将字节码中的方法,变量,构造函数等映射成相应的 Method、Filed、Constructor 等类,这些类提供了丰富的方法可以被我们所使用。
1.2 反射的应用场景
在Java中,反射(Reflection)是指程序在运行时可以访问、检测和修改其自身状态或行为的能力。通过反射,可以在运行时动态地获取类的信息、调用类的方法、访问类的属性,并进行一些其他的操作。
反射的应用场景包括:
-
动态加载类:
使用反射可以在运行时动态加载指定的类。通过 Class.forName() 方法或类加载器,可以根据类的全限定名动态加载类,并创建该类的实例。 -
获取类的信息:
通过反射可以获取类的各种元数据信息,如类的名称、父类、接口实现、构造方法、字段、方法等。可以通过调用 getClass() 或 class 关键字获取某个对象的类信息。 -
创建实例对象:
反射允许通过类的构造方法创建一个新的对象,即使没有直接访问类的构造方法。可以使用 Class 对象的 newInstance() 方法来创建类的实例对象。 -
调用方法:
通过反射可以在运行时动态调用类的方法。可以使用 Method 对象的 invoke() 方法调用类的方法,并传递相应的参数。 -
获取和设置字段值:
通过反射可以获取和设置类的字段的值。可以使用 Field 对象的 get() 和 set() 方法来访问和修改字段的值。 -
注解处理:
通过反射可以在运行时检查和处理类和字段上的注解信息。可以使用 Annotation 对象和注解处理器来处理注解,实现自定义的逻辑。
反射在一些框架和工具库中被广泛使用,例如:
-
Spring框架:
使用反射实现了IoC(控制反转)和AOP(面向切面编程)的功能,通过动态加载类、调用方法和访问属性来实现依赖注入和切面编程。 -
Hibernate ORM:Hibernate是一个ORM(对象关系映射)框架,它使用反射来实现对象和数据库之间的映射。通过使用注解或XML配置,Hibernate能够根据实体类的属性,动态生成和执行对应的SQL语句,从而将对象的状态持久化到数据库中。
-
JUnit测试框架:JUnit测试框架使用反射来发现和执行测试方法。通过分析测试类中的注解和方法,JUnit能够动态地运行各个测试方法,收集结果并生成报告。
-
JSON序列化和反序列化:许多JSON解析库(如Jackson、Gson)使用反射来在Java对象和JSON数据之间进行转换。通过分析Java对象的结构,这些库能够将对象属性映射为JSON键值对,或者根据JSON数据来创建相应的Java对象。
-
动态代理:反射可以用于实现动态代理模式。通过创建代理类和实现InvocationHandler接口,可以在运行时动态生成代理对象,从而进行一些额外的操作,如添加日志、权限校验等。
需要注意的是,尽管反射提供了灵活性和强大的能力,但由于其涉及到运行时的元数据操作,性能相对较低。因此,在使用反射时应谨慎考虑其影响,并尽量保证代码的可读性和性能的高效性。
二、IO流
2.1 IO流的划分
**按照流的方向:**输入流(inputStream)和输出流(outputStream)。
**按照实现功能分:**节点流(可以从或向一个特定的地方(节点)读写数据。如 FileReader)和处理流(是对一个已存在的流的连接和封装,通过所封装的流的功能调用实现数据读写。如BufferedReader。处理流的构造方法总是要带一个其他的流对象做参数。一个流对象经过其他流的多次包装,称为流的链接。)
**按照处理数据的单位:**字节流和字符流。字节流继承于 InputStream 和 OutputStream,字符流继承于InputStreamReader 和 OutputStreamWriter。
2.2 字节流如何转为字符流
字节输入流转字符输入流通过 InputStreamReader 实现,该类的构造函数可以传入 InputStream 对象。
字节输出流转字符输出流通过 OutputStreamWriter 实现,该类的构造函数可以传入 OutputStream 对象。
2.3 字节流和字符流的区别
字节流读取的时候,读到一个字节就返回一个字节; 字符流使用了字节流读到一个或多个字节(中文对应的字节数是两个,在 UTF-8 码表中是 3 个字节)时。先去查指定的编码表,将查到的字符返回。 字节流可以处理所有类型数据,如:图片,MP3,AVI 视频文件,而字符流只能处理字符数据。只要是处理纯文本数据,就要优先考虑使用字符流,除此之外都用字节流。字节流主要是操作 byte 类型数据,以 byte 数组为准,主要操作类就是 OutputStream、InputStream
字符流处理的单元为 2 个字节的 Unicode 字符,分别操作字符、字符数组或字符串,而字节流处理单元为 1 个字节,操作字节和字节数组。所以字符流是由 Java 虚拟机将字节转化为 2 个字节的Unicode 字符为单位的字符而成的,所以它对多国语言支持性比较好!如果是音频文件、图片、歌曲,就用字节流好点,如果是关系到中文(文本)的,用字符流好点。在程序中一个字符等于两个字节,java 提供了 Reader、Writer 两个专门操作字符流的类。