国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|

服務器之家 - 編程語言 - JAVA教程 - JAVA中的final關鍵字用法實例詳解

JAVA中的final關鍵字用法實例詳解

2020-03-10 11:30NW_KNIFE JAVA教程

這篇文章主要介紹了JAVA中的final關鍵字用法,結合實例形式較為詳細的分析了Java中的final關鍵字用于修飾數據,方法及類的具體使用技巧,需要的朋友可以參考下

本文實例講述了JAVA中的final關鍵字用法。分享給大家供大家參考,具體如下:

根據上下文環境,java的關鍵字final也存在著細微的區別,但通常指的是“這是無法改變的。”不想改變的理由有兩種:一種是效率,另一種是設計。由于兩個原因相差很遠,所以關鍵子final可能被誤用。

接下來介紹一下使用到final的三中情況:數據,方法,類

final數據

許多編程語言都有某種方法,來向編譯器告知一塊數據是恒定不變的。有時數據的恒定不變是很有用的,例如:

1. 一個編譯時恒定不變的常量
2. 一個在運行時初始化,而你不希望它被改變。

對于編譯期常量的這種情況,編譯器可以將該常量值代入任何可能用到它的計算式中,也就是說,可以在編譯期就執行計算式,這減輕了一些運行時的負擔。在java中,這類常量必須是基本類型,并且以final表示。在對這個常量定義時,必須進行賦值。

一個即是static又是final的域只占一段不能改變的存儲空間。

當final應用于對象引用時,而不是基本類型時,其含義有些讓人疑惑。對基本類型使用final不能改變的是他的數值。而對于對象引用,不能改變的是他的引用,而對象本身是可以修改的。一旦一個final引用被初始化指向一個對象,這個引用將不能在指向其他對象。java并未提供對任何對象恒定不變的支持。這一限制也通用適用于數組,它也是對象。例如:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
package finalPackage;
import java.util.*;
class Value {
  int i;
  public Value(int i) {
    this.i = i;
  }
}
/**
 * final數據常量
 * @author Administrator
 * 對基本類型使用final不能改變的是它的數值。
 * 而對于對象引用,不能改變的是他的引用,而對象本身是可以修改的。
 * 一旦一個final引用被初始化指向一個對象,這個引用將不能在指向其他對象。
 * 注意,根據慣例,即是static又是final的域(即編譯器常量)將用大寫表示,并用下劃分割個單詞。
 */
public class FinalData {
  private static Random rand = new Random(47);
  private String id;
  public FinalData(String id) {
    this.id = id;
  }
  // 編譯時常量 Can be compile-time constants:
  private final int valueOne = 9;
  private static final int VALUE_TWO = 99;
  // 典型的公共常量 Typical public constant:
  public static final int VALUE_THREE = 39;
  // 運行時常量 Cannot be compile-time constants:
  private final int i4 = rand.nextInt(20);
  static final int INT_5 = rand.nextInt(20);
  private Value v1 = new Value(11);
  private final Value v2 = new Value(22);
  private static final Value VAL_3 = new Value(33);
  // 數組 Arrays:
  private final int[] a = { 1, 2, 3, 4, 5, 6 };
  public String toString() {
    return id + ": " + "i4 = " + i4 + ", INT_5 = " + INT_5;
  }
  public static void main(String[] args) {
    FinalData fd1 = new FinalData("fd1");
    // ! fd1.valueOne++; // Error: can't change value
    fd1.v2.i++; // Object isn't constant!
    fd1.v1 = new Value(9); // OK -- not final
    for (int i = 0; i < fd1.a.length; i++)
      fd1.a[i]++; // Object isn't constant!
    // ! fd1.v2 = new Value(0); // Error: Can't
    // ! fd1.VAL_3 = new Value(1); // change reference
    // ! fd1.a = new int[3];
    System.out.println(fd1);
    System.out.println("Creating new FinalData");
    FinalData fd2 = new FinalData("fd2");
    System.out.println(fd1);
    System.out.println(fd2);
  }
  /**
   * 輸出結果:
   * fd1: i4 = 15, INT_5 = 18
   * Creating new FinalData
   * fd1: i4 = 15, INT_5 = 18
   * fd2: i4 = 13, INT_5 = 18
   */
}

