最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java 中的自引用詳解

 更新時間:2025年10月22日 09:23:54   作者:大邳草民  
本文介紹了Java中“自引用”概念,即類中包含指向自身類型的成員變量,常用于鏈表、樹等遞歸結構,自引用依賴于引用類型和JVM內存模型,避免無限遞歸,支持靈活安全的數據結構構建,并由GC自動管理內存,感興趣的朋友跟隨小編一起看看吧

1. 概念定義

自引用(Self-Referential Type) 是指:

在一個類的定義中,類的某個成員變量(或字段)類型就是該類自身。

這種定義使得類可以引用同類型的對象,從而構建出 遞歸數據結構(Recursive Data Structure),如:

  • 鏈表(Linked List)
  • 樹(Tree)
  • 圖(Graph)
  • 組織層級結構(Hierarchy)

? 舉個例子

class Node {
    int data;
    Node next; // 自引用:類型是當前類 Node
    Node(int data) {
        this.data = data;
    }
}

上例中的 Node 類中包含了一個字段 next,它的類型就是 Node 自身,這就是典型的 自引用結構。

2. 為什么可以“引用自己”

Java 的對象變量實際上是一個 引用(reference),而不是對象本身。

在 JVM 中:

  • 對象實體存儲在 堆(Heap) 上;
  • 局部變量和成員變量保存的是 引用(即指向堆中對象的邏輯地址)

因此,當在類中聲明 Node next; 時:

  • 并不會立即創(chuàng)建另一個 Node;
  • 只是聲明了一個可以“指向另一個 Node 對象”的引用變量;
  • 不會導致無限遞歸定義。

這正是自引用能夠成立的根本原因。

?? 注意對比:嵌套對象 vs 引用對象

定義方式是否可行原因
Node next;? 可行聲明了一個引用
Node next = new Node();?? 不可取會無限遞歸調用構造函數
class Node { Node next; }? 正常引用結構
class Node { Node next = new Node(); }? 棧溢出構造時遞歸實例化自身

3. 自引用的典型應用場景

1?? 單向鏈表(Singly Linked List)

class Node {
    int data;
    Node next; // 指向下一個節(jié)點
    Node(int data) {
        this.data = data;
    }
}

構建鏈表:

Node n1 = new Node(10);
Node n2 = new Node(20);
Node n3 = new Node(30);
n1.next = n2;
n2.next = n3;

邏輯結構:

n1 → n2 → n3 → null

2?? 二叉樹節(jié)點(Binary Tree Node)

class TreeNode {
    int value;
    TreeNode left;   // 指向左子節(jié)點
    TreeNode right;  // 指向右子節(jié)點
    TreeNode(int value) {
        this.value = value;
    }
}

樹狀結構自然形成遞歸關系,每個節(jié)點都可能再包含子節(jié)點。

3?? 圖節(jié)點(Graph Node)

import java.util.ArrayList;
import java.util.List;
class GraphNode {
    int val;
    List<GraphNode> neighbors;
    GraphNode(int val) {
        this.val = val;
        this.neighbors = new ArrayList<>();
    }
}

這里的 List<GraphNode> 就是自引用的集合形式,
它允許一個節(jié)點同時連接多個同類節(jié)點,從而構建圖結構。

4. 自引用的編譯原理與內存模型

(1)類加載與符號引用

當 Java 編譯器看到:

class Node {
    Node next;
}

時,它會將 next 的類型解析為符號引用(Symbolic Reference):

LNode;

在類加載階段(Class Loading):

  • JVM 會把符號引用解析為實際的類型引用;
  • 不需要在編譯時就擁有完整的類對象;
  • 因此類可以安全地引用自身。

(2)JVM 內存布局

每個 Java 對象都存放在 堆(Heap) 中,由 JVM 自動分配和回收。

當執(zhí)行:

Node n1 = new Node(10);
Node n2 = new Node(20);
n1.next = n2;

內存布局如下:

[棧區(qū)]                     [堆區(qū)]
+--------+           +--------------------+
| n1 --->|---------->| data=10            |
|        |           | next -> (Node@b32) |
+--------+           +--------------------+
| n2 --->|---------->| data=20            |
|        |           | next -> null       |
+--------+           +--------------------+

