欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

java仿C++模擬實現(xiàn)一個智能指針

 更新時間:2025年05月30日 09:23:15   作者:Katie。  
在?C++?等語言中,指針?是對內(nèi)存地址的直接操作,為靈活管理內(nèi)存和實現(xiàn)數(shù)據(jù)結(jié)構(gòu)提供了強大能力,本文將使用純Java實現(xiàn)一個通用的?SmartPointer<T>框架為各種資源類型提供類似?C++?智能指針的使用體驗

一、項目背景詳細(xì)介紹

1. 指針與智能指針概述

在 C++ 等語言中,指針 是對內(nèi)存地址的直接操作,為靈活管理內(nèi)存和實現(xiàn)數(shù)據(jù)結(jié)構(gòu)提供了強大能力,但也帶來懸掛指針、內(nèi)存泄漏和雙重釋放等安全風(fēng)險。為此,C++11 標(biāo)準(zhǔn)引入了 智能指針(smart pointer),如 std::unique_ptr、std::shared_ptr 和 std::weak_ptr,在構(gòu)造和析構(gòu)時自動管理資源,避免手動 delete 帶來的諸多問題。

Java 語言本身運行在垃圾回收(GC)機(jī)制下,所有對象均由 JVM 自動回收,程序員無需顯式釋放內(nèi)存。但在以下場景中,仍需要“智能指針”式的自動化資源管理:

非內(nèi)存資源:如文件句柄、數(shù)據(jù)庫連接、網(wǎng)絡(luò)套接字,這些資源不由 GC 管理,需要顯式關(guān)閉。

引用計數(shù):在復(fù)雜對象圖中,有時需要統(tǒng)計引用或在最后一個引用消亡時觸發(fā)某些清理動作。

弱引用管理:實現(xiàn)緩存或監(jiān)聽器時希望對象可被 GC 回收。

本項目旨在使用純 Java 實現(xiàn)一個通用的 SmartPointer<T> 框架,通過引用計數(shù)或自動關(guān)閉語義,為各種資源類型提供類似 C++ 智能指針的使用體驗。

1.2 智能指針在 Java 中的必要性

自動管理非內(nèi)存資源:避免因忘記關(guān)閉流或連接導(dǎo)致的資源泄漏;

延遲清理邏輯:可在最后一個引用消亡時執(zhí)行自定義回調(diào);

緩存與弱引用:結(jié)合 WeakReference 與 ReferenceQueue 實現(xiàn)自動過期緩存;

統(tǒng)一 API:對外暴露與普通對象相同接口,增強代碼可讀性與安全性。

二、項目需求詳細(xì)介紹

1.核心接口

定義泛型接口 SmartPointer<T>:

public interface SmartPointer<T> {
    T get();                    // 獲取底層對象
    void retain();             // 增加引用計數(shù)
    void release();            // 減少引用計數(shù),必要時觸發(fā)清理
    int useCount();            // 當(dāng)前引用計數(shù)
    boolean isValid();         // 底層資源是否仍可用
}

2.實現(xiàn)類

RefCountedPointer<T>:基于引用計數(shù)(AtomicInteger)管理對象,最后一個 release() 時執(zhí)行可選的清理函數(shù)。

AutoClosePointer<T extends AutoCloseable>:包裝 AutoCloseable 類型,在引用計數(shù)為零時自動調(diào)用 close();

3.弱引用支持

WeakSmartPointer<T>:內(nèi)部用 WeakReference<T> 和 ReferenceQueue<T>,對象回收時觸發(fā)清理回調(diào);

4.線程安全

所有實現(xiàn)均使用原子操作或同步保證多線程環(huán)境下的正確引用計數(shù)。

5.使用示例

文件流、數(shù)據(jù)庫連接、線程執(zhí)行上下文等多種場景示例。

6.擴(kuò)展性

支持自定義清理動作(Runnable onFinalize);

可組合多種智能指針。

7.測試與示例

單元測試驗證 retain/release 語義、并發(fā)安全、弱引用回調(diào);

示例 main 演示文件讀取、緩存管理。

8.文檔與注釋