由于valueOne和VALUE_TWO都是帶有編譯時數值的final基本類型,所以它們二者均可以用作編譯期常量,并且沒有重大區別。VALUE_THREE是一種更加典型的對常量進行定義的方式:定義為public,可以被任何人訪問;定義為static,則強調只有一份;定義為final,這說明它是個常量。請注意帶有恒定初始值的final static基本類型全用大寫字母命名,并且字母與字母之間用下劃線隔開。

我們不能因為某些數據是final的就認為在編譯時可以知道它的值。在運行時使用隨機數來初始化i4和INT_5的值說明了這一點。實例中fd1和fd2中i4的值是唯一的,每次都會被初始化為15,13。INT_5的值是不可以通過創建第二個FinalData對象加以改變的。這是因為他是static的,在裝載類時(也就是第一次創建這個類對象時)已經被初始化,而不是每次創建都初始化。

java也許生成"空白final",所謂空白final是指被聲明為final但又未給初值的域。無論什么情況下編譯器都會保證final域在使用前初始化。但空白final在final的使用上提供了很大的靈活性,為此,一個final域可以根據某些對象有所不同,卻又保持恒定不變的特性。下面的事例說明了一點:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
package finalPackage;
class Poppet {
  private int i;
  Poppet(int ii) {
    i = ii;
  }
  public int getI() {
    return i;
  }
  public void setI(int i) {
    this.i = i;
  }
}
/**
 * 空白final
 * @author Administrator
 * 所謂空白final是指被聲明為final但又未給初值的域。無論什么情況下編譯器都會保證final域在使用前初始化。
 */
public class BlankFinal {
  private final int i = 0; // Initialized final
  private final int j; // Blank final
  private final Poppet p; // Blank final reference
  // Blank finals MUST be initialized in the constructor:
  public BlankFinal() {
    j = 1; // Initialize blank final
    p = new Poppet(1); // Initialize blank final reference
  }
  public BlankFinal(int x) {
    j = x; // Initialize blank final
    p = new Poppet(x); // Initialize blank final reference
  }
  public static void main(String[] args) {
    BlankFinal b1=new BlankFinal();
    BlankFinal b2=new BlankFinal(47);
    System.out.println("b1.j="+b1.j+"\t\t b1.p.i="+b1.p.getI());
    System.out.println("b2.j="+b2.j+"\t\t b2.p.i="+b2.p.getI());
  }
  /**
   * 輸出結果:
   * b1.j=1     b1.p.i=1
   * b2.j=47     b2.p.i=47
   */
}

final參數

java中也許將參數列表中的參數以聲明的方式聲指明為final。這意味著你無發改變參數所指向的對象。例如:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package finalPackage;
class Gizmo {
  public void spin(String temp) {
    System.out.println(temp+" Method call Gizmo.spin()");
  }
}
/**
 * final參數
 * @author Administrator
 * 如果將參數列表中的參數指明為final,這意味著你無發改變參數所指向的對象的引用。
 */
public class FinalArguments {
  void with(final Gizmo g) {
    // ! g = new Gizmo(); // Illegal -- g is final
  }
  void without(Gizmo g) {
    g = new Gizmo(); // OK -- g not final
    g.spin("without");
  }
  // void f(final int i) { i++; } // Can't change
  // You can only read from a final primitive:
  int g(final int i) {
    return i + 1;
  }
  public static void main(String[] args) {
    FinalArguments bf = new FinalArguments();
    bf.without(null);
    bf.with(null);
    System.out.println("bf.g(10)="+bf.g(10));
  }
  /**
   * 輸出結果:
   * withoutMethod call Gizmo.spin()
   * bf.g(10)=11
   */
}

使用final方法有兩個原因。第一個原因是把方法鎖定,以防止任何繼承它的類修改它的含義。這是出于設計的考慮:想要確保在繼承中使用的方法保持不變,并且不會被覆蓋。

過去建議使用final方法的第二個原因是效率。在java的早期實現中,如果將一個方法指明為final,就是同意編譯器將針對該方法的所有調用都轉為內嵌調用。當編譯器發現一個final方法調用命令時,它會根據自己的謹慎判斷,跳過插入程序代碼這種正常的調用方式而執行方法調用機制(將參數壓入棧,跳至方法代碼處執行,然后跳回并清理棧中的參數,處理返回值),并且以方法體中的實際代碼的副本來代替方法調用。這將消除方法調用的開銷。當然,如果一個方法很大,你的程序代碼會膨脹,因而可能看不到內嵌所帶來的性能上的提高,因為所帶來的性能會花費于方法內的時間量而被縮減。

