class Parent {
static { System.out.println("父類-靜態塊"); }
{ System.out.println("父類-初始化塊"); }
public Parent() { System.out.println("父類-構造函數"); }
}
class Child extends Parent {
static { System.out.println("子類-靜態塊"); }
{ System.out.println("子類-初始化塊"); }
public Child() { System.out.println("子類-構造函數"); }
}
new Child();
父類-靜態塊
子類-靜態塊
父類-初始化塊
父類-構造函數
子類-初始化塊
子類-構造函數
關鍵: 靜態內容類載入時執行(一次),實例內容每 new 執行一次。
String a = "abc";
// 棧:引用變量 a
// 堆:String 物件(含 char[] value)
// 字符串池(方法區/堆):"abc" 常量
String v1 = "ab";
String v2 = "ab"; // true (池中同一物件)
String v3 = new String("ab"); // false (堆中新物件)
String v4 = "abcd";
String v5 = "ab" + "cd"; // true (編譯期常量折疊)
String v6 = v1 + "cd"; // false (運行期 new StringBuilder)
String v7 = CONST + "cd"; // true (CONST 為 compile-time constant)
String v8 = staticVar + "cd"; // false (運行期賦值)
String v9 = v4.intern(); // true (手動入池)
final + 常量表達式)new String() 強制在堆建立新物件,不入池intern() 手動將物件放入池/取得池中引用Java 只有值傳遞。基本型傳值副本,引用型傳引用的副本(指向同一堆物件)。
void change(int v) { v = 10; }
void change(Obj o) { o = new Obj(); o.val = 10; } // 修改局部引用指向
void add(Obj o) { o.val += 10; } // 修改物件內容
int v = 0; change(v); // v 仍為 0
Obj obj = new Obj(); change(obj); // obj.val 仍為 0
add(obj); // obj.val 變為 10
本質: 傳遞的是棧中的內容(基本值或引用位址),JVM 複製一份給方法參數。
| 關鍵字 | 用途 | 關鍵規則 |
|---|---|---|
| final | 修飾類/方法/變量/參數 | 類不可繼承、方法不可重寫、變量只能賦值一次(聲明/初始化塊/構造函數) |
| finally | try-catch-finally | 無論是否異常/return/break/continue 必執行,用於資源釋放 |
| finalize | Object 方法 | GC 回收前調用,不保證執行,Java 9+ 已棄用,改用 Cleaner/PhantomReference |
try { throw new RuntimeException(); }
catch (Exception e) { }
finally { System.out.println("必執行"); } // 輸出
try { return "ok"; }
finally { System.out.println("return 前執行"); } // 輸出
for (int i=0; i<3; i++) {
try { if (i==2) break; }
finally { System.out.println("break 也執行"); } // 每次循環都執行
}
| 類型 | 位數 | 包裝類 | 最小值 | 最大值 |
|---|---|---|---|---|
| byte | 8 | Byte | -128 | 127 |
| short | 16 | Short | -32,768 | 32,767 |
| int | 32 | Integer | -2,147,483,648 | 2,147,483,647 |
| long | 64 | Long | -9.22e18 | 9.22e18 |
| float | 32 | Float | 1.4E-45 | 3.4E38 |
| double | 64 | Double | 4.9E-324 | 1.8E308 |
| char | 16 | Character | 0 | 65,535 |
| boolean | 1~8 | Boolean | false | true |
byte → short → int → long → float → double
char → int
int → float, long → float, long → double
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String str = sdf.format(date);
Date parsed = sdf.parse("2023-05-20");
Calendar c = Calendar.getInstance();
c.get(Calendar.YEAR);
c.get(Calendar.MONTH); // 0-based!
c.get(Calendar.DATE);
c.get(Calendar.HOUR_OF_DAY); // 24小時制
LocalDateTime.now();
LocalDate.of(2023, 5, 20);
DateTimeFormatter.ofPattern("yyyy-MM-dd");
ChronoUnit.DAYS.between(d1, d2);