Javadoc 注釋所有接口與方法;

README 說明使用方法與注意事項。

9.教學(xué)要求

在博客中結(jié)合 UML 類圖和時序圖解釋引用計數(shù)和弱引用回收機(jī)制;

詳細(xì)討論與 GC、LeakSafe、try-with-resources 的區(qū)別。

三、相關(guān)技術(shù)詳細(xì)介紹

3.1 Java 垃圾回收與 AutoCloseable

JVM 會在無強引用對象時自動回收內(nèi)存,但不管理文件句柄、數(shù)據(jù)庫連接等非內(nèi)存資源,需實現(xiàn) AutoCloseable 并在 close() 中釋放資源。

Java 7 引入了 try-with-resources 語法糖,但僅對局部作用域資源生效,不能在任意作用域通過引用計數(shù)自動關(guān)閉。

3.2 引用計數(shù)

維護(hù)一個 AtomicInteger count;

retain() 時 count.incrementAndGet();

release() 時 count.decrementAndGet(),當(dāng)返回 0 時執(zhí)行清理;

需防止循環(huán)引用或多次釋放。

3.3 弱引用與 ReferenceQueue

WeakReference<T>:不會阻止對象被回收,對象回收后弱引用入隊;

ReferenceQueue<T>:持有弱引用的引用隊列,可在后臺線程中監(jiān)聽并執(zhí)行回調(diào);

適合緩存場景:對象被卸載后自動從緩存中移除。

3.4 線程安全與并發(fā)測試

使用 AtomicInteger 和 volatile,或在必要處進(jìn)行 synchronized;

單元測試中模擬高并發(fā) retain/release 調(diào)用,驗證計數(shù)準(zhǔn)確與僅調(diào)用一次清理。

四、實現(xiàn)思路詳細(xì)介紹

1.SmartPointer<T> 接口

定義基礎(chǔ)方法,屏蔽底層實現(xiàn);

2.AbstractRefCountedPointer<T>

抽象基類,維護(hù) protected final T referent; private final AtomicInteger refCount = new AtomicInteger(1); private final Runnable cleanup;

實現(xiàn) retain(), useCount(), isValid();

release() 調(diào)用 if (refCount.decrementAndGet()==0) cleanup.run();

3.RefCountedPointer<T>

繼承自 AbstractRefCountedPointer<T>,提供構(gòu)造器接受 referent 和可選 cleanup;

4.AutoClosePointer<T extends AutoCloseable>

構(gòu)造時傳入 T referent,cleanup = referent::close;

5.WeakSmartPointer<T>

內(nèi)部持有 WeakReference<T> weakRef 和 ReferenceQueue<T> queue;

單例后臺線程監(jiān)聽 queue,取出已回收對象對應(yīng)弱引用并執(zhí)行回調(diào);

6.使用示例

文件讀?。河?AutoClosePointer<InputStream> 自動 close();

連接池:用 RefCountedPointer<Connection> 多處 retain,最后自動 shutdown;

緩存:WeakSmartPointer<LargeObject>,對象回收時自動從 Map 中移除。

7.線程安全

refCount 用原子操作保證;弱引用隊列監(jiān)聽使用單線程安全;

8.測試

JUnit 測試 refCount 邊界、并發(fā)、多次 release() 無錯誤;

弱引用回收后回調(diào)執(zhí)行一次。

五、完整實現(xiàn)代碼

// =================================================================
// 文件:SmartPointer.java
// 包名:com.example.smartptr
// 功能:通用智能指針接口
// =================================================================
package com.example.smartptr;
 
public interface SmartPointer<T> {
    /** 返回被管理的對象,若已清理則拋異常 */
    T get();
    /** 增加引用計數(shù) */
    void retain();
    /** 減少引用計數(shù),必要時觸發(fā)清理 */
    void release();
    /** 當(dāng)前引用計數(shù) */
    int useCount();
    /** 對象是否仍未被清理 */
    boolean isValid();
}
 
// =================================================================
// 文件:AbstractRefCountedPointer.java
// 包名:com.example.smartptr
// 功能:帶引用計數(shù)與清理回調(diào)的抽象基類
// =================================================================
package com.example.smartptr;
 