在最近的java版本中,虛擬機(特別是hotspot技術)可以探測到這些情況,并優化去掉這些效率反而降低的額外的內嵌調用,因此不再需要使用final方法來進行優化了。事實上,這種做法正逐漸受到勸阻。在使用java se5/6時,應該讓編譯器和JVM去處理效率問題,只有在想明確禁止覆蓋式,才將方法設置為final的。

final和private關鍵字

類中的所有private方法都是隱式的制定為final的。由于你無法訪問private方法你也就無法覆蓋它。可以對private方法添加final修飾詞,但這毫無意義。例如:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
package finalPackage;
/**
 * final和private關鍵字
 *
 * 類中的所有private方法都是隱式的制定為final的。
 * 由于你無法訪問private方法,所以你也就無法覆蓋它。
 * 可以對private方法添加final修飾詞,但這毫無意義。
 */
class WithFinals {
  // Identical to "private" alone:
  private final void f() {
    System.out.println("WithFinals.f()");
  }
  // Also automatically "final":
  private void g() {
    System.out.println("WithFinals.g()");
  }
}
class OverridingPrivate extends WithFinals {
  private final void f() {
    System.out.println("OverridingPrivate.f()");
  }
  private void g() {
    System.out.println("OverridingPrivate.g()");
  }
}
class OverridingPrivate2 extends OverridingPrivate {
  public final void f() {
    System.out.println("OverridingPrivate2.f()");
  }
  public void g() {
    System.out.println("OverridingPrivate2.g()");
  }
}
public class OverideFinal {
  public static void main(String[] args) {
    WithFinals w1 = new WithFinals();
    // ! w1.f(); //Error,無法訪問私有方法
    // ! w1.g(); //Error,無法訪問私有方法
    OverridingPrivate w2 = new OverridingPrivate();
    // ! w2.f(); //Error,無法訪問私有方法
    // ! w2.g(); //Error,無法訪問私有方法
    OverridingPrivate2 w3 = new OverridingPrivate2();
    w3.f();
    w3.g();
  }
  /**
   * 輸出結果:
   * OverridingPrivate2.f()
   * OverridingPrivate2.g()
   */
}

"覆蓋"只有在某方法是基類接口的一部分時才會發生。即,必須將一個對象向上轉型為它的基類并調用相同的方法。如果某方法是private的,它就不是基類接口的一部分。它僅是一些隱藏于類中的程序代碼,如果一個基類中存在某個private方法,在派生類中以相同的名稱創建一個public,protected或包訪問權限方法的話,該方法只不過是與基類中的方法有相同的名稱而已,并沒有覆蓋基類方法。由于private方法無法觸及而且能有效隱藏,所以除了把它看成是因為它所歸屬的類的組織結構的原因而存在外,其他任何事物都不需要考慮它。

final 類

當將類定義為final時,就表明了你不打算繼承該類,而且也不許別人這樣做。換句話說,出于某種考慮,你對該類的設計永不需要做任何變動,或者出于安全的考慮,你不希望他有子類。例如:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package finalPackage;
class SmallBrain {
}
final class Dinosaur {
  int i = 7;
  int j = 1;
  SmallBrain x = new SmallBrain();
  void f() {
    System.out.println("Dinosaur.f()");
  }
}
// ! class Further extends Dinosaur {}
// error: Cannot extend final class 'Dinosaur'
/**
 * final 類
 *
 * final類中的屬性可以選擇是否定義為final
 * final類中的方法都隱式的制定為final方法,因此你無法覆蓋他們
 */
public class Jurassic {
  public static void main(String[] args) {
    Dinosaur n = new Dinosaur();
    n.f();
    n.i = 40;
    n.j++;
    System.out.println("n.i="+n.i);
    System.out.println("n.j="+n.j);
  }
  /**
   * 輸出結果為:
   * Dinosaur.f()
   * n.i=40
   * n.j=2
   */
}

請注意,final類的域可以根據個人的意愿選擇是或不是final。不論類是否被定義為final,相同的規則同樣適用于定義為final的域。然而,由于final是無法繼承的,所以被final修飾的類中的方法都隱式的制定為fianl,因為你無法覆蓋他們。在fianl類中可以給方法添加final,但這不會產生任何意義。

結論:

