1. Java 序列化

    java序列化和反序列化以及序列化ID

  2. Java 中的 final 关键字

  3. final关键字

    final修饰变量的本质: final修饰的变量会指向一块固定的内存, 这块内存中的值不能改变.

  4. try中有return时执行顺序、finally

​ return语句并不是函数的最终出口,如果有finally语句,这在return之后还会先执行finally(return的值会暂存在栈里面,等待finally执行后再返回)

  1. 线程的隔离级别
  2. 各种注入标识,autowired
  3. future设计模式
  4. Future,FutureTask,Callable,Runnable关系
  5. SpringMVC拦截器和过滤器

一、序列化(Java)

  1. 什么是序列化

序列化是指将 Java 对象转换为字节序列的过程,而反序列化则是将字节序列转换为 Java 对象的过程。

  1. 原因

序列化之后将数据分解成字节流,以便1. 存储在文件中或者2. 在网络上传输。

加上:3. 实现分布式对象,如RMI(远程方法调用)要利用对象序列化运行远程主机上的服务,就像在本地机上运行对象时一样

序列化目的:数据存储与传输以及实现分布式对象

  1. 实现方法

  2. 注意点

    • transient修饰的成员变量不会被序列化(transient 代表对象的临时数据)
    • 静态static修饰的成员变量不会被序列化
    • 序列化运行时会使用一个称为 serialVersionUID 的版本号,并与每个可序列化的类相关联,该序列号在反序列化过程中用于验证,序列化对象的发送者和接收者,是否为该对象,加载了与序列化兼容的类。如果接收者加载的该对象的类的serialVersionUID ,与对应的发送者的类的版本号不同,则反序列化将会导致 InvalidClassException。可序列化类可以通过声明名为 “serialVersionUID” 的字段(该字段必须是静态 (static)、最终 (final) 的 long 型字段)显式声明其自己的 serialVersionUID。
  1. 实现案例
public class SerialDemo {

public static void main(String[] args) throws IOException, ClassNotFoundException {
// 序列化对象User
FileOutputStream fos = new FileOutputStream("object.txt");
ObjectOutputStream oos = new ObjectOutputStream(fos);
User user1 = new User("xcbeyond", "123456789");
oos.writeObject(user1);
oos.flush();
oos.close();

// 反序列化
FileInputStream fis = new FileInputStream("object.txt");
ObjectInputStream ois = new ObjectInputStream(fis);
User user2 = (User) ois.readObject();
System.out.println(user2.getUsername()+ "," + user2.getPassword());
}
}
// 对象User,对其实现了Serializable接口
public class User implements Serializable {
private String username;
private String password;

……

}

参考:

七、Future设计模式

https://www.bilibili.com/video/BV1ov41167vH?t=60.4

(交数学作业时偷偷交一份语文作业,然后狂补,等到数学老师改到的时候再换回数学作业)

  1. 为什么出现Future机制

    常见的两种创建线程的方式。一种是直接继承Thread,另外一种就是实现Runnable接口。

    这两种方式都有一个缺陷就是:在执行完任务之后无法获取执行结果

​ 因此从Java 1.5开始,就提供了Callable和Future,通过它们可以在任务执行完毕之后得到任务执行结果。

​ Future模式的核心思想是能够让主线程将原来需要同步等待的这段时间用来做其他的事情。(因为可以异步获得执行结果,所以不用 一直同步等待去获得执行结果)

​ 上图简单描述了不使用Future和使用Future的区别,不使用Future模式,主线程在invoke完一些耗时逻辑之后需要等待,这个耗时逻辑在实际应用中可能是一次RPC调用,可能是一个本地IO操作等。B图表达的是使用Future模式之后,我们主线程在invoke之后可以立即返回,去做其他的事情,回头再来看看刚才提交的invoke有没有结果。

参考:

八、 关系

实现Runnable接口和实现Callable接口的区别

  1. Runnable(java.lang.Runnable)是自从java1.1就有了,而Callable(java.util.concurrent…)是1.5之后才加上去的。

  2. Callable规定的方法是call(),Runnable规定的方法是run()。

  3. Callable的任务执行后可返回值,而Runnable的任务是不能返回值(是void)。

  4. call方法可以抛出异常,run方法不可以。

  5. 运行Callable任务可以拿到一个Future对象,表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成,并检索计算的结果。通过Future对象可以了解任务执行情况,可取消任务的执行,还可获取执行结果。

  6. 加入线程池运行,Runnable使用ExecutorService的execute方法,Callable使用submit方法。