import java.util.concurrent.atomic.AtomicInteger;
 
public abstract class AbstractRefCountedPointer<T> implements SmartPointer<T> {
    protected final T referent;
    private final AtomicInteger refCount = new AtomicInteger(1);
    private final Runnable cleanup;
    private volatile boolean valid = true;
 
    protected AbstractRefCountedPointer(T referent, Runnable cleanup) {
        if (referent == null) throw new IllegalArgumentException("Referent cannot be null");
        this.referent = referent;
        this.cleanup  = cleanup;
    }
 
    @Override
    public T get() {
        if (!valid) throw new IllegalStateException("Resource already released");
        return referent;
    }
 
    @Override
    public void retain() {
        if (!valid) throw new IllegalStateException("Cannot retain released resource");
        refCount.incrementAndGet();
    }
 
    @Override
    public void release() {
        int rc = refCount.decrementAndGet();
        if (rc < 0) throw new IllegalStateException("release() called too many times");
        if (rc == 0) {
            valid = false;
            cleanup.run();
        }
    }
 
    @Override
    public int useCount() {
        return refCount.get();
    }
 
    @Override
    public boolean isValid() {
        return valid;
    }
}
 
// =================================================================
// 文件:RefCountedPointer.java
// 包名:com.example.smartptr
// 功能:普通對象的引用計數(shù)智能指針
// =================================================================
package com.example.smartptr;
 
public class RefCountedPointer<T> extends AbstractRefCountedPointer<T> {
    public RefCountedPointer(T referent, Runnable cleanup) {
        super(referent, cleanup != null ? cleanup : () -> {});
    }
    public RefCountedPointer(T referent) {
        this(referent, () -> {});
    }
}
 
// =================================================================
// 文件:AutoClosePointer.java
// 包名:com.example.smartptr
// 功能:自動關(guān)閉 AutoCloseable 資源的智能指針
// =================================================================
package com.example.smartptr;
 
public class AutoClosePointer<T extends AutoCloseable>
        extends AbstractRefCountedPointer<T> {
    public AutoClosePointer(T referent) {
        super(referent, () -> {
            try { referent.close(); }
            catch (Exception e) { /* 可記錄日志 */ }
        });
    }
}
 
// =================================================================
// 文件:WeakSmartPointer.java
// 包名:com.example.smartptr
// 功能:弱引用智能指針,資源被 GC 回收時觸發(fā)回調(diào)
// =================================================================
package com.example.smartptr;
 
import java.lang.ref.*;
import java.util.concurrent.*;
 
public class WeakSmartPointer<T> implements SmartPointer<T> {
    private final WeakReference<T> weakRef;
    private final ReferenceQueue<T> queue = new ReferenceQueue<>();
    private final Runnable cleanup;
    private volatile boolean valid = true;
 
    public WeakSmartPointer(T referent, Runnable cleanup) {
        this.weakRef = new WeakReference<>(referent, queue);
        this.cleanup = cleanup != null ? cleanup : () -> {};
        startWatcher();
    }
 
    private void startWatcher() {
        Thread watcher = new Thread(() -> {
            try {
                Reference<? extends T> r = queue.remove();
                if (r == weakRef) {
                    valid = false;
                    cleanup.run();
                }
            } catch (InterruptedException ignored) {}
        }, "WeakPtr-Watcher");
        watcher.setDaemon(true);
        watcher.start();
    }
 
    @Override
    public T get() {
        T t = weakRef.get();
        if (t == null) throw new IllegalStateException("Resource already GCed");
        return t;
    }
 
    @Override
    public void retain() {
        throw new UnsupportedOperationException("WeakSmartPointer does not support retain()");
    }
 
    @Override
    public void release() {
        throw new UnsupportedOperationException("WeakSmartPointer does not support release()");
    }
 
    @Override
    public int useCount() {
        return valid && weakRef.get() != null ? 1 : 0;
    }
 
    @Override
    public boolean isValid() {
        return valid && weakRef.get() != null;
    }
}
 
