1. 程式人生 > >Java核心(類的高階特性- final)

Java核心(類的高階特性- final)

一、final 變數

    final 關鍵字可用於變數宣告,一旦該變數被設定,就不可以在改變該變數的值。通常,由 final 定義的變數為常量。例如,在類中定義 PI 值,可以使用如下語句:

final double PI = 3.14;

    當在程式中使用到 PI 這個常量時,它的值就是3.14,如果在程式中再次對定義為 final 的常量賦值,編譯器將不會接受。

    final 關鍵字定義的變數必須在宣告時對其進行賦值操作。 final 除了可以修飾基本資料型別的常量,還可以修飾物件引用。由於陣列也可以被看做一個物件來引用,所以 final 可以修飾陣列。一旦一個物件引用被修飾為 final 後,它只能恆定指向一個物件,無法將其改變以指向另一個物件。一個既是 static 又是 final 的欄位只佔據一段不能改變的儲存空間。

    eg : 在專案的 com.ljs 包中建立 FinalData 類,在該類中建立 Test 內部類,並定義各種型別的 final 變數。

package com.ljs;
import java.util.Random;
class Test{
    int i =0;
}
public class FinalData{
    static Random random=new Random();
    private final int VALUE_1 = 9;        //宣告一個 final 常量
    private static int VALUE_2 = 10;        //宣告一個 final 、 static 常量
    private Test test = new Test();        //宣告一個 final 引用
    private Test test2 = new Test();        //宣告一個不是 final 的引用
    private final int[] a = {1,2,3,4,5,6};        //宣告一個定義 final 的陣列
    private int i4 = random.nextInt(20);
    private static final int i5 = random.nextInt(20);
    public String toString() {
        return i4 + "" + i5 + "";
    }
    public static void main(String[] args) {
        FinalData data = new FinalData();
        data.test = new Test();
        //可以對指定為 final 的引用中的成員變數賦值
        //但不能將定義為 final 的引用指向其他引用
        data.VALUE_2++;
        //不能改變定義為 final 的常量值
        data.test2 = new Test();
        for(int i = 0;i < data.a.length;i++) {
            data.a[i] = 9;
        }
        System.out.println("data:" + data);
        System.out.println("data2");
        System.out.println("new FinalData():" + new FinalData());
        System.out.println("data:" + data);
    }
}

    執行結果:

data:117
data2
new FinalData():67
data:117

    被定義為 final 的常量定義時需要使用大寫字母命名,並且中間使用下劃線進行連線,這是 Java 中歐冠的編碼規則。同時,定義為 final 的資料無論是常量。物件引用還是陣列,在主函式中都不可以改變。

    一個被定義為 final 的對應一塊能用只能指向唯一一個物件,不可以將它再指向其他物件,但是一個物件本身的值卻是可以改變的,那麼為了使一個常量真正做到不可更改,可以將常量宣告為 static final 。

    eg : 在專案的 com.ljs 包中建立 FinalStaitcData 類,在該類中建立 Random 類的物件,在主方法中分別輸出類中定義的 final 變數 a1 與 a2 。

package com.ljs;
import java.util.Random;
public class FinalStaticData{
    private static Random random=new Random();        //例項化一個 Random 類物件
    //隨機產生 0~10 之間的隨機數賦予定義為 final 的 a1
    private final int a1 = random.nextInt(10);
    //隨機產生 0~10 之間的隨機數賦予定義為 static final 的 a2
    private static final int a2 = random.nextInt(10);
    public static void main(String[] args) {
        FinalStaticData data = new FinalStaticData();        //例項化一個物件
        //呼叫定義為 final 的 a1
        System.out.println("重新例項化物件呼叫 a1 的值:" + data.a1);
        //呼叫定義為 static final 的 a2
        System.out.println("重新例項化物件呼叫 a2 的值:" + data.a2);
        //例項化另一個物件
        FinalStaticData data2 = new FinalStaticData();
        System.out.println("重新例項化物件呼叫 a1 的值:" + data.a1);
        System.out.println("重新例項化物件呼叫 a2 的值:"  +data.a2);
    }
}

    執行結果為:

重新例項化物件呼叫 a1 的值:9
重新例項化物件呼叫 a2 的值:5
重新例項化物件呼叫 a1 的值:9
重新例項化物件呼叫 a2 的值:5

    定義為 final 的常量不是恆定不變的,將隨機數賦予定義為 final 的常量,可以做到每次執行程式時改變 a1 的值。但是 a2 與 a1 不同,由於它被宣告為 static final 形式,所以在記憶體中為 a2 開闢了一個恆定不變的區域,當再次例項化一個 FinalStaticData 物件時,仍然指向 a2 這塊記憶體區域,所以 a2 的值保持不變。a2 是在裝載時被初始化,而不是每次建立新物件時都被初始化;而 a1 會在重寫例項化物件時被更改。

    在 Java 中定義全域性變數,通常使用 public static final 修飾,這樣的常量只能在定義時被賦值。

    可以將方法的引數定義為 final 型別,這預示著無法在方法中更改引數引用所指向的物件。

