Java中final、finally、finalize的区别
定义上的区别
-
final是java关键字,用于声明属性,方法和类,分别表示属性不可交变,方法不可覆盖,类不可继承。
-
finally是java中异常处理语句结构的一部分,表示总是执行。
-
finalize是Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,供垃圾收集时的其他资源回收,例如关闭文件等。
用法上的区别
- final:java中的关键字,修饰符
A).如果一个类被声明为final,就意味着它不能再派生出新的子类,不能作为父类被继承。因此,一个类不能同时被声明为abstract抽象类的和final的类。
B).如果将变量或者方法声明为final,可以保证它们在使用中不被改变.
1)被声明为final的变量必须在声明时给定初值,而在以后的引用中只能读取,不可修改。
2)被声明final的方法只能使用,不能重载。
- finally:java的一种异常处理机制
finally是对Java异常处理模型的最佳补充。finally结构使代码总会执行,而不管无异常发生。使用finally可以维护对象的内部状态,并可以清理非内存资源。特别是在关闭数据库连接这方面,如果程序员把数据库连接的close()方法放到finally中,就会大大降低程序出错的几率。
- finalize:Java中的一个方法名
Java技术使用finalize()方法在垃圾收集器将对象从内存中清除出去前,做必要的清理工作。这个方法是由垃圾收集器在确定这个对象没被引用时对这个对象调用的。它是在Object类中定义的,因此所的类都继承了它。子类覆盖finalize()方法以整理系统资源或者执行其他清理工作。finalize()方法是在垃圾收集器删除对象之前对这个对象调用的。
高级区别
final关键字
-
final定义变量时必须注意
1)、在定义时初始化或者在初始化代码块中初始化
2)、非静态final变量不能在静态初始化块中初始化
3)、静态final常量,在定义时初始化或者在静态代码块中初始化
4)、静态变量不能在初始化代码块中初始化
5)、静态final变量不可以在构造器中初始化
6)、final变量未被初始化,编译时就会报错public class FinalTest{ public final int A=10; //在定义时初始化 public final int B;{B=20;} //在初始化块中初始化 //非静态final变量不能在静态初始化块中初始化 //public final int C;static{//C=30; } //静态常量,在定义时初始化 public static final int STATIC_D=40; //静态常量,在静态初始化块中初始化 public static final int STATIC_E;static{STATIC_E = 50;} //静态变量不能在初始化块中初始化 //public static final int STATIC_F;{STATIC_F=60;} public final int G; //静态final变量不可以在构造器中初始化 //public static final int STATIC_H; //在构造器中初始化 public finalTest(){ G=70; //静态final变量不可以在构造器中初始化 //STATIC_H=80; //给final的变量第二次赋值时,编译会报错 //A=99; //STATIC_D=99; } //final变量未被初始化,编译时就会报错 //public final int L; //静态final变量未被初始化,编译时就会报错 //public static final int STATIC_J; }
-
final用来定义一个方法时,它表示这个方法不可以被子类重写,但是并不影响它被子类继承。
-
final的类的所方法都不能被重写,但这并不表示final的类的属性(变量值也是不可改变的,要想做到final类的属性值不可改变,必须给它增加final修饰。
finally
-
finally只能用在try/catch语句中并且附带着一个语句块,表示这段语句最终总是被执行。
-
return、continue、break这个可以打乱代码顺序执行语句的规律,可以使finally语句块得不到执行。
public final class FinallyTest { //测试return语句 //结果显示:编译器在编译return new ReturnClass();时, //将它分成了两个步骤,new ReturnClass()和return,前一个创建对象的语句是在finally语句块之前被执行的, //而后一个return语句是在finally语句块之后执行的,也就是说finally语句块是在程序退出方法之前被执行的 public ReturnClass testReturn() { try { return new ReturnClass(); } catch (Exception e) { e.printStackTrace(); } finally { System.out.println("执行了finally语句"); } return null; } //测试continue语句 public void testContinue() { for (int i = 0; i < 3; i++) { try { System.out.println(i); if (i == 1) { System.out.println("con"); } } catch (Exception e) { e.printStackTrace(); } finally { System.out.println("执行了finally语句"); } } } //测试break语句 public void testBreak() { for (int i = 0; i < 3; i++) { try { System.out.println(i); if (i == 1) { break; } } catch (Exception e) { e.printStackTrace(); } finally { System.out.println("执行了finally语句"); } } } public static void main(String[] args) { FinallyTest ft = new FinallyTest(); // 测试return语句 ft.testReturn(); System.out.println(); // 测试continue语句 ft.testContinue(); System.out.println(); // 测试break语句 ft.testBreak(); } } class ReturnClass { public ReturnClass() { System.out.println("执行了return语句"); } }
输出结果:
执行了return语句
执行了finally语句
0
执行了finally语句
1
con
执行了finally语句
2
执行了finally语句
0
执行了finally语句
1
执行了finally语句
输出的结果来看,return语句似乎在finally语句块之前执行了,事实真的如此吗?我们来想想看,return语句的作用是什么呢?是退出当前的方法,并将值或对象返回。如果 finally语句块是在return语句之后执行的,那么return语句被执行后就已经退出当前方法了,finally语句块又如何能被执行呢?因此,正确的执行顺序应该是这样的:编译器在编译return new ReturnClass();时,将它分成了两个步骤,new ReturnClass()和return,前一个创建对象的语句是在finally语句块之前被执行的,而后一个return语句是在finally语句块之后执行的,也就是说finally语句块是在程序退出方法之前被执行的。同样,finally语句块是在循环被跳过(continue和中断(break之前被执行的 。
finalize
finalize,它是一个方法,属于java.lang.Object类,它的定义如下:protected void finalize()throws Throwable{}众所周知,finalize()方法是GC(garbagecollector运行机制的一部分,在此我们只说说finalize()方法的作用是什么呢?finalize()方法是在GC清理它所从属的对象时被调用的,如果执行它的过程中抛出了无法捕获的异(uncaughtexception,GC将终止对改对象的清理,并且该异常会被忽略;直到下一次GC开始清理这个对象时,它的finalize()会被再次调用。