// =================================================================
// 文件:Main.java
// 包名:com.example.smartptr
// 功能:示例演示各種智能指針的使用場景
// =================================================================
package com.example.smartptr;
 
import java.io.*;
 
public class Main {
    public static void main(String[] args) throws Exception {
        System.out.println("=== RefCountedPointer 示例 ===");
        RefCountedPointer<StringBuilder> p = new RefCountedPointer<>(
            new StringBuilder("Hello"), () -> System.out.println("Cleanup called"));
        System.out.println("useCount=" + p.useCount());
        p.retain();
        System.out.println("useCount after retain=" + p.useCount());
        p.release();
        System.out.println("useCount after release=" + p.useCount());
        p.release(); // 最后一次,觸發(fā) cleanup
        System.out.println("isValid=" + p.isValid());
 
        System.out.println("\n=== AutoClosePointer 示例 ===");
        AutoClosePointer<FileInputStream> ap =
            new AutoClosePointer<>(new FileInputStream("test.txt"));
        FileInputStream fis = ap.get();
        System.out.println("File opened? " + (fis != null));
        ap.release(); // 自動 close()
 
        System.out.println("\n=== WeakSmartPointer 示例 ===");
        Object obj = new Object();
        WeakSmartPointer<Object> wp = new WeakSmartPointer<>(obj,
            () -> System.out.println("Weak cleanup called"));
        System.out.println("isValid before GC=" + wp.isValid());
        obj = null;
        System.gc(); Thread.sleep(100);
        System.out.println("isValid after GC=" + wp.isValid());
    }
}

六、代碼詳細(xì)解讀

SmartPointer<T>:統(tǒng)一接口;

AbstractRefCountedPointer<T>:引用計數(shù)基類,用 AtomicInteger 管理計數(shù),并在計數(shù)歸零時執(zhí)行清理回調(diào);

RefCountedPointer<T>:一般對象版,可選傳入自定義 cleanup;

AutoClosePointer<T>:針對 AutoCloseable,在最后一次 release() 時自動 close();

WeakSmartPointer<T>:使用 WeakReference 與后臺 ReferenceQueue 監(jiān)聽對象回收并執(zhí)行 cleanup;

七、項目詳細(xì)總結(jié)

本文在 Java 中手寫實現(xiàn)了多種“智能指針”模型:

引用計數(shù)智能指針:多處 retain/release,引用歸零時回調(diào);

自動關(guān)閉智能指針:封裝 AutoCloseable,最后釋放時自動關(guān)閉資源;

弱引用智能指針:結(jié)合 WeakReference 與 ReferenceQueue,對象 GC 后執(zhí)行回調(diào);

這些工具框架能幫助你在 Java 中對非內(nèi)存資源或需要特殊回調(diào)的對象進(jìn)行自動化管理,提升代碼安全性與健壯性。

八、項目常見問題及解答

Q1:Java 已有 GC,為什么還要引用計數(shù)?

A1:GC 只管理內(nèi)存,不負(fù)責(zé)文件、連接等資源,引用計數(shù)智能指針可在最后一個引用釋放時自動清理這些資源。

Q2:ReferenceQueue 會阻塞嗎?

A2:queue.remove() 會阻塞直到有引用入隊,因此 watcher 線程設(shè)置為守護(hù)線程并僅在一條引用回收時喚醒。

Q3:如何防止循環(huán)引用導(dǎo)致資源永不釋放?

A3:引用計數(shù)本身無法打破循環(huán)引用,可結(jié)合弱引用或手動調(diào)用 release() 斷開循環(huán)。

Q4:AutoClosePointer vs try-with-resources?

A4:try-with-resources 只在局部作用域有效,智能指針可跨作用域管理資源并延遲關(guān)閉。

Q5:使用智能指針會帶來性能開銷嗎?

A5:引用計數(shù)和弱引用機(jī)制有一定原子操作和線程管理開銷,應(yīng)在性能敏感場景做測評。

九、擴(kuò)展方向與性能優(yōu)化

循環(huán)引用檢測:結(jié)合 ReferenceQueue 和弱引用斷環(huán),避免循環(huán)引用泄漏;

