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

【Java每日一題】20170111:final 修飾引用變量的陷阱,你踩中了嗎?

     編輯:Java 綜合教學

【Java每日一題】20170111:final 修飾引用變量的陷阱,你踩中了嗎?

今天我們來分析一道經典的 Java 基礎題目,考察點直擊 final 關鍵字修飾引用類型變量的核心語義。很多初學者(甚至有經驗的開發者)容易混淆「引用不可變」與「對象內容不可變」的區別。

題目代碼

package Jan2017;
public class Ques0111 {
    public static void main(String[] args){
        final Person p1 = new Person("張三");
        final Person p2 = new Person("李四");
        p1 = new Person("王五");        // 第 1 行
        p2.setName("王五");             // 第 2 行
    }
}
class Person {
    private String name;
    Person(String name) { this.name = name; }
    public void setName(String name) { this.name = name; }
}

問題

請問主程序有無編譯錯誤?若有,錯在哪一行?

答案與解析

答案:有編譯錯誤,錯在第 1 行:`p1 = new Person("王五");`

詳細解析

  1. final 修飾基本類型:值不可變(如 `final int a = 1; a = 2;` 編譯報錯)。
  2. final 修飾引用類型:引用(地址值)不可變,但指向的對象內容(屬性值)可以改變。
    • `final Person p1 = new Person("張三");` → `p1` 存儲對象地址,被 `final` 鎖死,不能再指向別的對象。
    • 第 1 行 `p1 = new Person("王五");` 試圖讓 `p1` 指向新對象 → 編譯錯誤:cannot assign a value to final variable p1。
    • 第 2 行 `p2.setName("王五");` 僅修改 `p2` 指向對象內部的 `name` 屬性 → 完全合法,對象內容可變。

記憶口訣

final 鎖的是「門牌號」,不是「屋裡的人」。
引用變量是門牌號,對象是房子。final 禁止換門牌號,但允許裝修房子(修改屬性)。

延伸思考:如何讓對象真正不可變?

若需 `Person` 對象不可變,需滿足:

  • 類聲明 `final`(防止繼承破壞)
  • 所有屬性 `private final`
  • 無 `setter` 方法
  • 構造器中完成初始化,不提供修改入口
  • 若屬性為可變對象(如 `Date`、`List`),getter 返回防禦性拷貝

這就是《Effective Java》中提倡的不可變對象設計模式,線程安全、簡單可靠。

往期回顧與關注

20170110 題目解析請點擊文末鏈接或關注微信公眾號「weknow619」查看。weknow 團隊已開通分答,歡迎來咨詢交流!

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