二、final 方法

    將方法定義為 final 型別可以防止子類修改該類的定義與實現方式,同時定義為 final 的方法的執行效率要高於非 final 方法。在修飾許可權中提到的 private 修飾符,如果一個父類的某個方法被設定為 private 修飾符,子類將無法訪問該方法,自然無法覆蓋該方法,所以一個定義為 private 的方法隱式被指定為 final 型別,這樣無須將一個定義為 private 的方法再定義為 final 型別。

privale final void test{
    ...//省略一些程式程式碼
}

    eg : 在專案中建立 FinalMethod 類,在該類中建立 Parents 類和繼承該類的 Sub 類,在方法中分別呼叫這兩個類中的方法,並檢視 final 型別方法能否被覆蓋。

package com.ljs;

class Parents{
    private final void doit() {
        System.out.println("父類 .doit()");
    }
    final void doit2() {
        System.out.println("父類 .doit2()");
    }
    public void doit3() {
        System.out.println("父類 .doit3()");
    }
}
class Sub extends Parents{
    public final void doit() {        //在子類定義一個 doit() 方法
        System.out.println("子類 .doit()");
    }
    // final 方法不能覆蓋
    //final void doit2() {
        //System.out.println("子類 .doit2()");
    //}
    public void doit3() {
        System.out.println("子類 .doit3()");
    }
}
public class FinalMethod {
    public static void main(String[] args) {
        Sub sub = new Sub();        //例項化
        sub.doit();        //呼叫 doit() 方法
        Parents parents = sub;        //執行向上轉型操作
        //不能呼叫 private 方法
        //parents.doit();
        parents.doit2();
        parents.doit3();
    }
}

    執行結果為 :

子類 .doit()
父類 .doit2()
子類 .doit3()

    final 方法不能被覆蓋,例如, doit2() 方法不能再子類中二筆重寫,但是在父類中定義了一個 private final 的 doit() 方法,同時在子類中也定義了一個 doit() 方法,從表面上看,子類中的 doit() 方法覆蓋了父類的 doit() 方法,三十覆蓋必須滿足一個物件向上轉型為它的基本型別並呼叫相同方法這樣一個條件。例如,在主方法中 "  Parents p = s ; " 語句執行向上轉型操作,物件 p 值能呼叫正常覆蓋的 doit3()  方法,卻不能呼叫 doit() 方法,可見子類中的 doit() 方法並不是正常覆蓋,而是生成一個新的方法。

三、 final 類

    定義為 final 的類不能被繼承。

    如果希望一個類不允許任何類繼承,並且不允許其他人對這個類進行任何改動,可以將這個類設定為 final 形式。

    final 類的語法

final 類名{  }

    如果將某個類設定為 final 形式,則類中的所有方法都被隱式設定為 final 形式,但是 final 類中的成員變數可以被定義為 final 或非 final 形式。

    eg : 在專案中建立 FinalClass 類,在類中定義 doit() 方法和變數 a ,實現在主方法中操作變數 a 自增。

package com.ljs;

final class FinalClass {
    int a = 3;
    void doit() {
		
    }
    public static void main(String[] args) {
        FinalClass fClass = new FinalClass();
        fClass.a++;
        System.out.println("a:" + fClass.a);
    }
}

    執行結果為:

a:4

相關推薦

Java核心(高階特性- final)

一、final 變數    final 關鍵字可用於變數宣告,一旦該變數被設定,就不可以在改變該變數的值。通常,由 final 定義的變數為常量。例如,在類中定義 PI 值,可以使用如下語句:final double PI = 3.14;    當在程式中使用到 PI 這個常

Java核心庫-IO-文件過濾器(FilenameFilter)

return 文件過濾 system sof boolean style 接口 strong family 文件操作過濾器(FilenameFilter): listFiles(FilenameFilter filter )方法 : 實際就相當於: //文件過濾器(Fil

Java核心庫-IO-字符解碼和編碼操作

編碼 亂碼 .cn 字符 字符串 tro com str 數組 編碼:把字符串轉換為byte數組。 解碼:把byte數組轉換為字符串。 一定要保證編碼和解碼的字符集相同,否則亂碼。 Java核心類庫-IO-字符解碼和編碼操作

Java核心庫-IO-字節數組流/內存流

sta throws demo print char 字符數 lang java 字節數組 內存流(數組流):   把數據先臨時存在數組中,待會再從數組中獲取出來。   1. 字節內存流:ByteArrayInputStream/ByteArrayOutputStream

Java核心庫-IO-對象流(實現序列化與反序列化)

.get throws 反序 code row cts new java cep 使用對象流來完成序列化和反序列化操作:   ObjectOutputStream:通過writeObject()方法做序列化操作的   ObjectInputStream:通過readObje

Java核心庫-IO-打印流(PrintStream/PrintWriter)

int div leo obj clas 打印流 println 不換行 pan 打印流,打印數據的,打印流只能是輸出流: PrintStream:字節打印流。 PrintWriter:字符打印流。 對於PrintWriter來說,當啟用字段刷新之後 PrintWrite

