<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>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                ## 對缺乏潛在類型機制的補償 盡管 Java 不直接支持潛在類型機制,但是這并不意味著泛型代碼不能在不同的類型層次結構之間應用。也就是說,我們仍舊可以創建真正的泛型代碼,但是這需要付出一些額外的努力。 ### 反射 可以使用的一種方式是反射,下面的 `perform()` 方法就是用了潛在類型機制: ```java // generics/LatentReflection.java // Using reflection for latent typing import java.lang.reflect.*; // Does not implement Performs: class Mime { public void walkAgainstTheWind() {} public void sit() { System.out.println("Pretending to sit"); } public void pushInvisibleWalls() {} @Override public String toString() { return "Mime"; } } // Does not implement Performs: class SmartDog { public void speak() { System.out.println("Woof!"); } public void sit() { System.out.println("Sitting"); } public void reproduce() {} } class CommunicateReflectively { public static void perform(Object speaker) { Class<?> spkr = speaker.getClass(); try { try { Method speak = spkr.getMethod("speak"); speak.invoke(speaker); } catch(NoSuchMethodException e) { System.out.println(speaker + " cannot speak"); } try { Method sit = spkr.getMethod("sit"); sit.invoke(speaker); } catch(NoSuchMethodException e) { System.out.println(speaker + " cannot sit"); } } catch(SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { throw new RuntimeException(speaker.toString(), e); } } } public class LatentReflection { public static void main(String[] args) { CommunicateReflectively.perform(new SmartDog()); CommunicateReflectively.perform(new Robot()); CommunicateReflectively.perform(new Mime()); } } /* Output: Woof! Sitting Click! Clank! Mime cannot speak Pretending to sit */ ``` 上例中,這些類完全是彼此分離的,沒有任何公共基類(除了 **Object** )或接口。通過反射, `CommunicateReflectively.perform()` 能夠動態地確定所需要的方法是否可用并調用它們。它甚至能夠處理 **Mime** 只具有一個必需的方法這一事實,并能夠部分實現其目標。 ### 將一個方法應用于序列 反射提供了一些有用的可能性,但是它將所有的類型檢查都轉移到了運行時,因此在許多情況下并不是我們所希望的。如果能夠實現編譯期類型檢查,這通常會更符合要求。但是有可能實現編譯期類型檢查和潛在類型機制嗎? 讓我們看一個說明這個問題的示例。假設想要創建一個 `apply()` 方法,它能夠將任何方法應用于某個序列中的所有對象。這種情況下使用接口不適合,因為你想要將任何方法應用于一個對象集合,而接口不可能描述任何方法。如何用 Java 來實現這個需求呢? 最初,我們可以用反射來解決這個問題,由于有了 Java 的可變參數,這種方式被證明是相當優雅的: ```java // generics/Apply.java import java.lang.reflect.*; import java.util.*; public class Apply { public static <T, S extends Iterable<T>> void apply(S seq, Method f, Object... args) { try { for(T t: seq) f.invoke(t, args); } catch(IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { // Failures are programmer errors throw new RuntimeException(e); } } } ``` 在 **Apply.java** 中,異常被轉換為 **RuntimeException** ,因為沒有多少辦法可以從這種異常中恢復——在這種情況下,它們實際上代表著程序員的錯誤。 為什么我們不只使用 Java 8 方法參考(稍后顯示)而不是反射方法 **f** ? 注意,`invoke()` 和 `apply()` 的優點是它們可以接受任意數量的參數。 在某些情況下,靈活性可能至關重要。 為了測試 **Apply** ,我們首先創建一個 **Shape** 類: ```java // generics/Shape.java public class Shape { private static long counter = 0; private final long id = counter++; @Override public String toString() { return getClass().getSimpleName() + " " + id; } public void rotate() { System.out.println(this + " rotate"); } public void resize(int newSize) { System.out.println(this + " resize " + newSize); } } ``` 被一個子類 **Square** 繼承: ```java // generics/Square.java public class Square extends Shape {} ``` 通過這些,我們可以測試 **Apply**: ```java // generics/ApplyTest.java import java.util.*; import java.util.function.*; import onjava.*; public class ApplyTest { public static void main(String[] args) throws Exception { List<Shape> shapes = Suppliers.create(ArrayList::new, Shape::new, 3); Apply.apply(shapes, Shape.class.getMethod("rotate")); Apply.apply(shapes, Shape.class.getMethod("resize", int.class), 7); List<Square> squares = Suppliers.create(ArrayList::new, Square::new, 3); Apply.apply(squares, Shape.class.getMethod("rotate")); Apply.apply(squares, Shape.class.getMethod("resize", int.class), 7); Apply.apply(new FilledList<>(Shape::new, 3), Shape.class.getMethod("rotate")); Apply.apply(new FilledList<>(Square::new, 3), Shape.class.getMethod("rotate")); SimpleQueue<Shape> shapeQ = Suppliers.fill( new SimpleQueue<>(), SimpleQueue::add, Shape::new, 3); Suppliers.fill(shapeQ, SimpleQueue::add, Square::new, 3); Apply.apply(shapeQ, Shape.class.getMethod("rotate")); } } /* Output: Shape 0 rotate Shape 1 rotate Shape 2 rotate Shape 0 resize 7 Shape 1 resize 7 Shape 2 resize 7 Square 3 rotate Square 4 rotate Square 5 rotate Square 3 resize 7 Square 4 resize 7 Square 5 resize 7 Shape 6 rotate Shape 7 rotate Shape 8 rotate Square 9 rotate Square 10 rotate Square 11 rotate Shape 12 rotate Shape 13 rotate Shape 14 rotate Square 15 rotate Square 16 rotate Square 17 rotate */ ``` 在 **Apply** 中,我們運氣很好,因為碰巧在 Java 中內建了一個由 Java 集合類庫使用的 **Iterable** 接口。正由于此, `apply()` 方法可以接受任何實現了 **Iterable** 接口的事物,包括諸如 **List** 這樣的所有 **Collection** 類。但是它還可以接受其他任何事物,只要能夠使這些事物是 **Iterable** 的——例如,在 `main()` 中使用下面定義的 **SimpleQueue** 類: ```java // generics/SimpleQueue.java // A different kind of Iterable collection import java.util.*; public class SimpleQueue<T> implements Iterable<T> { private LinkedList<T> storage = new LinkedList<>(); public void add(T t) { storage.offer(t); } public T get() { return storage.poll(); } @Override public Iterator<T> iterator() { return storage.iterator(); } } ``` 正如反射解決方案看起來那樣優雅,我們必須觀察到反射(盡管在 Java 的最新版本中得到了顯著改進)通常比非反射實現要慢,因為在運行時發生了很多事情。 但它不應阻止您嘗試這種解決方案,這依然是值得考慮的一點。 幾乎可以肯定,你會首先使用 Java 8 的函數式方法,并且只有在解決了特殊需求時才訴諸反射。 這里對 **ApplyTest.java** 進行了重寫,以利用 Java 8 的流和函數工具: ```java // generics/ApplyFunctional.java import java.util.*; import java.util.stream.*; import java.util.function.*; import onjava.*; public class ApplyFunctional { public static void main(String[] args) { Stream.of( Stream.generate(Shape::new).limit(2), Stream.generate(Square::new).limit(2)) .flatMap(c -> c) // flatten into one stream .peek(Shape::rotate) .forEach(s -> s.resize(7)); new FilledList<>(Shape::new, 2) .forEach(Shape::rotate); new FilledList<>(Square::new, 2) .forEach(Shape::rotate); SimpleQueue<Shape> shapeQ = Suppliers.fill( new SimpleQueue<>(), SimpleQueue::add, Shape::new, 2); Suppliers.fill(shapeQ, SimpleQueue::add, Square::new, 2); shapeQ.forEach(Shape::rotate); } } /* Output: Shape 0 rotate Shape 0 resize 7 Shape 1 rotate Shape 1 resize 7 Square 2 rotate Square 2 resize 7 Square 3 rotate Square 3 resize 7 Shape 4 rotate Shape 5 rotate Square 6 rotate Square 7 rotate Shape 8 rotate Shape 9 rotate Square 10 rotate Square 11 rotate */ ``` 由于使用 Java 8,因此不需要 `Apply.apply()` 。 我們首先生成兩個 **Stream** : 一個是 **Shape** ,一個是 **Square** ,并將它們展平為單個流。 盡管 Java 缺少功能語言中經常出現的 `flatten()` ,但是我們可以使用 `flatMap(c-> c)` 產生相同的結果,后者使用身份映射將操作簡化為“ **flatten** ”。 我們使用 `peek()` 當做對 `rotate()` 的調用,因為 `peek()` 執行一個操作(此處是出于副作用),并在未更改的情況下傳遞對象。 注意,使用 **FilledList** 和 **shapeQ** 調用 `forEach()` 比 `Apply.apply()` 代碼整潔得多。 在代碼簡單性和可讀性方面,結果比以前的方法好得多。 并且,現在也不可能從 `main()` 引發異常。
                  <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>

                              哎呀哎呀视频在线观看