說明:

  • n1, n2 是棧變量;
  • 它們的值是指向堆中 Node 對象的引用(reference);
  • next 字段本質上也保存一個引用。

(3)對象頭與引用機制

在 HotSpot JVM 中,每個對象頭包含:

  • Mark Word:存放哈希值、鎖狀態(tài)、GC信息;
  • Class Pointer:指向對象的類元數據;
  • 實例數據:即類中聲明的字段;
  • 填充字節(jié):保證對象大小為 8 字節(jié)對齊。

當對象引用被賦值時(如 n1.next = n2):

  • 實際上只是復制了 n2 的“引用值”;
  • 這是一種輕量級操作(非深拷貝)。

(4)為什么不是內存地址

如果打?。?/p>

System.out.println(n1);

輸出類似:

Node@1b6d3586

這里的 1b6d3586 并不是內存地址,而是:

Integer.toHexString(hashCode());

其中 hashCode() 來源于對象頭(Mark Word)計算結果,與真實內存地址無直接關系。

5. 自引用與遞歸(Recursion)的關系

自引用是一種 數據結構層面的遞歸定義,
而遞歸函數是一種 行為層面的遞歸調用

兩者結合,可以優(yōu)雅地處理鏈表或樹結構。

void printList(Node node) {
    if (node == null) return;
    System.out.print(node.data + " ");
    printList(node.next); // 行為遞歸,利用結構自引用
}

輸出:

10 20 30

6. 自引用的注意事項與常見問題

?? 1. 無限遞歸創(chuàng)建

錯誤寫法:

class Node {
    Node next = new Node(); // 無限創(chuàng)建自身,棧溢出!
}

正確方式:

class Node {
    Node next; // 僅聲明引用,不立即實例化
}

?? 2. 循環(huán)引用導致邏輯死循環(huán)

n1.next = n2;
n2.next = n1; // 環(huán)狀結構

遍歷時若無判斷,會無限循環(huán)。
應通過 visited 集合或快慢指針檢測環(huán)。

?? 3. 打印對象時陷入遞歸

如果重寫 toString() 時遞歸引用:

@Override
public String toString() {
    return "Node[data=" + data + ", next=" + next + "]";
}

若鏈表有環(huán),會導致 StackOverflowError。
解決方式是檢測 next 是否為 null 或限制深度。

7. 底層機制擴展:JVM 引用與 GC 行為

1?? 引用類型分類(JDK 1.2 起)

類型特征是否參與 GC 回收
強引用(Strong Reference)普通引用,如 Node next;不可回收
軟引用(Soft Reference)內存不足時回收可選回收
弱引用(Weak Reference)GC 一旦掃描到即回收一定回收
虛引用(Phantom Reference)用于對象回收跟蹤無法訪問對象

Node next 默認是強引用,
因此只要對象之間互相引用,GC 就不會釋放內存(除非形成不可達狀態(tài))。

2?? 自引用與 GC 的安全性

Java 的 GC 通過 可達性分析(Reachability Analysis) 判斷對象是否存活。
即使存在自引用(如循環(huán)鏈表),只要外部沒有引用鏈指向該結構,它仍會被 GC 安全回收。

示例:

Node a = new Node(1);
Node b = new Node(2);
a.next = b;
b.next = a;  // 形成環(huán)
a = null;
b = null;    // 外部引用斷開

→ 整個環(huán)結構在下一次 GC 時被回收,無內存泄漏。

8. 與 C 語言的對比

特性JavaC
成員定義Node next;struct Node *next;
內存管理自動(GC)手動(malloc/free)
地址訪問不可見(安全)可見(指針運算)
循環(huán)檢測自動安全(GC)程序員負責
調試難度較低較高(需防懸空指針)

9.總結與核心觀點

主題內容
定義類中包含類型為自身的成員變量
機制JVM 通過引用語義避免無限遞歸
常用場景鏈表、樹、圖、層次結構
底層原理棧保存引用,堆存對象,引用指向堆地址
安全性GC 負責清理,防止懸空或泄漏
限制不能在定義時直接創(chuàng)建自身實例