Java核心庫-IO-NIO概述

字符 java 傳統 ont syn 概述 pan spa 數據 NIO:New IO 從JDK1.4開始提出的,新的IO,可以把一塊磁盤文件映射到內存中,我們再去讀取內存中的數據。 存放在java.nio包中 Java NIO(New IO)是Java1.4版本開始引入的

關於java繼承以及final問題總結

祖先 final關鍵字 fin 相同 不能 自己 pri 權限 成員變量 (1)子類和父類如果在同一個包內,則子類可以繼承父類的除private以外的所有成員變量和方法,並且權限不變; (2)子類和父類如果不在同一個包內,則子類可以繼承父類的public和protected

Java程式設計題解與上機指導(第四版)第七章 Java語言的高階特性 7.2藉助泛型定義一個線性表

線性表:由相同型別的物件組成的一個線性結構360百科: 定義 線性表(linear list)是資料結構的一種,一個線性表是n個具有相同特性的資料元素的有限序列。資料元素是一個抽象的符號,其具體含義在不同的情況下一般不同。 在稍複雜的線性表中,一個數據元素可由多個數據項(

JAVA--核心

object 類 ** object類是所有類的父類,任何一個類都繼承了object 類 ** object 類常用方法: toString(); 返回一個字串用於描述該物件。 equals(object obj); 用於比較兩個物件的記憶體地址,判斷是否為同一物件 h

JAVA核心

1,CLASS類——表示執行時類或介面的資訊。   可通過class物件獲取類名,父類等資訊,並可通過class類來獲取該類的屬性,方法,構造方法,包等。   獲取class物件有如下常用方法:   (已知類存在,已知類名) 直接類.class方法,返回該類的型別資訊.

Java物件和例項的關係、Java資料封裝、Java繼承和多型、Java抽象和介面、Java靜態欄位和方法、Java包和作用域、Java的classpath和jar、Java核心

Java物件和例項的關係: 面向物件程式設計(Object-Oriented Programming),是對現實世界建立計算機模型的一種方法。 class是物件的模板,它定義瞭如何建立例項,class的名字就是資料型別。一個class裡可以有多個欄位(field),欄位用

Java 核心庫中的一些設計模式

今天訪問java 併發程式設計網,看到一個翻譯徵集令,併發程式設計網的作者從stackoverflow 網站上選取了一些經典問答,遂決定翻譯幾篇 翻譯系列文章: 3.在java中如何建立一個記憶體洩露 譯文: 在Java 核心類庫中關於GOF設計模式的例子

java核心

原文:https://blog.csdn.net/wang7807564/article/details/79315042  Java核心包及其功能是: java核心類庫概要 包名 主要功能 java.

java筆記4-java核心

目錄   字串和編碼 StringBuilder 包裝型別 JavaBean 列舉類 (Enumeration) 常用工具類 字串和編碼 字串 Java字串的特點: 字串物件可以直接使用"..."表示 內容不可變 使用equal

JAVA面向物件高階特性之繼承(1)常見問題解答

1、什麼是繼承? 答:如果說A是一個B,則我們說A繼承自B。通過繼承來實現程式碼的複用。 2、Java中如何實現繼承?  答:Java類通過extends關鍵字實現繼承,所有的類都間接或者直接繼承自Object類。 3、Java中,有繼承關係時,變數隱藏的原則?  答:子類

Java核心技術 卷II 高階特性 第9版(中文)》電子書附下載連結+30個總結JVM虛擬機器的技術文排版好(收藏版)

技術書閱讀方法論 一.速讀一遍(最好在1~2天內完成) 人的大腦記憶力有限,在一天內快速看完一本書會在大腦裡留下深刻印象,對於之後複習以及總結都會有特別好的作用。 對於每一章的知識,先閱讀標題,弄懂大概講的是什麼主題,再去快速看一遍,不懂也沒有關係,但是一定要在不懂的

Java核心技術(卷二):高階特性 中文第9版 英文第10版 Core Java Volume II【帶目錄高清pdf下載】

放心下載pdf地址:必看理由:Java入門必看暢銷書,核心技術的卷二,經典中的經典,與《Java程式設計思想》並稱為Java入門的“倚天劍”和“屠龍刀”。豆瓣評分:8.5美國亞馬遜評分:4.8網友評論:(豆瓣網友)卷二雖然是高階特性,但是其中的io、檔案系統、正則表示式、網路

Java核心技術之基本數據

又能 art 資料 string 1.4 get bool 讀取 大數 這篇文章。我們討論一些java的最主要的東西。這些東西我們一般剛剛學java的時候就學過,可是不一定真正明確。正好,我在做一個讀取內存的值,涉及到bit位的值的讀取和寫。那就能夠討論一個

Java核心技術】型信息(Class對象 反射 動態代理)

示例 () 分享 不知道 必須 理解 name row 類庫 1 Class對象 理解RTTI在Java中的工作原理,首先需要知道類型信息在運行時是如何表示的,這是由Class對象來完成的,它包含了與類有關的信息。Class對象就是用來創建所有“常規”對象的,Java使用C