🔒 25. final vs abstract 關鍵字
關鍵字 | 修飾對象 | 作用 | 規則 |
---|---|---|---|
final | 類 | 禁止被繼承 | final class MyClass { ... } |
方法 | 禁止被子類重寫 | public final void func() | |
變量 | 變為常量(基本類型值不可變,引用類型地址不可變) | final int MAX = 100; | |
abstract | 類 | 必須被繼承 | abstract class Animal { ... } |
方法 | 必須被子類重寫 | abstract void eat(); |
關鍵區別:
final Dog dog = new Dog("歐歐"); dog.name = "美美"; // ? 允許修改對象屬性 dog = new Dog("亞亞"); // ? 禁止修改引用地址
?? 26. final vs finally vs finalize
關鍵字 | 類別 | 作用 | 示例 |
---|---|---|---|
final | 修飾符 | 定義不可變實體(類/方法/變量) | final class Immutable { ... } |
finally | 異常處理塊 | 確保資源釋放(無論是否發生異常) | try { ... } finally { conn.close(); } |
finalize | Object類方法 | GC回收對象前調用的清理方法(已廢棄) | protected void finalize() { /* 清理 */ } |
注意:
- Java 9+ 廢棄
finalize()
,推薦使用Cleaner
或try-with-resources
finally
塊始終執行(除非System.exit()
或 JVM 崩潰)
📦 27. java.lang.Object 的六個核心方法
equals(Object obj)
:對象等價性比較(默認比較地址)hashCode()
:返回對象哈希碼(需與equals
邏輯一致)toString()
:返回對象字符串表示(默認返回類名@地址)getClass()
:獲取對象的運行時類wait()/notify()/notifyAll()
:線程間通信(需在同步塊中使用)clone()
:創建并返回對象副本(需實現Cloneable
接口)
重寫規范:
@Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; User user = (User) o; return Objects.equals(name, user.name); }
🔑 28. 訪問權限修飾符對比
修飾符 | 類內部 | 同包 | 不同包子類 | 全局 |
---|---|---|---|---|
private | ? | ? | ? | ? |
默認 | ? | ? | ? | ? |
protected | ? | ? | ? | ? |
public | ? | ? | ? | ? |
類修飾規則:
- 外部類僅支持
public
或默認
- 內部類可使用所有修飾符
🏗? 29. 繼承中的構造方法執行順序
- 子類構造隱式調用
super()
:class Parent { Parent() { System.out.println("Parent構造"); } } class Child extends Parent { Child() { // 隱含 super(); System.out.println("Child構造"); } } // 輸出:Parent構造 → Child構造
- 顯式調用父類構造:
Child(int age) { super(age); // 必須位于首行 System.out.println("Child帶參構造"); }
- 多級繼承順序:
Object → 爺爺類 → 父類 → 子類
🆚 30. == vs equals()
操作符/方法 | 比較內容 | 示例 |
---|---|---|
== | 基本類型:值 | 10 == 10 → true |
引用類型:內存地址 | new String("A") == "A" → false | |
equals() | 默認同 == | |
重寫后按業務邏輯 | "A".equals(new String("A")) → true |
重寫原則:
- 自反性:
x.equals(x) = true
- 對稱性:
x.equals(y) = y.equals(x)
- 傳遞性:
x=y, y=z → x=z
🌀 31. Java多態詳解
三大條件:
- 繼承關系(
extends
或implements
) - 子類重寫父類方法
- 父類引用指向子類對象:
Animal dog = new Dog()
轉型示例:
// 向上轉型(自動)
Animal animal = new Dog();
animal.eat(); // 調用Dog重寫的eat() // 向下轉型(需顯式)
if (animal instanceof Dog) { Dog dog = (Dog) animal; dog.bark();
}
優勢:代碼擴展性強(新增子類不影響父類邏輯)
🗑? 32. 垃圾回收機制(GC)
核心特性:
- 自動管理:JRE 后臺回收無用對象(
java.lang.Object
未覆蓋時) - 回收區域:僅堆內存(不包含棧、方法區)
- 不可預測性:無法精確控制 GC 執行時機
觸發時機:
- Eden 區滿觸發 Minor GC
- 老年代滿觸發 Full GC
- 手動建議:
System.gc()
(不保證立即執行)
對象復活:
protected void finalize() { this.reference = this; // ? 已廢棄,禁止使用
}
📦 33. 基本類型與包裝類
基本類型 | 包裝類 | 自動裝箱/拆箱 |
---|---|---|
byte | Byte | Integer i = 10; → 裝箱 |
int | Integer | int n = i; → 拆箱 |
double | Double | Double d = 3.14; |
轉換場景:
- 集合存儲:
List<Integer> list = Arrays.asList(1, 2, 3);
- 類型轉換:
int age = Integer.parseInt("25");
- 空值處理:
Integer score = null;
(基本類型不支持null
)
🆚 34. Integer vs int
維度 | int | Integer |
---|---|---|
類型 | 基本類型 | 包裝類 |
默認值 | 0 | null |
內存占用 | 棧存儲(4字節) | 堆存儲(對象頭+引用) |
比較 | == 比值 | == 比地址,equals 比值 |
緩存優化 | 無 | -128~127 緩存(IntegerCache ) |
陷阱:
Integer a = 100, b = 100; a == b; // true(緩存范圍內) Integer c = 200, d = 200; c == d; // false(超出緩存)
📅 35. java.util.Date vs java.sql.Date
類 | 所屬包 | 用途 | 精度 |
---|---|---|---|
java.util.Date | java.util | 通用日期時間 | 毫秒級 |
java.sql.Date | java.sql | 數據庫日期(不含時間) | 到日(時間置零) |
轉換示例:
// util.Date → sql.Date
java.util.Date utilDate = new java.util.Date();
java.sql.Date sqlDate = new java.sql.Date(utilDate.getTime()); // sql.Date → util.Date(自動向上轉型)
java.util.Date date = sqlDate;
📂 36. 遞歸遍歷目錄文件
void listFiles(File dir) { File[] files = dir.listFiles(); if (files == null) return; for (File file : files) { if (file.isFile()) { System.out.println("文件: " + file.getPath()); } else { System.out.println("目錄: " + file.getPath()); listFiles(file); // 遞歸遍歷子目錄 } }
}
// 調用: listFiles(new File("D:/Project"));
優化:使用
Files.walk()
(Java 8 NIO)替代遞歸
37. Java編譯輸出結果
題目:關于Java編譯,下面哪一個正確?
A. Java程序經編譯后產生machine code
B. Java程序經編譯后會生產byte code
C. Java程序經編譯后會產生DLL
D. 以上都不正確
答案:B
解析:
- Java是解釋型語言,編譯生成字節碼(byte code)(.class文件)而非機器碼。
- DLL是C/C++編譯的動態鏈接庫,與Java無關。
38. 構造方法(Constructor)規則
題目:下列說法正確的有?
A. class中的construtor不可省略
B. construtor與class同名,但方法不能與class同名
C. construtor在一個對象被new時執行
D. 一個class只能定義一個construtor
答案:C
解析:
- A:類可省略構造方法(系統默認提供無參構造)。
- B:方法名可與類名相同(不推薦,違反規范)。
- D:類可定義多個構造方法(重載)。
- C正確:
new
創建對象時自動執行匹配的構造方法。
39. 接口修飾符
題目:Java中接口的修飾符可以為?
A. private
B. protected
C. final
D. abstract
答案:D
解析:
- 接口默認為
abstract
(可顯式聲明,通常省略)。 - 禁止使用
private
/protected
(僅支持public
或默認包訪問)。 final
會阻止接口被實現,違反接口設計目的。
40. 繼承中的構造方法執行順序
題目:以下代碼輸出什么?
class A { public A() { System.out.println("A"); }
}
class B extends A { public B() { System.out.println("B"); } public static void main(String[] args) { B b = new B(); }
}
答案:B(輸出AB)
解析:
- 子類構造方法隱式調用父類無參構造。
- 執行順序:父類構造 → 子類構造。
41. 關鍵字使用錯誤
題目:下列關于關鍵字的使用說法錯誤的是?
A. abstract不能與final并列修飾同一個類
B. abstract類中可以有private成員
C. abstract方法必須在abstract類中
D. static方法能處理非static屬性
答案:D
解析:
- D錯誤:static方法屬于類,無法直接訪問非static成員(需通過對象實例)。
- A:final類禁止繼承,abstract類需被繼承,沖突。
- B/C:抽象類可包含private屬性和抽象方法。
42. 內存回收機制
題目:下列哪些語句關于內存回收的說法正確?
A. 程序員必須創建一個線程來釋放內存
B. 內存回收程序負責釋放無用內存
C. 內存回收程序允許程序員直接釋放內存
D. 內存回收程序可以在指定時間釋放內存
答案:B
解析:
- B正確:GC自動回收無用對象內存。
- A/C/D:程序員無法控制GC執行(僅能建議
System.gc()
)。
43. 合法標識符
題目:選出合理的標識符?
A. _sysl_111
B. 2 mail
C. $change
D. class
答案:A、C
解析:
- 合法規則:
- 可包含字母、數字、
_
、$
- 不能以數字開頭(B錯誤)
- 不能是關鍵字(D錯誤,
class
是關鍵字)
- 可包含字母、數字、
44. 正確說法
題目:下列說法正確的是?
A. java.lang.Cloneable是類
B. java.lang.Runnable是接口
C. Double對象在java.lang包中
D. Double a=1.0是正確的java語句
答案:B、C、D
解析:
- A:
Cloneable
是接口(標記接口)。 - B:
Runnable
是接口(線程相關)。 - C:
Double
包裝類在java.lang
。 - D:自動裝箱(
double→Double
)。
45. 類聲明規則
題目:類名為"MyClass.java"的類可被工程中所有類訪問,正確聲明為?
A. private class MyClass
B. class MyClass extends Object
C. public class MyClass
D. public class MyClass extends Object
答案:C、D
解析:
- 全局訪問需
public
修飾(A/B默認包訪問)。 extends Object
可省略(所有類默認繼承Object)。
46. 面向對象特征及生活案例
題目:面向對象的特征有哪些?舉例說明。
答案:
- 封裝
- 隱藏實現細節,暴露接口。
- 例:汽車駕駛(無需了解發動機原理,通過方向盤/油門控制)。
- 繼承
- 子類復用父類屬性和方法。
- 例:電商系統——
User
為父類,Customer
/Admin
子類繼承基礎屬性。
- 多態
- 同一接口不同實現。
- 例:支付系統——
Payment
接口,Alipay
/WeChatPay
實現不同支付邏輯。
47. 內存泄漏 vs 內存溢出
題目:說明內存泄漏和內存溢出的區別及解決方案。
答案:
類型 | 內存泄漏(Memory Leak) | 內存溢出(OOM) |
---|---|---|
定義 | 對象不再使用但未被GC回收 | 內存不足無法分配新對象 |
原因 | 長生命周期對象持有短生命周期對象引用 | 內存泄漏積累或數據量過大 |
檢測工具 | VisualVM、MAT、JProfiler | JVM參數-XX:+HeapDumpOnOutOfMemoryError 生成堆轉儲 |
解決方案 | - 及時解引用(如List.clear() )- 避免靜態集合類濫用 - 使用弱引用( WeakReference ) | - 增加JVM內存 - 優化數據結構 - 分批次處理數據 |
48. Java序列化
題目:什么是Java序列化?如何實現?應用場景?
答案:
- 序列化:將對象狀態轉換為字節流(便于存儲/傳輸)。
- 實現方式:
public class User implements Serializable { private String name; // 無需重寫方法(默認序列化) } // 序列化 try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("user.dat"))) { oos.writeObject(user); }
- 應用場景:
- 分布式系統傳輸對象(RPC框架如Dubbo)。
- 緩存對象到硬盤(Redis持久化)。
- HTTP Session存儲(Tomcat會話保存)。
49. 繞過構造方法創建對象
題目:不通過構造函數也能創建對象嗎?
答案:可以,方式包括:
- 反射:
Class.newInstance()
或Constructor.newInstance()
。 - 克隆:實現
Cloneable
接口,調用clone()
。 - 反序列化:
ObjectInputStream.readObject()
。
注意:克隆和反序列化不會調用構造方法。
50. 匿名內部類的繼承與實現
題目:匿名內部類可不可以繼承或實現接口?
答案:
- 可繼承類:
new Thread() { @Override public void run() { /* 重寫Thread方法 */ } }.start();
- 可實現接口:
Runnable r = new Runnable() { @Override public void run() { /* 實現Runnable */ } };
限制:
- 匿名內部類不能顯式繼承和實現同時存在(隱式繼承Object)。
- 無法定義構造方法(需通過實例初始化塊
{}
模擬)。