?? 一句話總結

Java 自引用是一種基于引用語義的遞歸結構定義機制。
它通過在類中引用同類對象實現邏輯自連接,構建出復雜的數據結構。
底層由 JVM 的“堆-棧分離模型”和“引用機制”支撐,實現了靈活與安全的統(tǒng)一。

到此這篇關于Java 中的自引用的文章就介紹到這了,更多相關java自引用內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Java等待喚醒機制線程通信原理解析

    Java等待喚醒機制線程通信原理解析

    這篇文章主要介紹了Java等待喚醒機制線程通信原理解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-12-12
  • Java HashMap實現原理分析(一)

    Java HashMap實現原理分析(一)

    這篇文章主要介紹了Java HashMap實現原理的分析,幫助大家更好的理解和使用Java,感興趣的朋友可以了解下
    2020-08-08
  • Java網絡編程基礎用法詳解

    Java網絡編程基礎用法詳解

    網絡編程是指編寫運行在多個設備(計算機)的程序,這些設備都通過網絡連接起來,本文將帶大家詳細了解Java的網絡編程,文中有相關的代碼示例,需要的朋友可以參考下
    2023-05-05
  • IntelliJ IDEA 2017 漢化包及圖文教程

    IntelliJ IDEA 2017 漢化包及圖文教程

    這篇文章主要介紹了IntelliJ IDEA 2017 漢化包及圖文教程,文中給大家提供兩種方法,非常不錯,具有參考借鑒價值,需要的朋友參考下吧
    2018-03-03
  • Spring?Retry?實現樂觀鎖重試實踐記錄

    Spring?Retry?實現樂觀鎖重試實踐記錄

    本文介紹了在秒殺商品SKU表中使用樂觀鎖和MybatisPlus配置樂觀鎖的方法,并分析了測試環(huán)境和生產環(huán)境的隔離級別對樂觀鎖的影響,通過簡單驗證,展示了在可重復讀和讀已提交隔離級別下的不同行為,感興趣的朋友一起看看吧
    2025-03-03
  • Restful傳遞數組參數及注解大全

    Restful傳遞數組參數及注解大全

    這篇文章主要介紹了Restful傳遞數組參數及注解大全的相關資料,需要的朋友可以參考下
    2015-12-12
  • 如何安裝Hadoop并運行WordCount程序

    如何安裝Hadoop并運行WordCount程序

    這篇文章主要介紹了如何安裝Hadoop并運行WordCount程序,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2025-05-05
  • java獲取IP和IP的歸屬地的方法實踐

    java獲取IP和IP的歸屬地的方法實踐

    在Java中獲取IP地址通常指的是獲取本地機器的IP地址或者通過某種方式獲取的遠程IP地址,本文就來詳細的介紹一下,感興趣的可以了解一下
    2024-05-05
  • java 中HashCode重復的可能性

    java 中HashCode重復的可能性

    這篇文章主要介紹了java 中HashCode重復的可能性的相關資料,這里提供實例及測試代碼,需要的朋友可以參考下
    2017-07-07
  • Java超全面梳理內部類的使用

    Java超全面梳理內部類的使用

    說起內部類這個詞,想必很多人都不陌生,但是又會覺得不熟悉。原因是平時編寫代碼時可能用到的場景不多,用得最多的是在有事件監(jiān)聽的情況下,并且即使用到也很少去總結內部類的用法。今天我們就來一探究竟
    2022-04-04

最新評論

双牌县| 抚松县| 古田县| 新巴尔虎右旗| 怀化市| 安宁市| 英山县| 得荣县| 大理市| 平远县| 乐陵市| 西充县| 宁远县| 留坝县| 台北县| 黎平县| 武威市| 巴青县| 洛浦县| 平顺县| 大同市| 山东| 昌黎县| 右玉县| 河曲县| 天镇县| 滕州市| 隆林| 昂仁县| 琼海市| 西安市| 浮山县| 射洪县| 晋江市| 贞丰县| 温泉县| 河南省| 罗田县| 长武县| 临夏市| 务川|