异常处理
java的异常体系
Error、Exception的区别:Error是程序本身无法处理的错误,Excepttion是程序本身可以处理的异常,捕获处理后系统可能会恢复。
CheckedException是编译时异常,RuntimeException是运行时异常。
可以extends Exception自定义异常种类。
执行顺序
try{
int i = 1 / 0;
}catch (Exception e){
System.out.println("catch...");
}finally {
System.out.println("finally...");
}
System.out.println("other...");
try中没有发生异常:try -> finally -> finally之后的代码
try中发生了异常:
- 不再执行try中后续的代码,转到执行catch
- 如果catch中直接处理完了异常,则执行finally -> finally之后的代码;如果catch中throw往外抛了异常,则不再执行catch中后续的代码,直接执行finally,执行finally后不会再执行finally块之后的代码,而是跳到外层的catch中捕获处理异常(如果有外层的异常处理)。
在方法体中没有捕获处理异常,会跳出该方法的栈帧,导致方法体中后续代码都不会执行。
在循环体中,慎用throw直接抛出异常,如果循环体中的异常直接抛到了循环体外,会导致循环终止,后续批次都不会执行。
比如使用循环批量推送短信,某次循环时发生异常,没有在循环内处理异常,让异常抛到了循环外,则循环会被终止,循环中后续批次的消息都不会发送。
循环这种批量操作的场景,往往要尽量避免循环被异常终止,保证循环的继续执行,在循环体中可能发生异常的地方使用try…catch捕获处理掉异常。
异常块的优化
try…catch块对性能的影响主要体现在2方面
- 会影响指令重排序
- 发生异常时会生成Exception对象,需要保存栈快照等信息,开销大
优化点
- 不要大量使用try-catch
- 减少try中的代码量,能放到try外面就尽量放到外面
初始化块
初始化块和成员变量、成员函数一个级别,一般用于初始化。
class Xxx {
// 普通初始化块
{
}
// 静态初始化块
static {
}
// ......
}
一个类中可以有多个初始化块,如果都是static初始化块或者普通初始化块,越靠前的越先执行。
static初始化快只能访问类的静态成员,只在JVM加载类的class对象时执行1次,常用于初始化类的静态成员、公共资源。
编译时,会把普通初始化块中的代码放到构造函数函数体内的最前面。每次创建对象时,在执行构造函数之前,都会先执行普通初始化快。普通初始化快常用与初始化对象。
final关键字
final可修饰类、变量(包括成员变量、局部变量)、方法
- 被final修饰的类不能被继承
- 被final修饰的变量,声明时就必须赋值,后续不能修改其值,即只读。基本类型、String类型不能改变值,引用类型不能修改引用(内存地址),但可以修改引用指向的对象本身。
- 被final修饰的方法不能被重写
运算符优先级
运算符 | 结合性 |
---|---|
[ ] . ( ) 访问数据元素、调用成员、小括号 | 从左向右 |
! ~ ++ – + - 单目运算符 | 从右向左 |
* / % 乘除取模 | 从左向右 |
+ - 加减 | 从左向右 |
<< >> >>> 位运算 | 从左向右 |
< <= > >= instanceof 比较判断 | 从左向右 |
== != 等价判断 | 从左向右 |
& | 从左向右 |
^ | 从左向右 |
| | 从左向右 |
&& | 从左向右 |
|| | 从左向右 |
? : 三目运算符 | 从右向左 |
= += -= *= /= %= &= |= ^= <<= >>= >>= 赋值 | 从右向左 |
, | 从左到右 |
常见运算符的优先级
单目 > 算术运算 > 位运算 > 条件判断 > 逻辑运算 > 三目 > 赋值
>>>是无符号右移,和>>右移一样,只是不考虑最高位的正负,不管最高位原来是0还是1,都直接取0。