<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、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                ## 泛型方法 到目前為止,我們已經研究了參數化整個類。其實還可以參數化類中的方法。類本身可能是泛型的,也可能不是,不過這與它的方法是否是泛型的并沒有什么關系。 泛型方法獨立于類而改變方法。作為準則,請“盡可能”使用泛型方法。通常將單個方法泛型化要比將整個類泛型化更清晰易懂。 如果方法是 **static** 的,則無法訪問該類的泛型類型參數,因此,如果使用了泛型類型參數,則它必須是泛型方法。 要定義泛型方法,請將泛型參數列表放置在返回值之前,如下所示: ```java // generics/GenericMethods.java public class GenericMethods { public <T> void f(T x) { System.out.println(x.getClass().getName()); } public static void main(String[] args) { GenericMethods gm = new GenericMethods(); gm.f(""); gm.f(1); gm.f(1.0); gm.f(1.0F); gm.f('c'); gm.f(gm); } } /* Output: java.lang.String java.lang.Integer java.lang.Double java.lang.Float java.lang.Character GenericMethods */ ``` 盡管可以同時對類及其方法進行參數化,但這里未將 **GenericMethods** 類參數化。只有方法 `f()` 具有類型參數,該參數由方法返回類型之前的參數列表指示。 對于泛型類,必須在實例化該類時指定類型參數。使用泛型方法時,通常不需要指定參數類型,因為編譯器會找出這些類型。 這稱為 *類型參數推斷*。因此,對 `f()` 的調用看起來像普通的方法調用,并且 `f()` 看起來像被重載了無數次一樣。它甚至會接受 **GenericMethods** 類型的參數。 如果使用基本類型調用 `f()` ,自動裝箱就開始起作用,自動將基本類型包裝在它們對應的包裝類型中。 <!-- Varargs and Generic Methods --> ### 變長參數和泛型方法 泛型方法和變長參數列表可以很好地共存: ```java // generics/GenericVarargs.java import java.util.ArrayList; import java.util.List; public class GenericVarargs { @SafeVarargs public static <T> List<T> makeList(T... args) { List<T> result = new ArrayList<>(); for (T item : args) result.add(item); return result; } public static void main(String[] args) { List<String> ls = makeList("A"); System.out.println(ls); ls = makeList("A", "B", "C"); System.out.println(ls); ls = makeList( "ABCDEFFHIJKLMNOPQRSTUVWXYZ".split("")); System.out.println(ls); } } /* Output: [A] [A, B, C] [A, B, C, D, E, F, F, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z] */ ``` 此處顯示的 `makeList()` 方法產生的功能與標準庫的 `java.util.Arrays.asList()` 方法相同。 `@SafeVarargs` 注解保證我們不會對變長參數列表進行任何修改,這是正確的,因為我們只從中讀取。如果沒有此注解,編譯器將無法知道這些并會發出警告。 <!-- A General-Purpose Supplier --> ### 一個泛型的 Supplier 這是一個為任意具有無參構造方法的類生成 **Supplier** 的類。為了減少鍵入,它還包括一個用于生成 **BasicSupplier** 的泛型方法: ```java // onjava/BasicSupplier.java // Supplier from a class with a no-arg constructor package onjava; import java.util.function.Supplier; public class BasicSupplier<T> implements Supplier<T> { private Class<T> type; public BasicSupplier(Class<T> type) { this.type = type; } @Override public T get() { try { // Assumes type is a public class: return type.newInstance(); } catch (InstantiationException | IllegalAccessException e) { throw new RuntimeException(e); } } // Produce a default Supplier from a type token: public static <T> Supplier<T> create(Class<T> type) { return new BasicSupplier<>(type); } } ``` 此類提供了產生以下對象的基本實現: 1. 是 **public** 的。 因為 **BasicSupplier** 在單獨的包中,所以相關的類必須具有 **public** 權限,而不僅僅是包級訪問權限。 2. 具有無參構造方法。要創建一個這樣的 **BasicSupplier** 對象,請調用 `create()` 方法,并將要生成類型的類型令牌傳遞給它。通用的 `create()` 方法提供了 `BasicSupplier.create(MyType.class)` 這種較簡潔的語法來代替較笨拙的 `new BasicSupplier <MyType>(MyType.class)`。 例如,這是一個具有無參構造方法的簡單類: ```java // generics/CountedObject.java public class CountedObject { private static long counter = 0; private final long id = counter++; public long id() { return id; } @Override public String toString() { return "CountedObject " + id; } } ``` **CountedObject** 類可以跟蹤自身創建了多少個實例,并通過 `toString()` 報告這些實例的數量。 **BasicSupplier** 可以輕松地為 **CountedObject** 創建 **Supplier**: ```java // generics/BasicSupplierDemo.java import onjava.BasicSupplier; import java.util.stream.Stream; public class BasicSupplierDemo { public static void main(String[] args) { Stream.generate( BasicSupplier.create(CountedObject.class)) .limit(5) .forEach(System.out::println); } } /* Output: CountedObject 0 CountedObject 1 CountedObject 2 CountedObject 3 CountedObject 4 */ ``` 泛型方法減少了產生 **Supplier** 對象所需的代碼量。 Java 泛型強制傳遞 **Class** 對象,以便在 `create()` 方法中將其用于類型推斷。 <!-- Simplifying Tuple Use --> ### 簡化元組的使用 使用類型參數推斷和靜態導入,我們將把早期的元組重寫為更通用的庫。在這里,我們使用重載的靜態方法創建元組: ```java // onjava/Tuple.java // Tuple library using type argument inference package onjava; public class Tuple { public static <A, B> Tuple2<A, B> tuple(A a, B b) { return new Tuple2<>(a, b); } public static <A, B, C> Tuple3<A, B, C> tuple(A a, B b, C c) { return new Tuple3<>(a, b, c); } public static <A, B, C, D> Tuple4<A, B, C, D> tuple(A a, B b, C c, D d) { return new Tuple4<>(a, b, c, d); } public static <A, B, C, D, E> Tuple5<A, B, C, D, E> tuple(A a, B b, C c, D d, E e) { return new Tuple5<>(a, b, c, d, e); } } ``` 我們修改 **TupleTest.java** 來測試 **Tuple.java** : ```java // generics/TupleTest2.java import onjava.Tuple2; import onjava.Tuple3; import onjava.Tuple4; import onjava.Tuple5; import static onjava.Tuple.tuple; public class TupleTest2 { static Tuple2<String, Integer> f() { return tuple("hi", 47); } static Tuple2 f2() { return tuple("hi", 47); } static Tuple3<Amphibian, String, Integer> g() { return tuple(new Amphibian(), "hi", 47); } static Tuple4<Vehicle, Amphibian, String, Integer> h() { return tuple( new Vehicle(), new Amphibian(), "hi", 47); } static Tuple5<Vehicle, Amphibian, String, Integer, Double> k() { return tuple(new Vehicle(), new Amphibian(), "hi", 47, 11.1); } public static void main(String[] args) { Tuple2<String, Integer> ttsi = f(); System.out.println(ttsi); System.out.println(f2()); System.out.println(g()); System.out.println(h()); System.out.println(k()); } } /* Output: (hi, 47) (hi, 47) (Amphibian@14ae5a5, hi, 47) (Vehicle@135fbaa4, Amphibian@45ee12a7, hi, 47) (Vehicle@4b67cf4d, Amphibian@7ea987ac, hi, 47, 11.1) */ ``` 請注意,`f()` 返回一個參數化的 **Tuple2** 對象,而 `f2()` 返回一個未參數化的 **Tuple2** 對象。編譯器不會在這里警告 `f2()` ,因為返回值未以參數化方式使用。從某種意義上說,它被“向上轉型”為一個未參數化的 **Tuple2** 。 但是,如果嘗試將 `f2()` 的結果放入到參數化的 **Tuple2** 中,則編譯器將發出警告。 <!-- A Set Utility --> ### 一個 Set 工具 對于泛型方法的另一個示例,請考慮由 **Set** 表示的數學關系。這些被方便地定義為可用于所有不同類型的泛型方法: ```java // onjava/Sets.java package onjava; import java.util.HashSet; import java.util.Set; public class Sets { public static <T> Set<T> union(Set<T> a, Set<T> b) { Set<T> result = new HashSet<>(a); result.addAll(b); return result; } public static <T> Set<T> intersection(Set<T> a, Set<T> b) { Set<T> result = new HashSet<>(a); result.retainAll(b); return result; } // Subtract subset from superset: public static <T> Set<T> difference(Set<T> superset, Set<T> subset) { Set<T> result = new HashSet<>(superset); result.removeAll(subset); return result; } // Reflexive--everything not in the intersection: public static <T> Set<T> complement(Set<T> a, Set<T> b) { return difference(union(a, b), intersection(a, b)); } } ``` 前三個方法通過將第一個參數的引用復制到新的 **HashSet** 對象中來復制第一個參數,因此不會直接修改參數集合。因此,返回值是一個新的 **Set** 對象。 這四種方法代表數學集合操作: `union()` 返回一個包含兩個參數并集的 **Set** , `intersection()` 返回一個包含兩個參數集合交集的 **Set** , `difference()` 從 **superset** 中減去 **subset** 的元素 ,而 `complement()` 返回所有不在交集中的元素的 **Set**。作為顯示這些方法效果的簡單示例的一部分,下面是一個包含不同水彩名稱的 **enum** : ```java // generics/watercolors/Watercolors.java package watercolors; public enum Watercolors { ZINC, LEMON_YELLOW, MEDIUM_YELLOW, DEEP_YELLOW, ORANGE, BRILLIANT_RED, CRIMSON, MAGENTA, ROSE_MADDER, VIOLET, CERULEAN_BLUE_HUE, PHTHALO_BLUE, ULTRAMARINE, COBALT_BLUE_HUE, PERMANENT_GREEN, VIRIDIAN_HUE, SAP_GREEN, YELLOW_OCHRE, BURNT_SIENNA, RAW_UMBER, BURNT_UMBER, PAYNES_GRAY, IVORY_BLACK } ``` 為了方便起見(不必全限定所有名稱),將其靜態導入到以下示例中。本示例使用 **EnumSet** 輕松從 **enum** 中創建 **Set** 。(可以在[第二十二章 枚舉](book/22-Enumerations.md)一章中了解有關 **EnumSet** 的更多信息。)在這里,靜態方法 `EnumSet.range()` 要求提供所要在結果 **Set** 中創建的元素范圍的第一個和最后一個元素: ```java // generics/WatercolorSets.java import watercolors.*; import java.util.EnumSet; import java.util.Set; import static watercolors.Watercolors.*; import static onjava.Sets.*; public class WatercolorSets { public static void main(String[] args) { Set<Watercolors> set1 = EnumSet.range(BRILLIANT_RED, VIRIDIAN_HUE); Set<Watercolors> set2 = EnumSet.range(CERULEAN_BLUE_HUE, BURNT_UMBER); System.out.println("set1: " + set1); System.out.println("set2: " + set2); System.out.println( "union(set1, set2): " + union(set1, set2)); Set<Watercolors> subset = intersection(set1, set2); System.out.println( "intersection(set1, set2): " + subset); System.out.println("difference(set1, subset): " + difference(set1, subset)); System.out.println("difference(set2, subset): " + difference(set2, subset)); System.out.println("complement(set1, set2): " + complement(set1, set2)); } } /* Output: set1: [BRILLIANT_RED, CRIMSON, MAGENTA, ROSE_MADDER, VIOLET, CERULEAN_BLUE_HUE, PHTHALO_BLUE, ULTRAMARINE, COBALT_BLUE_HUE, PERMANENT_GREEN, VIRIDIAN_HUE] set2: [CERULEAN_BLUE_HUE, PHTHALO_BLUE, ULTRAMARINE, COBALT_BLUE_HUE, PERMANENT_GREEN, VIRIDIAN_HUE, SAP_GREEN, YELLOW_OCHRE, BURNT_SIENNA, RAW_UMBER, BURNT_UMBER] union(set1, set2): [BURNT_SIENNA, BRILLIANT_RED, YELLOW_OCHRE, MAGENTA, SAP_GREEN, CERULEAN_BLUE_HUE, ULTRAMARINE, VIRIDIAN_HUE, VIOLET, RAW_UMBER, ROSE_MADDER, PERMANENT_GREEN, BURNT_UMBER, PHTHALO_BLUE, CRIMSON, COBALT_BLUE_HUE] intersection(set1, set2): [PERMANENT_GREEN, CERULEAN_BLUE_HUE, ULTRAMARINE, VIRIDIAN_HUE, PHTHALO_BLUE, COBALT_BLUE_HUE] difference(set1, subset): [BRILLIANT_RED, MAGENTA, VIOLET, CRIMSON, ROSE_MADDER] difference(set2, subset): [BURNT_SIENNA, YELLOW_OCHRE, BURNT_UMBER, SAP_GREEN, RAW_UMBER] complement(set1, set2): [BURNT_SIENNA, BRILLIANT_RED, YELLOW_OCHRE, MAGENTA, SAP_GREEN, VIOLET, RAW_UMBER, ROSE_MADDER, BURNT_UMBER, CRIMSON] */ ``` 接下來的例子使用 `Sets.difference()` 方法來展示 **java.util** 包中各種 **Collection** 和 **Map** 類之間的方法差異: ```java // onjava/CollectionMethodDifferences.java // {java onjava.CollectionMethodDifferences} package onjava; import java.lang.reflect.Method; import java.util.*; import java.util.stream.Collectors; public class CollectionMethodDifferences { static Set<String> methodSet(Class<?> type) { return Arrays.stream(type.getMethods()) .map(Method::getName) .collect(Collectors.toCollection(TreeSet::new)); } static void interfaces(Class<?> type) { System.out.print("Interfaces in " + type.getSimpleName() + ": "); System.out.println( Arrays.stream(type.getInterfaces()) .map(Class::getSimpleName) .collect(Collectors.toList())); } static Set<String> object = methodSet(Object.class); static { object.add("clone"); } static void difference(Class<?> superset, Class<?> subset) { System.out.print(superset.getSimpleName() + " extends " + subset.getSimpleName() + ", adds: "); Set<String> comp = Sets.difference( methodSet(superset), methodSet(subset)); comp.removeAll(object); // Ignore 'Object' methods System.out.println(comp); interfaces(superset); } public static void main(String[] args) { System.out.println("Collection: " + methodSet(Collection.class)); interfaces(Collection.class); difference(Set.class, Collection.class); difference(HashSet.class, Set.class); difference(LinkedHashSet.class, HashSet.class); difference(TreeSet.class, Set.class); difference(List.class, Collection.class); difference(ArrayList.class, List.class); difference(LinkedList.class, List.class); difference(Queue.class, Collection.class); difference(PriorityQueue.class, Queue.class); System.out.println("Map: " + methodSet(Map.class)); difference(HashMap.class, Map.class); difference(LinkedHashMap.class, HashMap.class); difference(SortedMap.class, Map.class); difference(TreeMap.class, Map.class); } } /* Output: Collection: [add, addAll, clear, contains, containsAll, equals, forEach, hashCode, isEmpty, iterator, parallelStream, remove, removeAll, removeIf, retainAll, size, spliterator, stream, toArray] Interfaces in Collection: [Iterable] Set extends Collection, adds: [] Interfaces in Set: [Collection] HashSet extends Set, adds: [] Interfaces in HashSet: [Set, Cloneable, Serializable] LinkedHashSet extends HashSet, adds: [] Interfaces in LinkedHashSet: [Set, Cloneable, Serializable] TreeSet extends Set, adds: [headSet, descendingIterator, descendingSet, pollLast, subSet, floor, tailSet, ceiling, last, lower, comparator, pollFirst, first, higher] Interfaces in TreeSet: [NavigableSet, Cloneable, Serializable] List extends Collection, adds: [replaceAll, get, indexOf, subList, set, sort, lastIndexOf, listIterator] Interfaces in List: [Collection] ArrayList extends List, adds: [trimToSize, ensureCapacity] Interfaces in ArrayList: [List, RandomAccess, Cloneable, Serializable] LinkedList extends List, adds: [offerFirst, poll, getLast, offer, getFirst, removeFirst, element, removeLastOccurrence, peekFirst, peekLast, push, pollFirst, removeFirstOccurrence, descendingIterator, pollLast, removeLast, pop, addLast, peek, offerLast, addFirst] Interfaces in LinkedList: [List, Deque, Cloneable, Serializable] Queue extends Collection, adds: [poll, peek, offer, element] Interfaces in Queue: [Collection] PriorityQueue extends Queue, adds: [comparator] Interfaces in PriorityQueue: [Serializable] Map: [clear, compute, computeIfAbsent, computeIfPresent, containsKey, containsValue, entrySet, equals, forEach, get, getOrDefault, hashCode, isEmpty, keySet, merge, put, putAll, putIfAbsent, remove, replace, replaceAll, size, values] HashMap extends Map, adds: [] Interfaces in HashMap: [Map, Cloneable, Serializable] LinkedHashMap extends HashMap, adds: [] Interfaces in LinkedHashMap: [Map] SortedMap extends Map, adds: [lastKey, subMap, comparator, firstKey, headMap, tailMap] Interfaces in SortedMap: [Map] TreeMap extends Map, adds: [descendingKeySet, navigableKeySet, higherEntry, higherKey, floorKey, subMap, ceilingKey, pollLastEntry, firstKey, lowerKey, headMap, tailMap, lowerEntry, ceilingEntry, descendingMap, pollFirstEntry, lastKey, firstEntry, floorEntry, comparator, lastEntry] Interfaces in TreeMap: [NavigableMap, Cloneable, Serializable] */ ``` 在第十二章 [集合的本章小結](book/12-Collections.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>

                              哎呀哎呀视频在线观看