整体区别java
final 用于申明属性,方法和类,表示属性不可变,方法不能够被覆盖,类不能够被继承。
finally 是异常处理语句结构中,表示老是执行的部分。
finallize 表示是object类一个方法,在垃圾回收机制中执行的时候会被调用被回收对象的方法。容许回收此前未回收的内存垃圾。全部object都继承了 finalize()方法mysql
一.final详解程序员
Java中final也用来修饰3类东西:变量,方法和类。
1.变量
final修饰变量表示该变量是不可变的。例如 final int i =1;在程序中i的值就不容许改变了。比较容易混淆的是final用来修饰引用变量时,表示该引用变量是不可变的即引用变量指向的内存地址是不变的,可是被指的内存地址中的类是能够改变的。例如:
final MyClass myClass = new MyClass();
这样声明myClass后,其所指向的内存地址就固定了,但仍然能够改变myClass所引用对象的成员变量。若是试图重用myClass这个变量,让其引用另外一个对象则会出错。
myClass = new MyClass();//error!!!
2.方法
final修饰方法时表示该方法是不能被子类重写的。
3.类sql
final修饰类时表示该类是不能被继承的,因为java的单继承关系,因此该类是继承关系链中的终端。数据库
关于final的几个注意事项:jvm
a、final变量必须在声明的时候初始化或是在构造函数中初始化;
b、接口中声明的全部变量都是final的;
c、final,finally,finalize的区别。final表示不可变,final表示必须执行的语句,finalize表示垃圾回收时执行的代码。函数
二.finalizespa
Java中全部类都从Object类中继承finalize()方法。.net
当垃圾回收器(garbage colector)决定回收某对象时,就会运行该对象的finalize()方法。值得C++程序员注意的是,finalize()方法并不能等同与析构函数。Java中是没有析构函数的。C++的析构函数是在对象消亡时运行的。因为C++没有垃圾回收,对象空间手动回收,因此一旦对象用不到时,程序员就应当把它delete()掉。因此析构函数中常常作一些文件保存之类的收尾工做。可是在Java中很不幸,若是内存老是充足的,那么垃圾回收可能永远不会进行,也就是说filalize()可能永远不被执行,显然期望它作收尾工做是靠不住的。线程
那么finalize()到底是作什么的呢?它最主要的用途是回收特殊渠道申请的内存。Java程序有垃圾回收器,因此通常状况下内存问题不用程序员操心。但有一种JNI(Java Native Interface)调用non-Java程序(C或C++),finalize()的工做就是回收这部分的内存。
三.finally 详解
Java异常处理模型与其余语言相比,关键词finally是最出色的新增特性了。finally构件使得该区段中的代码老是得以执行,而不管是否发生异常,特别适用于维护对象的内部状态(用来保证异常发生恢复对象的有效状态,以确保程序能在处理完异常后自动再次投入运行)和清理non-memory资源(垃圾回收机制没法处理的资源,如数据库链接、Socket等等)。
但有一点值得注意,那就是尽可能不要从try区段中返回(调用return),由于只要有finally区段存在,它就必定会被执行,那么若是你在finally区段中又调用了一次return语句,则try区段中的返回值将会被遮掩,使得方法调用者获得的是finally区段中的返回值--这经常又与程序编写的初衷相背。
首先来问你们一个问题:finally 语句块必定会执行吗?
不少人都认为 finally 语句块是确定要执行的,其中也包括一些颇有经验的 Java 程序员。惋惜并不像大多人所认为的那样,对于这个问题,答案固然是否认的,咱们先来看下面这个例子。
public class Test { public static void main(String[] args) { System.out.println("return value of test(): " + test()); } public static int test() { int i = 1; // if(i == 1) // return 0; System.out.println("the previous statement of try block"); i = i / 0; try { System.out.println("try block"); return i; }finally { System.out.println("finally block"); } } }
清单 1 的执行结果以下:
the previous statement of try block Exception in thread "main" java.lang.ArithmeticException: / by zero at com.bj.charlie.Test.test(Test.java:15) at com.bj.charlie.Test.main(Test.java:6)
另外,若是去掉上例中被注释的两条语句前的注释符,执行结果则是:
return value of test(): 0
在以上两种状况下,finally 语句块都没有执行,说明什么问题呢?只有与 finally 相对应的 try 语句块获得执行的状况下,finally 语句块才会执行。以上两种状况,都是在 try 语句块以前返回(return)或者抛出异常,因此 try 对应的 finally 语句块没有执行。
那好,即便与 finally 相对应的 try 语句块获得执行的状况下,finally 语句块必定会执行吗?很差意思,此次可能又让你们失望了,答案仍然是否认的。请看下面这个例子(清单 2)。
public class Test { public static void main(String[] args) { System.out.println("return value of test(): " + test()); } public static int test() { int i = 1; try { System.out.println("try block"); System.exit(0); return i; }finally { System.out.println("finally block"); } } }
清单 2 的执行结果以下:
try block
finally 语句块仍是没有执行,为何呢?由于咱们在 try 语句块中执行了 System.exit (0) 语句,终止了 Java 虚拟机的运行。那有人说了,在通常的 Java 应用中基本上是不会调用这个 System.exit(0) 方法的。OK !没有问题,咱们不调用 System.exit(0) 这个方法,那么 finally 语句块就必定会执行吗?
再一次让你们失望了,答案仍是否认的。当一个线程在执行 try 语句块或者 catch 语句块时被打断(interrupted)或者被终止(killed),与其相对应的 finally 语句块可能不会执行。还有更极端的状况,就是在线程运行 try 语句块或者 catch 语句块时,忽然死机或者断电,finally 语句块确定不会执行了。可能有人认为死机、断电这些理由有些强词夺理,没有关系,咱们只是为了说明这个问题。
下面,咱们先来看一个简单的例子(清单 3)。
public class Test { public static void main(String[] args) { try { System.out.println("try block"); return ; } finally { System.out.println("finally block"); } } }
清单 3 的执行结果为:
try block finally block
清单 3 说明 finally 语句块在 try 语句块中的 return 语句以前执行。咱们再来看另外一个例子(清单 4)。
public class Test { public static void main(String[] args) { System.out.println("reture value of test() : " + test()); } public static int test(){ int i = 1; try { System.out.println("try block"); i = 1 / 0; return 1; }catch (Exception e){ System.out.println("exception block"); return 2; }finally { System.out.println("finally block"); } } }
清单 4 的执行结果为:
try block exception block finally block reture value of test() : 2
清单 4 说明了 finally 语句块在 catch 语句块中的 return 语句以前执行。
从上面的清单 3 和清单 4,咱们能够看出,其实 finally 语句块是在 try 或者 catch 中的 return 语句以前执行的。更加通常的说法是,finally 语句块应该是在控制转移语句以前执行,控制转移语句除了 return 外,还有 break 和 continue。另外,throw 语句也属于控制转移语句。虽然 return、throw、break 和 continue 都是控制转移语句,可是它们之间是有区别的。其中 return 和 throw 把程序控制权转交给它们的调用者(invoker),而 break 和 continue 的控制权是在当前方法内转移。请你们先记住它们的区别,在后续的分析中咱们还会谈到。
仍是得来点有说服力的证据,下面这段摘自 Java 语言规范第四版(《The Java™ Programming Language, Fourth Edition》),请读者本身体会一下其含义。
好了,看到这里,是否是有人认为本身已经掌握了 finally 的用法了?先别忙着下结论,咱们再来看两个例子 – 清单 5 和清单 6。
public class Test { public static void main(String[] args) { System.out.println("return value of getValue(): " + getValue()); } public static int getValue() { try { return 0; } finally { return 1; } } }
清单 5 的执行结果:
return value of getValue(): 1
public class Test { public static void main(String[] args) { System.out.println("return value of getValue(): " + getValue()); } public static int getValue() { int i = 1; try { return i; } finally { i++; } } }
清单 6 的执行结果:
return value of getValue(): 1
利用咱们上面分析得出的结论:finally 语句块是在 try 或者 catch 中的 return 语句以前执行的。 由此,能够轻松的理解清单 5 的执行结果是 1。由于 finally 中的 return 1;语句要在 try 中的 return 0;语句以前执行,那么 finally 中的 return 1;语句执行后,把程序的控制权转交给了它的调用者 main()函数,而且返回值为 1。那为何清单 6 的返回值不是 2,而是 1 呢?按照清单 5 的分析逻辑,finally 中的 i++;语句应该在 try 中的 return i;以前执行啊? i 的初始值为 1,那么执行 i++;以后为 2,再执行 return i;那不就应该是 2 吗?怎么变成 1 了呢?
关于 Java 虚拟机是如何编译 finally 语句块的问题,有兴趣的读者能够参考《 The JavaTM Virtual Machine Specification, Second Edition 》中 7.13 节 Compiling finally。那里详细介绍了 Java 虚拟机是如何编译 finally 语句块。实际上,Java 虚拟机会把 finally 语句块做为 subroutine(对于这个 subroutine 不知该如何翻译为好,干脆就不翻译了,省得产生歧义和误解。)直接插入到 try 语句块或者 catch 语句块的控制转移语句以前。可是,还有另一个不可忽视的因素,那就是在执行 subroutine(也就是 finally 语句块)以前,try 或者 catch 语句块会保留其返回值到本地变量表(Local Variable Table)中。待 subroutine 执行完毕以后,再恢复保留的返回值到操做数栈中,而后经过 return 或者 throw 语句将其返回给该方法的调用者(invoker)。请注意,前文中咱们曾经提到过 return、throw 和 break、continue 的区别,对于这条规则(保留返回值),只适用于 return 和 throw 语句,不适用于 break 和 continue 语句,由于它们根本就没有返回值。
转自:http://www.ibm.com/developerworks/cn/java/j-lo-finally/