final,finalize,finally 的區別
final finalize finally 的區別
一、性質不同(1)final為關鍵字;
(2)finalize()為方法;
(3)finally為為區塊標誌,用於try語句中;
二、作用
(1)final為用於標識常量的關鍵字,final標識的關鍵字儲存在常量池中(在這裡final常量的具體用法將在下面進行介紹);
(2)finalize()方法在Object中進行了定義,用於在物件“消失”時,由JVM進行呼叫,用於對物件進行垃圾回收,類似於C++中的解構函式;使用者自定義時,用於釋放物件佔用的資源(比如進行I/0操作)
(3)finally{}用於標識程式碼塊,與try{}進行配合,不論try中的程式碼執行完或沒有執行完(這裡指有異常),該程式碼塊之中的程式必定會進行;
三、詳解
final 是一種修飾符(關鍵字),final具有"不可改變的"含義,它可以修飾非抽象類、非抽象成員方法和變數。如果一個類被宣告為final,意味著它不能再派生出新的子類,不能作為父類被繼承。因此一個類不能既被宣告為 abstract的(能夠被繼承,而且可能含有抽象方法),又被宣告為final(不能被繼承)的。將變數或方法宣告為 final,可以保證它們在使用中不被改變。被宣告為final的變數必須在宣告時給定初值,而在以後的引 用中只能讀取,不可修改。被宣告為final的方法也同樣只能使用,不能過載
final定義變數問題
3.1.1 final定義基本型別變數時,要求變數初始化必須在宣告時或者建構函式中,不能用於其它地方。該關鍵字定義的常量,除了初始化階段,不能更改常量的值。
3.1.2 final定義物件的引用,該引用的初始化與定義常量時的要求一致;該關鍵字定義的物件內容可以改變,但是引用指向的地址不能改變;
final定義引數問題
3.2.1 如果傳入該引數定義的變數時,方法不能對該引數內容進行修改,與定義變數的修改規則相同;java方法中傳遞基本型別時是傳值的,java方法對於物件的傳遞是傳參的;歸根結底,java中方法的傳遞是依靠傳遞“副本”:對於基本型別,首先建立一個Copy,並將傳入的值賦值給Copy,然後對Copy進行操作;對於物件型別,首先建立一個引用Copy,並將傳入的物件引用賦值給Copy;
如下面所示 final修飾的屬性(成員變數)賦值的位置:
非靜態的成員變數
1.宣告的同時
2.匿名程式碼塊
3.構造器(類中出現的所有構造器)
靜態的成員變數
1.宣告的同時
2.static程式碼塊
a. final可以修飾靜態變數、例項變數、區域性變數;
b. final變數都必須顯示初始化,否則會導致編譯錯誤;
1) 靜態變數,定義變數時進行初始化或者static程式碼塊中賦值;
2) 例項變數,可以在定義變數時,或者在構造方法中進行初始化;
c. final變數只能賦一次值。
eg1:
public class Sample {
private final int var1 = 1;
public Sample() {
var1 = 2; //編譯出錯,不允許改變var1例項變數的值;
}
public void method(final int param) {
final int var2 = 1;
var2++; //編譯出錯,不允許改變var2區域性常量的值
param++; //編譯出錯,不允許改變final型別引數的值;
}
}
eg2: public class Sample {
final int var1; //定義var1例項常量
final int var2 = 0; //定義並初始化var2例項常量
Sample() {
var1 = 1; //初始化var1例項常量
}
Sample(int x) {
var1 = x; //初始化var1例項常量
}
}
3.1.1定義方法(1)使用final關鍵字定義的方法,不能被子類繼承,某些情況下,出於安全原因,父類不允許子類覆蓋某個方法, 此時可以把這個方法宣告為final型別。例如在 java.lang.Object類中,getClass()方法為final型別;
(2)允許編譯器將所有對此方法的呼叫轉化為inline(行內)行為,即可以將此方法直接複製在呼叫處,而不是進行例行的方法呼叫(儲存斷點、壓棧),這樣會使程式的效率升高。但是---------如果過多的話,這樣會造成程式碼膨脹,反而會影響效率,所以該方法要慎用。。
(3) final不能用來修飾構造方法,因為"方法覆蓋"這一概念僅適用於類的成員方法,而不適用於類的構造方法,父類的構造方法和子類的構造方法之間不存在覆蓋關係. 因此用final修飾構造方法是無意義的。父類中用private修飾的方法不能被子類的方法覆蓋,因此private型別的方法預設是final型別的。
4.1.1定義類
繼承關係的弱點是打破封裝,子類能夠訪問父類的方法,而且能以方法覆蓋的方式修改實現細節。在以下情況下,可以考慮把類定義為final型別,使得這個類不能被繼承。
. 子類有可能會錯誤地修改父類的實現細節;
. 出於安全,類的實現細節不允許有任何改動;
. 在建立物件模型時,確信這個類不會再被擴充套件;
例如JDK中java.lang.String類被定義為final型別;
(二)、finalize詳解
finalize 屬於方法名。Java 技術允許使用 finalize() 方法在垃圾收集器將物件從記憶體中清除出去 之前做必要的清理工作。
這個方法是由垃圾收集器在確定這個物件沒有被引用時對這個物件呼叫的。它 是在 Object 類中定義的,因此所有的類都繼承了它。子類覆蓋 finalize() 方法以整理系統資源或者 執行其他清理工作。finalize() 方法是在垃圾收集器刪除物件之前對這個物件呼叫的。
屬於java.lang.Object類,檢視API能夠知道它的定義如下:
protected void finalize() throws Throwable { }
finalize()方法是在GC清理它所從屬的物件時被呼叫的,如果執行它的過程中丟擲了無法捕獲的異常(uncaught exception),GC將終止對該物件的清理,並且該異常會被忽略;直到下一次GC開始清理這個物件時,它的finalize()會被再次呼叫。
請看下面的示例:
package sample;
public class FinalizeTest
{
// 重寫finalize()方法
protected void finalize() throws Throwable
{
System.out.println("執行了finalize()方法");
}
public static void main(String[] args)
{
FinalizeTest fl = new FinalizeTest();
fl = null;
System.gc();//呼叫垃圾回收機制
}
}
執行結果如下:即呼叫了重寫的方法,顯示:執行了finalize()方法
Runtime.getRuntime().gc();
呼叫它們的作用只是建議垃圾收集器(GC)啟動,清理無用的物件釋放記憶體空間,但是GC的啟動並不是一定的,這由JAVA虛擬機器來決定。直到 JAVA虛擬機器停止執行,有些物件的finalize()可能都沒有被執行過,那麼怎樣保證所有物件的這個方法在JAVA虛擬機器停止執行之前一定被呼叫呢?答案是我們可以呼叫System類的另一個方法:
public static void runFinalizersOnExit(boolean value) {
//other code
}
給這個方法傳入true就可以保證物件的finalize()方法在JAVA虛擬機器停止執行前一定被執行了,不過遺憾的是這個方法是不安全的,它會導致有用的物件finalize()被誤呼叫,因此已經不被贊成使用了。由於finalize()屬於Object類,因此所有類都有這個方法,Object的任意子類都可以重寫(override)該方法,在其中釋放系統資源或者做其它的清理工作,如關閉輸入輸出流。
(三)、finally詳解
finally 在異常處理時提供 finally 塊來執行必須進行的操作。finally{}用於標識程式碼塊,與try{}進行配合,不論try中的程式碼執行完或沒有執行完(這裡指有異常),該程式碼塊之中的程式必定會進行;如果丟擲一個異常,那麼相匹配 的 catch 子句就會執行,然後控制就會進入 finally 塊(如果有的話)。如果不丟擲異常,則會從try塊中直接跳轉到finally塊中。如下面程式段:
(1)有異常時:
package sample;
public class TryCatchFinally
{
//用於輸出,定義函式專門用於輸出
public static void sop(Object o)
{
System.out.println(o);
}
//定義函式用於表示出錯資訊
static public int div(int a,int b)
{
int res=0;
try
{
res=a/b;
}
catch(ArithmeticException e)
{
sop("in catch");
}
finally
{
sop("in Finally");
}
return res;
}
//主函式
public static void main(String[] args)
{
sop("Main0:"+div(10,0));
}
}
結果如下所示:
如下程式碼,不存在異常時
package sample;
public class FinallyTest
{
//用於輸出,定義函式專門用於輸出
public static void sop(Object o)
{
System.out.println(o);
}
//定義函式用於表示出錯資訊
static public int div(int a,int b)
{
int res=0;
try
{
res=a/b;
}
catch(ArithmeticException e)
{
sop("in catch");
}
finally
{
sop("in Finally");
}
return res;
}
//主函式
public static void main(String[] args)
{
sop("Main0:"+div(10,2));
}
}
執行結果如下所示:沒有執行catch塊,但和有異常時一樣,同樣執行finally塊
以上就是三者的區別
相關文章
- Java中final、finally、finalize的區別Java
- final、finally、finalize()的區別(skycto JEEditor)
- Java中final,finally,finalize的區別Java
- final:finalize:finally:
- final、finally、finalize的理解
- 徹底區分final.finalize,finally
- 【Java面試題系列】:Java中final finally finalize的區別Java面試題
- final,finalize,finally的不同之處
- final、finally、finalize的詳細分析
- final,finally,finallize的區別
- 異常-面試題之final,finally和finalize的區別,如果在finally之前有return面試題
- 【java】final、finally、finallize的區別Java
- 『Java 語法基礎』final、finalize 和 finally 的不同之處Java
- final和finalize
- 看完這篇 final、finally 和 finalize 和麵試官扯皮就沒問題了
- final修飾和static final修飾的區別
- final與static關鍵字的區別?(skycto JEEditor)
- Flutter 知識梳理 (Dart) - Dart 中 static, final, const 區別FlutterDart
- finalize方法
- try-catch-finally的使用
- java中的Static、final、Static final各種用法Java
- java exception and finally returnJavaException
- [Java基礎]FinallyJava
- LinkedList和ArrayList的區別、Vector和ArrayList的區別
- http和https的區別/get和post的區別HTTP
- final
- Python檔案操作:finally子句的使用Python
- ||和??的區別
- /*和/**的區別
- ??與?:的區別
- 蜂蜜的區別
- .finally is not a function —— 解決低版本瀏覽器axios不支援finallyFunction瀏覽器iOS
- C# Dispose 和 Finalize 要點C#
- GC和解構函式(Finalize 方法)GC函式
- Java趣味分享:try/finallyJava
- 謹慎 try-finally
- C++11新特性之final override識別符號C++IDE符號
- python異常處理中finally的作用Python
- UIModalPresentationStyle 各種型別的區別UI型別