異步清理:將 cleanup 回調(diào)提交線程池執(zhí)行,避免阻塞釋放線程;

自定義清理策略:支持不同場景的 retry、超時或降級處理;

分布式引用計數(shù):在分布式對象緩存中實現(xiàn)全局引用計數(shù);

與 Spring 集成:將智能指針作為 Bean 管理,利用容器生命周期自動管理資源。

到此這篇關(guān)于java仿C++模擬實現(xiàn)一個智能指針的文章就介紹到這了,更多相關(guān)java智能指針內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 字節(jié)碼調(diào)教入口JVM?寄生插件javaagent

    字節(jié)碼調(diào)教入口JVM?寄生插件javaagent

    這篇文章主要介紹了字節(jié)碼調(diào)教入口JVM?寄生插件javaagent方法示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-08-08
  • Java使用POI導(dǎo)出Excel(一):單sheet

    Java使用POI導(dǎo)出Excel(一):單sheet

    這篇文章介紹了Java使用POI導(dǎo)出Excel的方法,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-10-10
  • Apache?log4j2-RCE?漏洞復(fù)現(xiàn)及修復(fù)建議(CVE-2021-44228)

    Apache?log4j2-RCE?漏洞復(fù)現(xiàn)及修復(fù)建議(CVE-2021-44228)

    Apache?Log4j2是一款Java日志框架,大量應(yīng)用于業(yè)務(wù)系統(tǒng)開發(fā)。2021年11月24日,阿里云安全團(tuán)隊向Apache官方報告了Apache?Log4j2遠(yuǎn)程代碼執(zhí)行漏洞(CVE-2021-44228),本文給大家介紹Apache?log4j2-RCE?漏洞復(fù)現(xiàn)(CVE-2021-44228)的相關(guān)知識,感興趣的朋友一起看看吧
    2021-12-12
  • 舉例解析Java多線程編程中需要注意的一些關(guān)鍵點

    舉例解析Java多線程編程中需要注意的一些關(guān)鍵點

    這篇文章主要介紹了Java多線程編程中需要注意的一些關(guān)鍵點,包括ThreadLocal變量與原子更新等一些深層次的內(nèi)容,需要的朋友可以參考下
    2015-11-11
  • Spring三級緩存解決循環(huán)依賴的過程分析

    Spring三級緩存解決循環(huán)依賴的過程分析

    這篇文章主要介紹了Spring三級緩存解決循環(huán)依賴,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-04-04
  • MyBatis Mapper中 @Select注解調(diào)用靜態(tài)常量的問題分析

    MyBatis Mapper中 @Select注解調(diào)用靜態(tài)常量的問題分析

    在Java編碼中,我們通常會把這些數(shù)字或者字符串定義在常量類或者接口中,可以直接在mapper中也可以使用這些常量就比較好,這篇文章主要介紹了MyBatis Mapper中 @Select注解調(diào)用靜態(tài)常量,需要的朋友可以參考下
    2023-06-06
  • Spring Boot Log4j2的配置使用詳解

    Spring Boot Log4j2的配置使用詳解

    本篇文章主要介紹了Spring Boot Log4j2的配置使用詳解,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-05-05
  • Springboot整合Activiti操作詳解

    Springboot整合Activiti操作詳解

    這篇文章主要給大家詳細(xì)介紹了Springboot整合Activiti的操作流程,文中流程步驟和代碼示例介紹的非常詳細(xì),具有一定的參考價值,需要的朋友可以參考下
    2023-07-07
  • springboot?接收LocalDateTime方式

    springboot?接收LocalDateTime方式

    這篇文章主要介紹了springboot?接收LocalDateTime方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-07-07
  • 詳解SpringBoot集成Redis來實現(xiàn)緩存技術(shù)方案

    詳解SpringBoot集成Redis來實現(xiàn)緩存技術(shù)方案

    本篇文章主要介紹了詳解SpringBoot集成Redis來實現(xiàn)緩存技術(shù)方案,具有一定的參考價值,有興趣的可以了解一下
    2017-06-06

最新評論