爲什麼不應該在參數中使用Java 8的Optional

本文翻譯自:Why should Java 8's Optional not be used in arguments

I've read on many Web sites Optional should be used as a return type only, and not used in method arguments. 我已經在許多網站上閱讀了Optional應該僅用作返回類型,而不能在方法參數中使用。 I'm struggling to find a logical reason why. 我正在努力尋找一個合理的理由。 For example I have a piece of logic which has 2 optional parameters. 例如,我有一段邏輯,其中包含2個可選參數。 Therefore I think it would make sense to write my method signature like this (solution 1): 因此,我認爲這樣寫我的方法簽名將是有意義的(解決方案1):

public int calculateSomething(Optional<String> p1, Optional<BigDecimal> p2 {
    // my logic
}

Many web pages specify Optional should not be used as method arguments. 許多指定爲Optional的網頁不應用作方法參數。 With this in mind, I could use the following method signature and add a clear Javadoc comment to specify that the arguments may be null, hoping future maintainers will read the Javadoc and therefore always carry out null checks prior to using the arguments (solution 2): 考慮到這一點,我可以使用以下方法簽名並添加清晰的Javadoc註釋以指定參數可以爲null,希望以後的維護者將讀取Javadoc,因此始終在使用參數之前進行null檢查(解決方案2) :

public int calculateSomething(String p1, BigDecimal p2) {
    // my logic
}

Alternatively I could replace my method with four public methods to provide a nicer interface and make it more obvious p1 and p2 are optional (solution 3): 或者,我可以用四個公共方法替換我的方法,以提供更好的接口,並使p1和p2更加明顯(解決方案3):

public int calculateSomething() {
    calculateSomething(null, null);
}

public int calculateSomething(String p1) {
    calculateSomething(p1, null);
}

public int calculateSomething(BigDecimal p2) {
    calculateSomething(null, p2);
}

public int calculateSomething(String p1, BigDecimal p2) {
    // my logic
}

Now I try writing the code of the class which invokes this piece of logic for each approach. 現在,我嘗試編寫該類的代碼,每種方法都會調用此邏輯。 I first retrieve the two input parameters from another object which returns Optional s and then, I invoke calculateSomething . 我首先從另一個返回Optional的對象中檢索兩個輸入參數,然後調用calculateSomething Therefore, if solution 1 is used the calling code would look like this: 因此,如果使用解決方案1,則調用代碼將如下所示:

Optional<String> p1 = otherObject.getP1();
Optional<BigInteger> p2 = otherObject.getP2();
int result = myObject.calculateSomething(p1, p2);

if solution 2 is used, the calling code would look like this: 如果使用解決方案2,則調用代碼將如下所示:

Optional<String> p1 = otherObject.getP1();
Optional<BigInteger> p2 = otherObject.getP2();
int result = myObject.calculateSomething(p1.orElse(null), p2.orElse(null));

if solution 3 is applied, I could use the code above or I could use the following (but it's significantly more code): 如果應用瞭解決方案3,我可以使用上面的代碼,也可以使用以下代碼(但是代碼很多):

Optional<String> p1 = otherObject.getP1();
Optional<BigInteger> p2 = otherObject.getP2();
int result;
if (p1.isPresent()) {
    if (p2.isPresent()) {
        result = myObject.calculateSomething(p1, p2);
    } else {
        result = myObject.calculateSomething(p1);
    }
} else {
    if (p2.isPresent()) {
        result = myObject.calculateSomething(p2);
    } else {
        result = myObject.calculateSomething();
    }
}

So my question is: Why is it considered bad practice to use Optional s as method arguments (see solution 1)? 所以我的問題是:爲什麼將Optional用作方法參數被認爲是不好的做法(請參閱解決方案1)? It looks like the most readable solution to me and makes it most obvious that the parameters could be empty/null to future maintainers. 對我來說,這似乎是最易讀的解決方案,並且對於將來的維護人員來說,最明顯的是參數可以爲空/空。 (I'm aware the designers of Optional intended it to only be used as a return type, but I can't find any logical reasons not to use it in this scenario). (我知道Optional的設計者打算將其僅用作返回類型,但在這種情況下我找不到任何不使用它的邏輯原因)。


#1樓

參考:https://stackoom.com/question/29waw/爲什麼不應該在參數中使用Java-的Optional


#2樓

I think that is because you usually write your functions to manipulate data, and then lift it to Optional using map and similar functions. 我認爲這是因爲通常編寫函數來處理數據,然後使用map和類似函數將其提升爲Optional This adds the default Optional behavior to it. 這將爲其添加默認的Optional行爲。 Of course, there might be cases, when it is necessary to write your own auxilary function that works on Optional . 當然,在某些情況下,有必要編寫自己的對Optional起作用的輔助函數。


#3樓

I believe the reson of being is you have to first check whether or not Optional is null itself and then try to evaluate value it wraps. 我相信,存在的共鳴是您必須首先檢查Optional是否爲null,然後嘗試評估它包裝的值。 Too many unnecessary validations. 太多不必要的驗證。


#4樓

The pattern with Optional is for one to avoid returning null . 帶有Optional的模式是爲了避免返回 null It's still perfectly possible to pass in null to a method. 仍然可以將null傳遞給方法。

While these aren't really official yet, you can use JSR-308 style annotations to indicate whether or not you accept null values into the function. 儘管這些還不是真正的官方,但是您可以使用JSR-308樣式註釋來指示您是否在函數中接受null值。 Note that you'd have to have the right tooling to actually identify it, and it'd provide more of a static check than an enforceable runtime policy, but it would help. 請注意,您必須具有正確的工具來實際識別它,並且它提供的靜態檢查多於可執行的運行時策略,但這會有所幫助。

public int calculateSomething(@NotNull final String p1, @NotNull final String p2) {}

#5樓

Oh, those coding styles are to be taken with a bit of salt. 哦,這些編碼風格要花點兒力氣。

  1. (+) Passing an Optional result to another method, without any semantic analysis; (+)將Optional結果傳遞給另一種方法,而無需任何語義分析; leaving that to the method, is quite alright. 將其留給方法,是完全可以的。
  2. (-) Using Optional parameters causing conditional logic inside the methods is literally contra-productive. (-)使用可選參數在方法內部引起條件邏輯實際上是相反的。
  3. (-) Needing to pack an argument in an Optional, is suboptimal for the compiler, and does an unnecessary wrapping. (-)需要將參數打包在Optional中,對於編譯器來說不是最佳選擇,並且不需要進行包裝。
  4. (-) In comparison to nullable parameters Optional is more costly. (-)與可爲空的參數相比,可選的成本更高。

In general: Optional unifies two states, which have to be unraveled. 一般而言:Optional統一了兩個狀態,必須將其拆散。 Hence better suited for result than input, for the complexity of the data flow. 因此,對於數據流的複雜性,比輸入更適合結果。


#6樓

This advice is a variant of the "be as unspecific as possible regarding inputs and as specific as possible regarding outputs" rule of thumb. 該建議是“對於輸入儘可能不具體,而對輸出儘可能具體”的一種變體。

Usually if you have a method that takes a plain non-null value, you can map it over the Optional , so the plain version is strictly more unspecific regarding inputs. 通常,如果您有一個採用純非null值的方法,則可以將其映射到Optional ,因此對於輸入,純格式嚴格來說更加不確定。 However there are a bunch of possible reasons why you would want to require an Optional argument nonetheless: 但是,仍然有很多可能的原因導致您仍然需要一個Optional參數的原因:

  • you want your function to be used in conjunction with another API that returns an Optional 您希望將您的函數與另一個返回Optional API結合使用
  • Your function should return something other than an empty Optional if the given value is empty 您的函數應返回空值以外的其他值如果給定值爲空,則爲Optional
  • You think Optional is so awesome that whoever uses your API should be required to learn about it ;-) 您認爲Optional非常好,以至於使用API​​的人都必須瞭解它;-)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章