<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                ## Chapter 8. Methods(方法) ### Item 55: Return optionals judiciously(明智地的返回 Optional) Prior to Java 8, there were two approaches you could take when writing a method that was unable to return a value under certain circumstances. Either you could throw an exception, or you could return null (assuming the return type was an object reference type). Neither of these approaches is perfect. Exceptions should be reserved for exceptional conditions (Item 69), and throwing an exception is expensive because the entire stack trace is captured when an exception is created. Returning null doesn’t have these shortcomings, but it has its own. If a method returns null, clients must contain special-case code to deal with the possibility of a null return, unless the programmer can prove that a null return is impossible. If a client neglects to check for a null return and stores a null return value away in some data structure, a NullPointerException may result at some arbitrary time in the future, at some place in the code that has nothing to do with the problem. 在 Java 8 之前,在編寫在某些情況下無法返回值的方法時,可以采用兩種方法。要么拋出異常,要么返回 null(假設返回類型是對象引用類型)。這兩種方法都不完美。應該為異常條件保留異常([Item-69](/Chapter-10/Chapter-10-Item-69-Use-exceptions-only-for-exceptional-conditions.md)),并且拋出異常代價高昂,因為在創建異常時捕獲整個堆棧跟蹤。返回 null 沒有這些缺點,但是它有自己的缺點。如果方法返回 null,客戶端必須包含特殊情況代碼來處理 null 返回的可能性,除非程序員能夠證明 null 返回是不可能的。如果客戶端忽略檢查 null 返回并將 null 返回值存儲在某個數據結構中,那么 NullPointerException 可能會在將來的某個時間,在代碼中的某個與該問題無關的位置產生。 In Java 8, there is a third approach to writing methods that may not be able to return a value. The `Optional<T>` class represents an immutable container that can hold either a single non-null T reference or nothing at all. An optional that contains nothing is said to be empty. A value is said to be present in an optional that is not empty. An optional is essentially an immutable collection that can hold at most one element. `Optional<T>` does not implement `Collection<T>`, but it could in principle. 在 Java 8 中,還有第三種方法來編寫可能無法返回值的方法。`Optional<T>` 類表示一個不可變的容器,它可以包含一個非空的 T 引用,也可以什么都不包含。不包含任何內容的 Optional 被稱為空。一個值被認為存在于一個非空的 Optional 中。Optional 的本質上是一個不可變的集合,它最多可以容納一個元素。`Optional<T>` 不實現 `Collection<T>`,但原則上可以。 A method that conceptually returns a T but may be unable to do so under certain circumstances can instead be declared to return an `Optional<T>`. This allows the method to return an empty result to indicate that it couldn’t return a valid result. An Optional-returning method is more flexible and easier to use than one that throws an exception, and it is less error-prone than one that returns null. 理論上應返回 T,但在某些情況下可能無法返回 T 的方法可以將返回值聲明為 `Optional<T>`。這允許該方法返回一個空結果來表明它不能返回有效的結果。具備 Optional 返回值的方法比拋出異常的方法更靈活、更容易使用,并且比返回 null 的方法更不容易出錯。 In Item 30, we showed this method to calculate the maximum value in a collection, according to its elements’ natural order. 在 [Item-30](/Chapter-5/Chapter-5-Item-30-Favor-generic-methods.md) 中,我們展示了根據集合元素的自然順序計算集合最大值的方法。 ``` // Returns maximum value in collection - throws exception if empty public static <E extends Comparable<E>> E max(Collection<E> c) { if (c.isEmpty()) throw new IllegalArgumentException("Empty collection"); E result = null; for (E e : c) if (result == null || e.compareTo(result) > 0) result = Objects.requireNonNull(e); return result; } ``` This method throws an IllegalArgumentException if the given collection is empty. We mentioned in Item 30 that a better alternative would be to return `Optional<E>`. Here’s how the method looks when it is modified to do so: 如果給定集合為空,此方法將拋出 IllegalArgumentException。我們在 [Item-30](/Chapter-5/Chapter-5-Item-30-Favor-generic-methods.md) 中提到,更好的替代方法是返回 `Optional<E>`。 ``` // Returns maximum value in collection as an Optional<E> public static <E extends Comparable<E>> Optional<E> max(Collection<E> c) { if (c.isEmpty()) return Optional.empty(); E result = null; for (E e : c) if (result == null || e.compareTo(result) > 0) result = Objects.requireNonNull(e); return Optional.of(result); } ``` As you can see, it is straightforward to return an optional. All you have to do is to create the optional with the appropriate static factory. In this program, we use two: Optional.empty() returns an empty optional, and Optional.of(value) returns an optional containing the given non-null value. It is a programming error to pass null to Optional.of(value). If you do this, the method responds by throwing a NullPointerException. The Optional.ofNullable(value) method accepts a possibly null value and returns an empty optional if null is passed in. **Never return a null value from an Optional-returning method:** it defeats the entire purpose of the facility. 如你所見,返回一個 Optional 是很簡單的。你所要做的就是使用適當的靜態工廠創建。在這個程序中,我們使用了兩個靜態工廠:`Optional.empty()` 返回一個空的 Optional,`Optional.of(value)` 返回一個包含給定非空值的可選值。將 null 傳遞給 `Optional.of(value)` 是一個編程錯誤。如果你這樣做,該方法將通過拋出 NullPointerException 來響應。`Optional.ofNullable(value)` 方法接受一個可能為空的值,如果傳入 null,則返回一個空的 Optional。**永遠不要從具備 Optional 返回值的方法返回空值:** 它違背了這個功能的設計初衷。 Many terminal operations on streams return optionals. If we rewrite the max method to use a stream, Stream’s max operation does the work of generating an optional for us (though we do have to pass in an explicit comparator): 許多流上的 Terminal 操作返回 Optional。如果我們使用一個流來重寫 max 方法,那么流版本的 max 操作會為我們生成一個 Optional(盡管我們必須傳遞一個顯式的 comparator): ``` // Returns max val in collection as Optional<E> - uses stream public static <E extends Comparable<E>> Optional<E> max(Collection<E> c) { return c.stream().max(Comparator.naturalOrder()); } ``` So how do you choose to return an optional instead of returning a null or throwing an exception? Optionals are similar in spirit to checked exceptions (Item 71), in that they force the user of an API to confront the fact that there may be no value returned. Throwing an unchecked exception or returning a null allows the user to ignore this eventuality, with potentially dire consequences. However, throwing a checked exception requires additional boilerplate code in the client. 那么,如何選擇是返回 Optional 而不是返回 null 或拋出異常呢?Optional 在本質上類似于已檢查異常([Item-71](/Chapter-10/Chapter-10-Item-71-Avoid-unnecessary-use-of-checked-exceptions.md)),因為它們迫使 API 的用戶面對可能沒有返回值的事實。拋出未檢查的異常或返回 null 允許用戶忽略這種可能性,從而帶來潛在的可怕后果。但是,拋出一個已檢查的異常需要在客戶端中添加額外的樣板代碼。 If a method returns an optional, the client gets to choose what action to take if the method can’t return a value. You can specify a default value: 如果一個方法返回一個 Optional,客戶端可以選擇如果該方法不能返回值該采取什么操作。你可以指定一個默認值: ``` // Using an optional to provide a chosen default value String lastWordInLexicon = max(words).orElse("No words..."); ``` or you can throw any exception that is appropriate. Note that we pass in an exception factory rather than an actual exception. This avoids the expense of creating the exception unless it will actually be thrown: 或者你可以拋出任何適當的異常。注意,我們傳遞的是異常工廠,而不是實際的異常。這避免了創建異常的開銷,除非它實際被拋出: ``` // Using an optional to throw a chosen exception Toy myToy = max(toys).orElseThrow(TemperTantrumException::new); ``` If you can prove that an optional is nonempty, you can get the value from the optional without specifying an action to take if the optional is empty, but if you’re wrong, your code will throw a NoSuchElementException: 如果你能證明一個 Optional 非空,你可以從 Optional 獲取值,而不需要指定一個操作來執行,如果 Optional 是空的,但是如果你錯了,你的代碼會拋出一個 NoSuchElementException: ``` // Using optional when you know there’s a return value Element lastNobleGas = max(Elements.NOBLE_GASES).get(); ``` Occasionally you may be faced with a situation where it’s expensive to get the default value, and you want to avoid that cost unless it’s necessary. For these situations, Optional provides a method that takes a `Supplier<T>` and invokes it only when necessary. This method is called orElseGet, but perhaps it should have been called orElseCompute because it is closely related to the three Map methods whose names begin with compute. There are several Optional methods for dealing with more specialized use cases: filter, map, flatMap, and ifPresent. In Java 9, two more of these methods were added: or and ifPresentOrElse. If the basic methods described above aren’t a good match for your use case, look at the documentation for these more advanced methods and see if they do the job. 有時候,你可能會遇到這樣一種情況:獲取默認值的代價很高,除非必要,否則你希望避免這種代價。對于這些情況,Optional 提供了一個方法,該方法接受 `Supplier<T>`,并僅在必要時調用它。這個方法被稱為 orElseGet,但是它可能應該被稱為 orElseCompute,因為它與以 compute 開頭的三個 Map 方法密切相關。有幾個 Optional 的方法來處理更特殊的用例:filter、map、flatMap 和 ifPresent。在 Java 9 中,又添加了兩個這樣的方法:or 和 ifPresentOrElse。如果上面描述的基本方法與你的實例不太匹配,請查看這些更高級方法的文檔,確認它們是否能夠完成任務。 In case none of these methods meets your needs, Optional provides the isPresent() method, which may be viewed as a safety valve. It returns true if the optional contains a value, false if it’s empty. You can use this method to perform any processing you like on an optional result, but make sure to use it wisely. Many uses of isPresent can profitably be replaced by one of the methods mentioned above. The resulting code will typically be shorter, clearer, and more idiomatic. 如果這些方法都不能滿足你的需要,Optional 提供 `isPresent()` 方法,可以將其視為安全閥。如果 Optional 包含值,則返回 true;如果為空,則返回 false。你可以使用此方法對 Optional 結果執行任何你希望進行的處理,但請確保明智地使用它。`isPresent()` 的許多用途都可以被上面提到的方法所替代,如此生成的代碼可以更短、更清晰、更符合習慣。 For example, consider this code snippet, which prints the process ID of the parent of a process, or N/A if the process has no parent. The snippet uses the ProcessHandle class, introduced in Java 9: 例如,考慮這段代碼,它打印一個進程的父進程的 ID,如果進程沒有父進程,則打印 N/A。該代碼段使用了在 Java 9 中引入的 ProcessHandle 類: ``` Optional<ProcessHandle> parentProcess = ph.parent(); System.out.println("Parent PID: " + (parentProcess.isPresent() ? String.valueOf(parentProcess.get().pid()) : "N/A")); ``` The code snippet above can be replaced by this one, which uses Optional’s map function: 上面的代碼片段可以替換為如下形式,它使用了 Optional 的 map 函數: ``` System.out.println("Parent PID: " + ph.parent().map(h -> String.valueOf(h.pid())).orElse("N/A")); ``` When programming with streams, it is not uncommon to find yourself with a `Stream<Optional<T>>` and to require a `Stream<T>` containing all the elements in the nonempty optionals in order to proceed. If you’re using Java 8, here’s how to bridge the gap: 當使用流進行編程時,通常會發現你經常使用 `Stream<Optional<T>>`,并且需要一個 `Stream<T>`,其中包含非空 Optional 中的所有元素,以便繼續。如果你正在使用 Java 8,下面的語句演示了如何彌補這個不足: ``` streamOfOptionals.filter(Optional::isPresent).map(Optional::get) ``` In Java 9, Optional was outfitted with a stream() method. This method is an adapter that turns an Optional into a Stream containing an element if one is present in the optional, or none if it is empty. In conjunction with Stream’s flatMap method (Item 45), this method provides a concise replacement for the code snippet above: 在 Java 9 中,Optional 配備了一個 `stream()` 方法。這個方法是一個適配器,它將一個 Optional 元素轉換成一個包含元素的流(如果一個元素出現在 Optional 元素中),如果一個元素是空的,則一個元素都沒有。與 Stream 的 flatMap 方法([Item-45](/Chapter-7/Chapter-7-Item-45-Use-streams-judiciously.md))相結合,這個方法為上面的代碼段提供了一個簡潔的替換版本: ``` streamOfOptionals..flatMap(Optional::stream) ``` Not all return types benefit from the optional treatment. **Container types, including collections, maps, streams, arrays, and optionals should not be wrapped in optionals.** Rather than returning an empty `Optional<List<T>>`, you should simply return an empty `List<T>` (Item 54). Returning the empty container will eliminate the need for client code to process an optional. The ProcessHandle class does have the arguments method, which returns `Optional<String[]>`, but this method should be regarded as an anomaly that is not to be emulated. 并不是所有的返回類型都能從 Optional 處理中獲益。**容器類型,包括集合、Map、流、數組和 Optional,不應該封裝在 Optional 中。** 你應該簡單的返回一個空的 `List<T>`,而不是一個空的 `Optional<List<T>>`([Item-54](/Chapter-8/Chapter-8-Item-54-Return-empty-collections-or-arrays-not-nulls.md))。返回空容器將消除客戶端代碼處理 Optional 容器的需要。ProcessHandle 類確實有 arguments 方法,它返回 `Optional<String[]>`,但是這個方法應該被視為一種特例,不應該被仿效。 So when should you declare a method to return `Optional<T>` rather than T? As a rule, **you should declare a method to return `Optional<T>` if it might not be able to return a result and clients will have to perform special processing if no result is returned.** That said, returning an `Optional<T>` is not without cost. An Optional is an object that has to be allocated and initialized, and reading the value out of the optional requires an extra indirection. This makes optionals inappropriate for use in some performance-critical situations. Whether a particular method falls into this category can only be determined by careful measurement (Item 67). 那么,什么時候應該聲明一個方法來返回 `Optional<T>` 而不是 T 呢?作為規則,**你應該聲明一個方法來返回 `Optional<T>`(如果它可能無法返回結果),如果沒有返回結果,客戶端將不得不執行特殊處理。** 也就是說,返回 `Optional<T>` 并不是沒有代價的。Optional 對象必須分配和初始化,從 Optional 對象中讀取值需要額外的間接操作。這使得 Optional 不適合在某些性能關鍵的情況下使用。某一特定方法是否屬于這一情況只能通過仔細衡量來確定([Item-67](/Chapter-9/Chapter-9-Item-67-Optimize-judiciously.md))。 Returning an optional that contains a boxed primitive type is prohibitively expensive compared to returning a primitive type because the optional has two levels of boxing instead of zero. Therefore, the library designers saw fit to provide analogues of `Optional<T>` for the primitive types int, long, and double. These optional types are OptionalInt, OptionalLong, and OptionalDouble. They contain most, but not all, of the methods on `Optional<T>`. Therefore, **you should never return an optional of a boxed primitive type,** with the possible exception of the “minor primitive types,” Boolean, Byte, Character, Short, and Float. 與返回基本數據類型相比,返回包含包裝類的 Optional 類型的代價高得驚人,因為 Optional 類型有兩個裝箱級別,而不是零。因此,庫設計人員認為應該為基本類型 int、long 和 double 提供類似的 `Optional<T>`。這些可選類型是 OptionalInt、OptionalLong 和 OptionalDouble。它們包含 `Optional<T>` 上的大多數方法,但不是所有方法。因此,**永遠不應該返包裝類的 Optional**,可能除了「次基本數據類型」,如 Boolean、Byte、Character、Short 和 Float 之外。 Thus far, we have discussed returning optionals and processing them after they are returned. We have not discussed other possible uses, and that is because most other uses of optionals are suspect. For example, you should never use optionals as map values. If you do, you have two ways of expressing a key’s logical absence from the map: either the key can be absent from the map, or it can be present and map to an empty optional. This represents needless complexity with great potential for confusion and errors. More generally, **it is almost never appropriate to use an optional as a key, value, or element in a collection or array.** 到目前為止,我們已經討論了返回 Optional 并在返回后如何處理它們。我們還沒有討論其他可能的用法,這是因為大多數其他 Optional 用法都是值得疑的。例如,永遠不要將 Optional 用作 Map 的值。如果這樣做,則有兩種方法可以表示鍵在 Map 中邏輯上的缺失:鍵可以不在 Map 中,也可以存在并映射到空的 Optional。這代表了不必要的復雜性,很有可能導致混淆和錯誤。更一般地說,**在集合或數組中使用 Optional 作為鍵、值或元素幾乎都是不合適的。** This leaves a big question unanswered. Is it ever appropriate to store an optional in an instance field? Often it’s a “bad smell”: it suggests that perhaps you should have a subclass containing the optional fields. But sometimes it may be justified. Consider the case of our NutritionFacts class in Item 2. A NutritionFacts instance contains many fields that are not required. You can’t have a subclass for every possible combination of these fields. Also, the fields have primitive types, which make it awkward to express absence directly. The best API for NutritionFacts would return an optional from the getter for each optional field, so it makes good sense to simply store those optionals as fields in the object. 這留下了一個懸而未決的大問題。在實例字段中存儲 Optional 字段是否合適?通常這是一種「代碼中的不良習慣」:建議你可能應該有一個包含 Optional 字段的子類。但有時這可能是合理的。考慮 [Item-2](/Chapter-2/Chapter-2-Item-2-Consider-a-builder-when-faced-with-many-constructor-parameters.md) 中的 NutritionFacts 類的情況。NutritionFacts 實例包含許多不需要的字段。不能為這些字段的所有可能組合提供子類。此外,字段具有原始類型,這使得直接表示缺少非常困難。對于 NutritionFacts 最好的 API 將為每個可選字段從 getter 返回一個 Optional,因此將這些 Optional 作為字段存儲在對象中是很有意義的。 In summary, if you find yourself writing a method that can’t always return a value and you believe it is important that users of the method consider this possibility every time they call it, then you should probably return an optional. You should, however, be aware that there are real performance consequences associated with returning optionals; for performance-critical methods, it may be better to return a null or throw an exception. Finally, you should rarely use an optional in any other capacity than as a return value. 總之,如果你發現自己編寫的方法不能總是返回確定值,并且你認為該方法的用戶在每次調用時應該考慮這種可能性,那么你可能應該讓方法返回一個 Optional。但是,你應該意識到,返回 Optional 會帶來實際的性能后果;對于性能關鍵的方法,最好返回 null 或拋出異常。最后,除了作為返回值之外,你幾乎不應該以任何其他方式使用 Optional。 --- **[Back to contents of the chapter(返回章節目錄)](/Chapter-8/Chapter-8-Introduction.md)** - **Previous Item(上一條目):[Item 54: Return empty collections or arrays, not nulls(返回空集合或數組,而不是 null)](/Chapter-8/Chapter-8-Item-54-Return-empty-collections-or-arrays-not-nulls.md)** - **Next Item(下一條目):[Item 56: Write doc comments for all exposed API elements(為所有公開的 API 元素編寫文檔注釋)](/Chapter-8/Chapter-8-Item-56-Write-doc-comments-for-all-exposed-API-elements.md)**
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看