1. final
final意味着“最后的、最终的”含义,final可以用来修饰类,方法和变量(成员变量或局部变量)。
1.1 修饰类
当用final修饰类时,表明该类不能被其他类所继承。String是一个典型的final类型的类。
注意:final类中所有的成员方法都会隐式的定义为final方法。
1.2 修饰方法
把方法锁定,以防止继承类对其进行更改。如:枚举类中的equals()/clone()
此方法不能被重写,也不能在子类中重新定义同名同参的新方法
1.3 修饰变量
final成员变量表示常量,只能被赋值一次,赋值后其值不再改变。
当final修饰一个基本数据类型时,表示该基本数据类型的值一旦在初始化后便不能发生变化;
如果final修饰一个引用类型时,则在对其初始化之后便不能再让其指向其他对象了,但该引用所指向的对象的内容是可以发生变化的,即地址的值不发生变化。
final修饰一个成员变量(属性),必须要显示初始化。这里有三种初始化方式,一种是在变量声明的时候初始化;第二种方法是在代码块中赋值;第三种方法是在构造函数中对这个变量赋初值。
final修饰一个方法形参,一旦调用该方法(传入了实参),该参数值就不能再修改。
2. finally
finally是在处理异常时搭配try/catch语句使用,并且附带一个语句块,在服务正常运行的情况下finally语句块最终一定会被执行(不管有没有抛出异常),经常被用于释放资源。
注意:只有与finally对应的try语句块得到执行的情况下,finally语句块才一定会执行。
@Test
public void test(){
List<String> list = Arrays.asList("123", "12345", "1234", "4321", "1234567", "5678");
//在执行try语句块之前就已经返回,finally不会执行
// if(list.size() ==6 ){
// return;
// }
//在执行try语句块之前抛出异常,所以try对应的finally语句并没有执行。
//int i = 1/0;
try {
list.forEach(s -> {
if (s.length() > 5) {
//模拟出现异常
throw new RuntimeException("foreach跳出循环");
}
System.out.println(s);
});
} catch (Exception e) {
System.out.println("捕获异常" + e.getMessage());
}finally{
System.out.println("finally语句块执行!!!");
}
}
当一个线程在执行 try 语句块或者 catch 语句块时被打断(interrupted)或者被终止(killed),与其相对应的 finally 语句块可能不会执行。
如果finally中有return语句,,且已经执行到了try代码块,则不会执行try/catch中的return语句;如果finally中没有return,则执行完finally块中的代码,再执行try/catch中的return语句。
public static void main(String[] args) {
String s = testFinallyReturn();
System.out.println(s); //finally
}
public static String testFinallyReturn(){
List<String> list = Arrays.asList("123", "12345", "1234", "4321", "1234567", "5678");
try {
list.forEach(s -> {
if (s.length() > 5) {
//模拟出现异常
throw new RuntimeException("foreach跳出循环");
}
System.out.println(s);
});
return "成功";
} catch (Exception e) {
System.out.println(e.getMessage());
return "异常";
}finally{
System.out.println("finally语句块执行!!!");
//return "finally";
}
}
3. finalize
finalize()是在java.lang.Object里定义的,也就是说每一个对象都有这么个方法。这个方法在gc启动,该对象被回收的时候被调用。其实gc可以回收大部分的对象(凡是new出来的对象,gc都能搞定,一般情况下我们又不会用new以外的方式去创建对象),反射方式可以创建对象,所以一般是不需要程序员去实现finalize的。
特殊情况下,需要程序员实现finalize,当对象被回收的时候释放一些资源,比如:一个socket链接,在对象初始化时创建,整个生命周期内有效,那么就需要实现finalize,关闭这个链接。
使用finalize还需要注意一个事,调用super.finalize();
一个对象的finalize()方法只会被调用一次,而且finalize()被调用不意味着gc会立即回收该对象,所以有可能调用finalize()后,该对象又不需要被回收了,然后到了真正要被回收的时候,因为前面调用过一次,所以不会再调用finalize(),进而产生问题。 所以,不推荐手动调用finalize()方法
,它跟析构函数不一样。