簡體   English   中英

如何確定Java方法是否修改作為參數傳遞的對象

[英]How to determine if a Java method modifies an object passed as parameter

我來自C ++背景,目前我正在學習Java。 當我嘗試使用某些第三方庫時出現了一個問題。 如何確定對作為參數的對象引用的方法的調用是否修改了對象? 在C ++中,由於使用了const關鍵字,因此很清楚。 如果方法簽名是:

void foo(Boo& boo);

我知道引用的對象可能會被修改,而如果方法簽名是:

void foo(const Boo& boo);

編譯器保證不會修改引用的對象。

我沒有在Java中看到類似的東西,因為只有引用本身可以被聲明為final,而不是引用的對象,並且最終的參數在第一個地方沒有多大意義,因為它無論如何都是通過值傳遞的。 因此,當我看到一個方法,如:

void foo(Boo boo) {...}

如何確定boo引用的對象是否在函數體內修改(可能使用注釋)? 如果沒有辦法知道,是否有一些廣泛使用的約定或一些最佳實踐來避免混淆和錯誤?

如何確定boo引用的對象是否在函數體內修改(可能使用注釋)?

唯一的方法是不幸地讀取代碼。

如果沒有辦法知道,是否有一些廣泛使用的約定或一些最佳實踐來避免混淆和錯誤?

常見的慣例是在需要時使用包裝器傳遞無法修改的對象。 這樣可以確保類無法修改對象。

List<String> readOnly = Collections.unmodifiableList(list);

如果對象是Cloneable,您也可以使用clone()但另一種常見方法是使用副本。

List<String> readOnly = new ArrayList<>(list);

如果您關心此類行為,單元測試可以顯示方法是否修改了對象。 如果您已經進行了單元測試,通常需要一兩行來檢查。

不幸的是,這種語言沒有內置這種設施。 一個好的防御性做法是將您傳遞的數據對象定義為不可變的(即,沒有任何允許修改其狀態的公共方法)。 如果你真的關心這個問題,你可以在將對象傳遞給你不信任的方法之前復制/克隆一個對象,但這通常是一個多余的預防措施。

注意:這個答案是更詳細的版本

您還可以在代碼中編寫純度或副作用注釋 - mernst

在編譯時可以通過注釋檢查的各種事物之間存在Checker FrameworkIJG Immutablity檢查器 此檢查器允許您使用@Immutable@ReadOnly注釋對象引用。

問題是您經常需要自己注釋庫 為了簡化您的任務,Checker Framework可以自動推斷部分注釋; 你仍然需要自己做很多事情。

Java語言中沒有內置副作用分析。

您可以通過手動檢查執行副作用分析,但是存在一些自動化過程的工具。

您可以使用一個推理工具( 123 ),以檢測是否你的代碼的副作用的參數。

你也可以寫純度或副作用的注釋你的代碼,然后用一個檢查/驗證工具( 12 ),以確保您的代碼符合你寫的注釋。

所有上述鏈接工具都有局限性,但您可能會發現它們很有用。 如果您了解其他工具,請在評論中提及。

如何確定boo引用的對象是否在函數體內修改(可能使用注釋)?

我必須同意其他答案,沒有直接的方法來確定該方法是否會修改您的對象,是的,以確保該方法無法修改您的Object您必須做的就是在您身邊。

如果沒有辦法知道,是否有一些廣泛使用的約定或一些最佳實踐來避免混淆和錯誤?

這里方法名稱出現在場景中。 繼續使用方法的命名約定,我們必須查看一些方法聲明,這些聲明明確地說服了您的Object根本不會被更改。

例如,你知道Arrays.copyOf不會改變你的實際數組, System.out.println(boo)不會改變你的boo

方法名稱是真正的武器 ,可以為方法用戶提供盡可能多的信息。 (是的!這總是不可能,但要遵循相當不錯的做法。)

讓我們考慮在你的情況下說printBoo只會打印, copyBoo只會復制, clearBoo會重置所有屬性, checkAndCreateNewBoo會檢查你的boo Object並在需要時創建新的。

因此,最終,如果我們能以適當的方式調用者使用他們可以用事實放心Object會調用該方法后保持不變。

正如大家所說,更喜歡使用不可變對象,也避免使用void方法

這樣的方法的可用目的

void foo(Boo boo) {...}

是更改對象本身的狀態或更改作為參數傳遞的對象

void completOrder(Order order) { ... }
//or
void parserTokenEnded(String str) { ... }

有一種方法,方法開發人員應將參數標記為final,如果它不打算修改參數。

     public void test(final Object param)

然而,很少有人遵循這一點,因此很難知道。 然而,優秀的程序員遵循這條規則,尤其是編寫api。 如果要編寫方法並公開它。 make param final表示不會修改傳遞的對象。

暫無
暫無

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

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