关于 Java 异常机制的补充

为什么 Java 中打开物理资源,如磁盘文件、网络连接、数据库连接等,必须需要显式的关闭?

JVM 提供的垃圾回收机制只负责堆内存分配出来的内存,打开的物理资源,GC 是不进行回收的,所以需要手动的关闭。

如何正确的关闭资源?

  1. 在 finall 中执行资源关闭操作。
  2. 保证关闭资源前资源不为 null,因为存在资源初始化前就发生异常情况,所以在 finally 语句中对资源对象进行非空判断。
  3. 为每个资源关闭操作执行 try/catch 操作,因为在资源关闭过程中也有可能发生异常,导致程序中断。

Read More

Java 异常机制浅析

处理错误

异常分类

所有的异常都是继承于 Throwable

运行时内存区域

Error 类层次结构描述了 Java 运行时内部的错误以及资源耗尽错误,应用程序不应该抛出这种类型的对象,而是让程序来处理,一般情况下程序会直接中断,并报出错误以及堆栈信息。

Read More

RxJava Transformer

0x81 Observable、Observer 线程切换

在 Retrofit 结合 RxJava 进行开发时,我们可以通过 subscribeOn()、observeOn() 分别设置被订阅者和订阅者的线程。在此场景中,我们要在应用中的所有请求中执行上面操作,这下重复工作就需要 Transformer 来优化。

0x82 Transformer 实现对调用链的处理

我们可能有以下实现方式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
abstract class SchedulerTransformer<T> protected constructor(private val subscribeOnScheduler: Scheduler = Schedulers.io(), 
private val observeOnScheduler: Scheduler = AndroidSchedulers.mainThread()) : ObservableTransformer<T, T>,
SingleTransformer<T, T>,
MaybeTransformer<T, T>,
CompletableTransformer,
FlowableTransformer<T, T> {

override fun apply(upstream: Completable): CompletableSource {
return upstream.subscribeOn(subscribeOnScheduler)
.observeOn(observeOnScheduler)
}

override fun apply(upstream: Flowable<T>): Publisher<T> {
return upstream.subscribeOn(subscribeOnScheduler)
.observeOn(observeOnScheduler)
}

override fun apply(upstream: Maybe<T>): MaybeSource<T> {
return upstream.subscribeOn(subscribeOnScheduler)
.observeOn(observeOnScheduler)
}

override fun apply(upstream: Observable<T>): ObservableSource<T> {
return upstream.subscribeOn(subscribeOnScheduler)
.observeOn(observeOnScheduler)
}

override fun apply(upstream: Single<T>): SingleSource<T> {
return upstream.subscribeOn(subscribeOnScheduler)
.observeOn(observeOnScheduler)
}
}

Read More

Dagger2 前奏篇:依赖注入概念

一、What is Dagger2 ?

Dagger2 是一个谷歌开源的依赖注入(Dependency Injection)框架,简称DI。Dagger2 是 Google 出的依赖注入框架。肯定有小伙伴疑问,为什么会有个 2 呢。该框架是基于 Square 开发的 Dagger 基础上开发的。
那么 什么是 依赖注入 呢?

1.1 何为依赖注入(控制反转 – IOC(Inversion of Control))

我在网上搜索了相关内容,觉得以下解释相对容易理解(自定义后):

Read More

OKhttp3 核心拦截器、应用拦截器、网络拦截器

2019-12-10 更新,见文末。

RetryAndFollowUpInterceptor

功能:实现重试、跟踪

实现原理:

while(true) 死循环,如果发生重定向则构建 Request,进入下一次循环,从新发起网络请求,但是最大重定向次数为 20 次。

  • 检验返回的 Response ,如果没有异常(包括请求失败、重定向等),那么执行 return Response, return 会直接结束循环操作,将结果返回到下一个拦截器中进行处理。

  • 检验返回的 Response ,如果出现异常情况,那么会根据 Response 新建 Request,并且执行一些必要的检查(是否为同一个 connnetion ,是的话抛出异常,不是的话是否旧的 connection 的资源,并新建一个 connection)
    ,在构建重定向请求时,从 Response 中取出 Location 字段,构建重定向后的 Request。下一次循环时,将进行新一轮的拦截器的处理。

Read More

hexo 博客维护

关于 Hexo 博客建站

自己在 2016 基于 Hexo + GitPage 搭建个人博客,但是看到推到 Github 上的代码是 hexo g 生成的 public 文件夹下文件,那我日后怎么维护。自己看到别人上传的代码却是真正的 source 文件。

今日自己才知道,需要维护两套代码,一套真正的 source 文件,一套部署到 github 的代码,真是废柴。

关于 Hexo 主题

自己在网上搜索了一部分主题,有的页面概念过于繁杂,有的页面过于花哨,自己的主要目的是博客记录,搭建时默认的 Hexo 主题已经满足要求,就不再更换主题(于今日有效,万一哪天遇到称心得主题)。

JVM 运行时内存分布

1. 概述

Java 不像 C/C++ 需要程序员自己管理内存,Java 把内存控制的权利交给类 Java 虚拟机。

2. 运行时数据区域

JVM 在 Java 程序运行时把它所管理的内存划分为几个不同的数据区域。

2.1 程序计数器

程序计数器是一块较小的内存,它可以看作 当前线程 所执行的 字节码的行号指示器在虚拟机的概念模型里,字节码解释器的工作就是通过改变这个计数器的值 来选取下一条需要执行的字节码,分支、循环、跳转、异常处理、线程恢复等基础功能都需要这个计数器来完成。

如上图所示,程序计数器是线程私有的。

如何执行工作

如果线程正在执行一个 Java 方法,这个计数器记录的正是执行的虚拟机字节码指令的地址,如果执行的是 Native 方法,这个计数器值为空。

Read More

Java 泛型:深入理解通配符

1. 通配符概念

因为 List 是泛型类,为了 表示各种泛型 List 的父类,可以使用类型通配符,类型通配符使用问号(?)表示,将一个问号当做类型元素传递个 List,可以表示为 List<?>,意思是 元素类型未知的 List,不同于 List 其元素类型为 T。这个问号被称为通配符,它的元素类型可以匹配任何类型。

Read More