首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 運算子與指派深度解析(二)

     編輯:Java 相關知識

目標 2:equals(Object) 方法的行為

判斷 java.lang.String、java.lang.Boolean 與 java.lang.Object 任意組合物件呼叫 equals(Object) 方法的結果。

equals 方法執行的是「深層比較」,比較物件所指向的實際值;而 == 運算子執行「淺層比較」,比較的是參考位址(若 Java 有指標的話)。無論 String 物件以何種方式建立,equals 都會進行逐字元比較。

目標 3:邏輯運算子與短路求值

在已知運算元值的運算式中,判斷 &、|、&&、|| 這些運算子會評估哪些運算元,以及整個運算式的結果。

目標 4:參數傳遞對物件與基本型別的影響

釐清將變數傳入方法並在方法內進行指派或其他修改操作時,對物件與基本型別值的影響。

一元數值提升

適用情境:

  • 一元算術運算子 + 和 - 的運算元
  • 一元位元補數運算子 ~ 的運算元
  • 陣列建立時的維度運算式(如 new int[x]),x 必須評估為 int
  • 陣列索引運算式(如 table['a']),索引必須評估為 int
  • 位移運算子的各個運算元

二元數值提升

適用情境:

  • 算術運算子 *、/、%、+、- 的運算元
  • 關係運算子 <、<=、>、>= 的運算元
  • 等值運算子 == 和 != 的數值運算元
  • 位元運算子 &、^、| 的整數運算元

基本型別轉換規則

  1. 三種轉換類型:指派轉換、方法呼叫轉換、算術提升
  2. boolean 不能與任何非布林型別互相轉換
  3. 擴展轉換被接受,窄化轉換被拒絕
  4. byte、short 不能與 char 互相轉換
  5. 算術提升規則:
    • 一元運算子:若運算元為 byte、short、char,轉為 int;否則不轉換
    • 二元運算子:若有 double 則全部轉 double;否則有 float 轉 float;否則有 long 轉 long;否則全部轉 int
  6. 指派字面常值時,編譯器檢查數值是否在目標型別範圍內
  7. final 變數指派時,若值可在編譯期確定且在範圍內,允許隱性窄化轉換
  8. 方法呼叫轉換只找精確匹配或更寬的型別,不會自動窄化
  9. 允許的基本型別轉換路徑:
    byte → short → int → long → float → double
    char 獨立分支

基本型別強制轉型

  1. 窄化轉換必須強制轉型,資料損失風險大;擴展轉換也可加上強制轉型以提高可讀性
  2. 任何非布林型別可互相強制轉型
  3. 不能將 boolean 轉型為其他型別,或反之

物件參考轉換

  1. 三種參考型別:類別、介面、陣列
  2. 兩種物件建立方式:類別實例、陣列
  3. 兩種轉換:指派轉換、方法呼叫轉換
  4. 只允許「向上」轉換(子型別→父型別),向下需強制轉型
  5. 介面可作為變數型別宣告,參與參考轉換,但不可實例化
  6. 基本型別陣列只能轉換為相同型別的陣列;物件參考陣列可轉換/強制轉型
  7. 基本型別陣列可轉為 Object 參考,但不可轉為 Object[]

物件參考強制轉型規則

編譯期規則:

  • 新舊型別皆為類別時,必須有繼承關係
  • 皆為陣列時,必須為參考型別且元素型別可合法轉換
  • 介面與非 final 類別之間總是可以強制轉型

執行期規則:

  • 新型別為類別:被轉換物件的實際類別必須是新型別或其子類別
  • 新型別為介面:被轉換物件的實際類別必須實作該介面

各型別參考轉換總表

  • Object 參考可轉為:Object、Cloneable(需轉型)、任意類別(需轉型)、任意陣列(需轉型)、任意介面(需轉型)
  • 類別型別參考可轉為:父類別(含 Object)、子類別(需轉型)、實作的介面、任意介面(需轉型,final 且未實作該介面除外)
  • 介面參考可轉為:Object、父介面、任意介面/類別(需轉型,final 且未實作該介面除外)
  • 基本型別陣列可轉為:Object、Cloneable、相同型別陣列
  • 物件陣列可轉為:Object、Cloneable、父類別陣列(含 Object[])、子類別陣列(需轉型)

範例題

class Superclass { }
class Subclass1 extends Superclass { }

Superclass a = new Superclass();
Subclass1 b = new Subclass1();
b = (Subclass1)a;  // 結果為何?

正確答案:b) 編譯合法,但執行期可能拋出 ClassCastException。編譯器允許向下轉型,但執行時 a 實際指向 Superclass 實例,非 Subclass1,故拋出異常。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved