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

Java 中的自引用詳解

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

1. 概念定義

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

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

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

  • 鏈表(Linked List)
  • 樹(Tree)
  • 圖(Graph)
  • 組織層級結(jié)構(gòu)(Hierarchy)

? 舉個例子

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

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

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

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

在 JVM 中:

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

因此,當(dāng)在類中聲明 Node next; 時:

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

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

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

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

3. 自引用的典型應(yīng)用場景

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

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

構(gòu)建鏈表:

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

邏輯結(jié)構(gòu):

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é)構(gòu)自然形成遞歸關(guān)系,每個節(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é)點,從而構(gòu)建圖結(jié)構(gòu)。

4. 自引用的編譯原理與內(nèi)存模型

(1)類加載與符號引用

當(dāng) Java 編譯器看到:

class Node {
    Node next;
}

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

LNode;

在類加載階段(Class Loading):

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

(2)JVM 內(nèi)存布局

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

當(dāng)執(zhí)行:

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

內(nèi)存布局如下:

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

說明:

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

(3)對象頭與引用機(jī)制

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

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

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

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

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

如果打?。?/p>

System.out.println(n1);

輸出類似:

Node@1b6d3586

這里的 1b6d3586 并不是內(nèi)存地址,而是:

Integer.toHexString(hashCode());

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

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

自引用是一種 數(shù)據(jù)結(jié)構(gòu)層面的遞歸定義,
而遞歸函數(shù)是一種 行為層面的遞歸調(diào)用。

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

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

輸出:

10 20 30

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

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

錯誤寫法:

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

正確方式:

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

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

n1.next = n2;
n2.next = n1; // 環(huán)狀結(jié)構(gòu)

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

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

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

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

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

7. 底層機(jī)制擴(kuò)展:JVM 引用與 GC 行為

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

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

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

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

Java 的 GC 通過 可達(dá)性分析(Reachability Analysis) 判斷對象是否存活。
即使存在自引用(如循環(huán)鏈表),只要外部沒有引用鏈指向該結(jié)構(gòu),它仍會被 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)結(jié)構(gòu)在下一次 GC 時被回收,無內(nèi)存泄漏。

8. 與 C 語言的對比

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

9.總結(jié)與核心觀點

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

?? 一句話總結(jié)

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

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

相關(guān)文章

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

    Java等待喚醒機(jī)制線程通信原理解析

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

    Java HashMap實現(xiàn)原理分析(一)

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

    Java網(wǎng)絡(luò)編程基礎(chǔ)用法詳解

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

    IntelliJ IDEA 2017 漢化包及圖文教程

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

    Spring?Retry?實現(xiàn)樂觀鎖重試實踐記錄

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

    Restful傳遞數(shù)組參數(shù)及注解大全

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

    如何安裝Hadoop并運行WordCount程序

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

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

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

    java 中HashCode重復(fù)的可能性

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

    Java超全面梳理內(nèi)部類的使用

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

最新評論

辽阳县| 大埔区| 静海县| 五家渠市| 四川省| 白水县| 连州市| 连山| 土默特右旗| 开阳县| 通辽市| 松阳县| 岑巩县| 尼勒克县| 浙江省| 建瓯市| 信丰县| 根河市| 大竹县| 景宁| 余姚市| 赫章县| 宜州市| 大冶市| SHOW| 大荔县| 麦盖提县| 汝南县| 梨树县| 镇雄县| 开封市| 西和县| 即墨市| 沧源| 奉新县| 鲜城| 怀仁县| 金乡县| 渭源县| 临夏县| 大埔县|