序列化和反序列化
- 都是完成对Java对象的操作,将Java对象写入本地硬盘的文件中,将本地文件中存储的Java对象还原到Java内存中;
- 序列化就是指将内存中的对象输出到硬盘中进行保存,反序列化就是相反的操作,从文件中读取数据并还原成内存中的数据;
如何使用序列化
给类实现接口java.io.Serializable,该类的对象就具备了序列化的功能;
package com.wei.demo1;
import java.io.Serializable;
public class User implements Serializable {
private Integer id;
private String name;
private Integer age;
public User(Integer id, String name, Integer age) {
this.id = id;
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "User{" +
"id=" + id + ", name='" + name + '\'' +
", age=" + age +
'}';
}
}
节点流(直接连接文件)、处理流(必须建立在节点流的基础上)
package com.wei.demo1;
import java.io.*;
public class Test {
public static void main(String[] args) throws Exception {
//创建对象
User user = new User(1,"张三",22);
//开始序列化
OutputStream outputStream = new FileOutputStream("D:\\javahome\\test.txt");
ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
objectOutputStream.writeObject(user);
objectOutputStream.flush();
objectOutputStream.close();
outputStream.close();
}
}
持久化:将数据永久的保存下来;
反序列化
从文件中读取数据还原成Java对象;
package com.wei.demo1;
import java.io.*;
public class Test2 {
public static void main(String[] args) throws Exception {
InputStream inputStream = new FileInputStream("D:\\javahome\\test.txt");
ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);
User user = (User) objectInputStream.readObject();
System.out.println(user);
objectInputStream.close();
inputStream.close();
}
}
反射
- 很难理解、非常抽象、非常重要;
- 现阶段只需要了解反射的基本概念,基于应用即可;
- Spring框架阶段需要深入了解
什么是反射
- 常规情况下是通过类来创建实例化对象的,反射就是将这一个过程进行反转,通过实例化对象来获取对象类的信息;
- 我们通过反射就是在程序运行期间获取类的结构进而完成某些特定的功能;
Class类
- Class类是反射的基础,Java中是通过一个对象来描述某个类的信息;
- Class类是专门描述其他类的。每个Class类的实例化对象都有对应某个类的信息;
- 创建Class对象的方式有3种:
- 通过调用Class静态方法forName(String className);
- 通过目标类创建;
- 通过目标类的对象创建
package com.wei.demo1;
public class Test3 {
public static void main(String[] args) throws Exception {
//目标类是 User,获取其信息,获取 User 对 应的 Class 对象 //全类名、全限定类名(带着包名的类名 com.wei.demo1.User)
Class clazz1 = Class.forName("com.southwind.demo1.User");
System.out.println(clazz1);
//这里的 class 是类字面量
Class clazz2 = User.class;
System.out.println(clazz2);
User user = new User(1,"张三",22);
Class clazz3 = user.getClass();
System.out.println(clazz3);
System.out.println(clazz1 == clazz2);
System.out.println(clazz2 == clazz3);
}
}
获取Class的目的是调用他的方法进而获取到目标类的各种信息;
方法 | 描述 |
---|---|
boolean isInterface() | 判断该类是否为接口 |
boolean isArray() | 判断该类是否为数组 |
boolean isAnnotation() | 判断该类是否为注解 |
String getName() | 获取类的全限定类名 |
ClassLoader getClassLoader() | 获取类加载器 |
Class getSuperclass() | 获取父类 |
Package getPackage() | 获取类所在的包 |
Package geyPackage() | 获取类所在的包 |
Class getInterfaces() | 获取类所实现的接口 |
Field[] getFields() | 获取类的所有成员变量 |
Method[] getMethods() | 获取类中所有方法 |
Method getMethod(String name,Class… args) | 获取类中指定的方法 |
Constructor[] getConstructors() | 获取所有构造器 |
Constructor getConstructor(Class… args) | 获取指定的构造器 |
package com.wei.demo1;
import java,lang,reflect.Constructor;
import java.lang.reflect.Field;
public class Test4{
public static void main(String args[]) throws Exception{
Class<User> clazz=User.class;
Class<?>[] interfaces=clazz.getInterfaces();
for (Class<?> anInterface : interfaces) {
System.out.println(anInterface);
}
System.out.println("************************ **************");
//只能获取类中的公有成员变量,获取父类中的共 有成员变量
// Field[] fields = clazz.getFields();
//获取所有的成员变量,只能获取当前类的成员变 量
Field[] declaredFields = clazz.getDeclaredFields();
for (Field field : declaredFields){
System.out.println(field);
}
}
}
获取目标构造函数
- getConstructors()是用来获取目标类的共有构造函数;
- getConstructor(parameters…)是用来获取目标类的某个公有构造函数;
- getDeclaredConstructors()是用来获取目标类的全部构造函数;
- getDeclaredConstructor(parameters…)用来获取目标类的某个构造函数;
- clazz.getConstructor(int.class)获取int参数构造器;
- java.lang.NoSuchMethodException:表示没有该方法;
package com.wei.demo1;
import java.lang.reflect.Constructor;
public class Test {
public static void main(String[] args) throws Exception {
//Class是反射的源头,要使用反射,必须先获取 Class对象
Class clazz = User.class;
//Constructor专门用来描述构造函数
Constructor constructor = clazz.getDeclaredConstructor(int.class);
System.out.println(constructor);
//通过构造器创建对象
System.out.println(constructor.newInstance(1 ));
System.out.println(new User(1));
}
}
获取目标类的方法
- getMethods()获取目标类的公有方法(包含父类公有方法);
- getDeclaredMethod()获取目标类的所有方法(不包含父类);
//常规操作
User user=new User();
user.rest1("name");
//反射操作
Constructor constructor=clazz.getConstructor(null);
method.invock(constructor.bewInstance(null),("name"));
package com.wei.demo1;
import java.lang.reflect.Method;
public class User {
public User(){ }
public User(int id){ }
@Override
public String toString() {
return "User{}";
}
//有参/无参
//共有和私有
public void test1(String string){
System.out.println("test1");
}
public void test2(){
System.out.println("test2");
}
private void test3(Student student){
System.out.println("test3");
}
private void test4(){
System.out.println("test4");
}
public static void main(String[] args) throws Exception {
Class clazz = User.class;
Constructor constructor = clazz.getConstructor(null);
User user = (User) constructor.newInstance(null);
// //方法为主体
Method method2 = clazz.getMethod("test2", null);
Method method3 = clazz.getDeclaredMethod("test3", Student.class);
Method method4 = clazz.getDeclaredMethod("test4", null);
method2.invoke(user,null);
method3.invoke(user,new Student());
method4.invoke(user);
}
}
获取成员变量
NoSuchFieldException:表示没有这个成员变量;
package com.wei.demo1;
import java.lang.reflect.Field;
public class Test4 {
public static void main(String[] args) throws Exception {
Class clazz = Student.class;
Student student = new Student(1);
Student student2 = new Student(2);
Field field = clazz.getDeclaredField("id");
//暴力反射,在外部可以访问私有成员变量
field.setAccessible(true);
field.set(student,100);
System.out.println(student);
}
}
反射提供了一种特性,可以在外部访问类中的私有信息,包括成员变量、方法、构造函数;
只需要调用对应资源的setAccessible(true)即可,设置暴力反射,一般不建议这样使用,因为这样或破坏类的封装性;