簡體   English   中英

使用反射從公共到私有

[英]Public to private using reflection

我正在嘗試執行類似以下代碼的操作:

public class Connector {
     public static Connection getConnection() {
         conn = DriverManager.getConnection(String, String, String);
         conn.getClass().getMethod("close").setAccessible(false); // this is what i am trying to achieve
     }
     public static void close(Connection c) {
         c.getClass().getMethod("close").setAccessible(true);
         try{ c.close(); }
         catch(Throwable e) {}
     }
}

我想阻止其他人調用conn.close()並強制他們使用Connector.close()因為有時conn.close()在調用時會拋出NullPointerException 甚至有可能嗎?

從理論上講,使用“類加載器魔術”可能會發生這樣的事情。

換句話說:您可以創建自己的類加載器,在加載它們的同時操作特定的類。

使用問題中提出的反射很可能不起作用。 請記住:反射主要是關於代碼結構的反射 是的,之前的Java 9,你可以很容易地轉向“低層次”,改變字段的可訪問性(除非安全管理是否到位),但除此之外,反射不允許更改代碼的結構。 它用於檢查,而不是操縱

所以,真正的答案是:不要那樣做。 而是想出人們應該使用的正確、干凈的界面。

將某些內容公開以供以后在運行時將其減少到低於此值是沒有意義的。 這與“適當的 OOP”相反。

不要編寫自己的類加載器,這太糟糕了。

而是創建您自己的類,可能命名為RestrictedConnection並使用組合來包含真正的Connection

接下來,不要為 RestrictedConnection 類提供close方法。

我想阻止其他人調用conn.close()並強制人們使用Connector.close()因為有時conn.close()從 jsp 調用時會拋出NullPointerException 甚至有可能嗎?

即使可能,它也達不到你的目的。 您只需將 JSP 代碼嘗試調用Connection.close()時發生的異常更改為IncompatibleClassChangeError 那不是更好。

撇開JSP 首先直接訪問Connection或調用其close()方法是否是個好主意的問題,有時會遇到NPE 的事實表明應用程序邏輯存在缺陷。 您應該追蹤並修復它——為什么您的 JSP 有時會變為null而不是真正的Connection ——而不是試圖對症狀施加創可貼。

您可以創建一個包裝器對象,該對象僅包含 Connection 對象,並將每個類重新路由到基礎 Connection,除非關閉。

public class CustomConnection {
    private Connection conn;
    public CustomConnection( Connection conn ) {
        this.conn = conn;
    }

    public void close() {
       throw new ForbiddenException();
    }

    public void commit() {
        this.conn.commit();
    }

    ....

}

並更改您的連接器類:

public class Connector {
     public static CustomConnection getConnection() {
         conn = DriverManager.getConnection(String, String, String);
         return new CustomConnection( conn );
     }
}

我認為你最好的選擇是:

  • 子類連接並在有人調用 close 時拋出異常。 這是更簡單的選項,不會給出編譯時錯誤,但調用它永遠不會工作,人們不會這樣做(而不是這樣做,因為它工作一次然后再出錯)。

  • 創建一個 Annotation Preprocessor 以在用戶代碼中調用該方法時給出編譯時錯誤。 這更加困難和復雜,可能不是最好的方法,但會在編譯時出錯,這總是更好。

如果可能的話,使用反射最多只會給出一個運行時錯誤,所以在這種情況下,我寧願選擇一個更簡單、更清晰的選項。

不敢相信沒有人提到這一點:棄用它,在更高版本中刪除它


public方法轉換為private方法可能會導致代碼損壞。

處理這種情況的最佳方法:通知其他人“這可能會在未來被刪除”:在破壞舊版本之前給他們時間更新他們的代碼。

這就是@Deprecated的用途。 如果其他人依賴他們的代碼,請不要在沒有警告的情況下破壞它。 稍后,您可以刪除它,並保證您告訴依賴者它將不再可訪問。

是的,用戶仍然可以使用它。 但至少他們會知道他們不應該使用它。 好處是讓依賴您的代碼的開發人員有時間更新他們的軟件,而不是立即破壞他們的軟件。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM