Java :: final/Object/instanceof - OpenHome.cc

文章推薦指數: 80 %
投票人數:10人

在Java SE API 會宣告為 final 的類別或方法,通常與JVM 物件或作業系統資源管理有密切相關,因此不希望API 使用者繼承或重新定義。

java.lang.Object. 在 ... OPENHOME.CC Java |Java平台概論 Java版本遷移 JDK規範與實作 JVM、JRE與JDK |路徑/套件/模組 Hello,Java JDK/JRE/類別版本 類別/原始碼路徑 package與import 初探模組 |語法基礎 型態 變數 運算子 型態轉換 if/else、switch for、while迴圈 |類別與物件 定義類別 使用Scanner、BigDecimal 基本型態包裹器 陣列 字串 Java與Unicode |封裝 流程與資料的封裝 public/建構式/重載 this與static 不定長度引數/內部類別 資料載體與record |繼承 共同行為與isa 重新定義/abstract protected/super final/Object/instanceof sealed類別 |介面 定義行為外觀 解決需求變化 介面語法細節 使用enum列舉 sealed介面 |例外 try/catch例外處理 要抓還是要拋? 堆疊追蹤與assert finally資源關閉 |泛型 定義與使用泛型 Producerextends Consumersuper |Lambda 初試Lambda Lambda運算式與函式介面 this與final 方法與建構式參考 GitHub Twitter Facebook LinkedIn 2DDesigns 3DDesigns Tags BuiltwithbyHugo HOME> Java> 繼承> final/Object/instanceof final與類別定義 java.lang.Object 重新定義toString 重新定義equals instanceof模式比對 inheritance objectoriented patternmatching final/Object/instanceof June6,2022 如果在指定變數值之後,就不想再改變變數值,可以在宣告變數時加上final限定,如果後續撰寫程式時,自己或別人不經意想修改final變數,就會出現編譯錯誤。

final與類別定義 如果物件資料成員被宣告為final,但沒有明確使用=指定值,那表示延遲物件成員值的指定,在建構式執行流程中,一定要有對該資料成員指定值的動作,否則編譯錯誤。

class前也可以加上final關鍵字,如果class前使用了final關鍵字定義,那麼表示這個類別是最後一個了,不會再有子類別,也就是不能被繼承。

有沒有實際的例子呢?有的!String在定義時就限定為final了。

定義方法時,也可以限定該方法為final,這表示最後一次定義方法了,也就是子類別不可以重新定義final方法。

有沒有實際的例子呢?有的!java.lang.Object就有幾個final方法,例如notify、notifyAll,如果嘗試在繼承父類別後,重新定義final方法,會發生編譯錯誤。

在JavaSEAPI會宣告為final的類別或方法,通常與JVM物件或作業系統資源管理有密切相關,因此不希望API使用者繼承或重新定義。

java.lang.Object 在Java中,子類別只能繼承一個父類別,如果定義類別時沒有使用extends關鍵字指定繼承任何類別,那一定是繼承java.lang.Object,也就是說,如果你如下定義類別: publicclassSome{ ... } 那就相當於如下撰寫: publicclassSomeextendsObject{ ... } 因此在Java,任何類別追溯至最上層父類別,一定就是java.lang.Object,也就是所有物件,都「是一種」Object,如下撰寫程式是合法的: Objecto1="Justin"; Objecto2=newDate(); String是一種Object,Date是一種Object,任何型態的物件,都可以使用Object宣告的名稱來參考。

這有什麼好處?如果有個需求是使用陣列收集各種物件,那該宣告為什麼型態呢?答案是Object[]。

例如: Object[]objs={"Monica",newDate(),newSwordsMan()}; varname=(String)objs[0]; vardate=(Date)objs[1]; varswordsMan=(SwordsMan)objs[2]; 因為陣列長度有限,使用陣列來收集物件不是那麼地方便,以下定義的ArrayList類別,則可以不限長度地收集物件: packagecc.openhome; importjava.util.Arrays; publicclassArrayList{ privateObject[]list; privateintnext; publicArrayList(intcapacity){ list=newObject[capacity]; } publicArrayList(){ this(16); } publicvoidadd(Objecto){ if(next==list.length){ list=Arrays.copyOf(list,list.length*2); } list[next++]=o; } publicObjectget(intindex){ returnlist[index]; } publicintsize(){ returnnext; } } 自定義的ArrayList類別,內部使用Object陣列來收集物件,每一次收集的物件會放在next指定的索引處,在建構ArrayList實例時,可以指定內部陣列初始容量,如果使用無參數建構式,則預設容量為16。

如果要收集物件,可透過add方法,參數型態為Object,可以接收任何物件,如果內部陣列原長度不夠,就使用Arrays.copyOf方法自動建立原長度兩倍的陣列並複製元素,如果想取得收集之物件,可以使用get指定索引取得,如果想知道已收集的物件個數,則透過size方法得知。

以下使用自定義的ArrayList類別,可收集訪客名稱,並將名單轉為大寫後顯示: packagecc.openhome; importjava.util.Scanner; importstaticjava.lang.System.out; publicclassGuest{ publicstaticvoidmain(String[]args){ varnames=newArrayList(); collectNameTo(names); out.println("訪客名單:"); printUpperCase(names); } staticvoidcollectNameTo(ArrayListnames){ varscanner=newScanner(System.in); while(true){ out.print("訪客名稱:"); varname=scanner.nextLine(); if(name.equals("quit")){ break; } names.add(name); } } staticvoidprintUpperCase(ArrayListnames){ for(vari=0;i



請為這篇文章評分?