根據程序上下文環境,Java關鍵字final有“這是無法改變的”或者“終態的”含義,它可以修飾非抽象類、非抽象類成員方法和變量。你可能出于兩種理解而需要阻止改變:設計或效率。
final類不能被繼承,沒有子類,final類中的方法默認是final的。
final方法不能被子類的方法覆蓋,但可以被繼承。
final成員變量表示常量,只能被賦值一次,賦值后值不再改變。
final不能用于修飾構造方法。

注意:父類的private成員方法是不能被子類方法覆蓋的,因此private類型的方法默認是final類型的。

希望本文所述對大家Java程序設計有所幫助。

延伸 · 閱讀

精彩推薦
  • JAVA教程Java中的靜態綁定和動態綁定詳細介紹

    Java中的靜態綁定和動態綁定詳細介紹

    這篇文章主要介紹了Java中的靜態綁定和動態綁定詳細介紹,在Java中存在兩種綁定方式,一種為靜態綁定,又稱作早期綁定,另一種就是動態綁定,亦稱為后期綁定...

    junie4922019-12-08
  • JAVA教程Java中三種簡單注解介紹和代碼實例

    Java中三種簡單注解介紹和代碼實例

    這篇文章主要介紹了Java中三種簡單注解介紹和代碼實例,本文講解了Override注解、Deprecated注解、Suppresswarnings注解、元注解等內容,需要的朋友可以參考下 ...

    renfufei1452019-11-28
  • JAVA教程史上最全的java隨機數生成算法分享

    史上最全的java隨機數生成算法分享

    這篇文章主要介紹了史上最全的java隨機數生成算法,我分享一個最全的隨機數的生成算法,最代碼的找回密碼的隨機數就是用的這個方法 ...

    java教程網3492019-11-01
  • JAVA教程java實現的正則工具類

    java實現的正則工具類

    這篇文章主要介紹了java實現的正則工具類,可用于針對電話號碼、郵箱、QQ號碼、QQ密碼、手機號的正則驗證功能,具有一定參考借鑒價值,需要的朋友可以參...

    張庚1512020-01-09
  • JAVA教程Java的Struts框架中的if/else標簽使用詳解

    Java的Struts框架中的if/else標簽使用詳解

    這篇文章主要介紹了Java的Struts框架中的if/else標簽使用詳解,Struts是Java的SSH三大web開發框架之一,需要的朋友可以參考下 ...

    goldensun4132020-03-07
  • JAVA教程java編程實現郵件定時發送的方法

    java編程實現郵件定時發送的方法

    這篇文章主要介紹了java編程實現郵件定時發送的方法,涉及Java基于定時器實現計劃任務的相關技巧,具有一定參考借鑒價值,需要的朋友可以參考下 ...

    awj35841532020-01-15
  • JAVA教程Android入門簡單實例

    Android入門簡單實例

    這篇文章主要介紹了Android入門簡單實例,對于初學Android的朋友有一定的借鑒價值,需要的朋友可以參考下 ...

    shichen20142732019-11-26
  • JAVA教程簡單總結Java的反射機制的運用

    簡單總結Java的反射機制的運用

    這篇文章主要介紹了Java的反射機制的運用,對一些常用的類作了一些說明,需要的朋友可以參考下 ...

    turkeyzhou3612020-03-02
主站蜘蛛池模板: 自拍小电影 | 国产精品久久嫩一区二区免费 | www久久久| 欧美国产激情二区三区 | 北条麻妃一区二区三区中文字幕 | 国产欧美在线观看 | 亚洲欧美视频 | 国产视频久久 | 亚洲成人激情在线观看 | 久草视频网站 | 日本99精品 | 免费看的av | 亚洲国产精品久久久久 | 国产精品美乳在线观看 | 国产精品久久久久久中文字 | 精品国产99| 性视屏 | 国产精品久久久久久吹潮 | 精品一区二区三区在线观看 | 日韩中文字幕在线播放 | 一级爱 | 中文字幕一区二区三区在线观看 | 精品视频一区二区三区四区 | 欧美日韩精品一区二区三区蜜桃 | 精品亚洲永久免费精品 | 成人午夜毛片 | 久久影音 | 成人av专区 | 亚洲精品系列 | 91视频.com | 国产中文字幕在线播放 | 欧美三区 | 看亚洲a级一级毛片 | 在线视频 中文字幕 | 啵啵影院午夜男人免费视频 | 91在线网站 | 国产大学生一区 | 久久久久国产一区二区三区四区 | 精品成人久久 | 日韩中文字幕av | 国产精品美女久久久网av |