zoukankan      html  css  js  c++  java
  • Java泛型(11):潜在类型机制

    泛型的目标之一就是能够编写尽可能广泛应用的代码

    为了实现这一点,我们需要各种途径来放松对我们的代码将要作用的类型所做的限制,同时不丢失静态类型检查的好处。即写出更加泛化的代码。

    Java泛型看起来是向这个方向迈进了一步。但是还是有一定的限制:

    (1)当你在编写或使用只是持有对象<T>的泛型时,这些代码可以适用于任何类型。这些代码就可以真正应用于任何地方,因此相当泛化。

    (2)当要在泛型类型上执行操作时,就会产生问题,因为擦除要求指定可能会用到的泛型类型的边界,以安全的调用代码中的泛型对象上的具体方法。

    这是对泛化的明显限制。因为必须限制你的泛型类型,使它们继承特定类或实现特定接口。

    某些编程语言(Python、C++)提供一种解决方案称为潜在类型机制,它只要求泛型代码实现某个方法的子集,而不是特定类或接口

    尽管Java不支持潜在类型机制,但这并不意味着有界泛型代码不能在不同的类型层次结构之间应用,只不过需要付出一些额外的努力。

    (0)以下面例子作为原型:

     1 interface Performs {
     2     void speak();
     3     void sit();
     4 }
     5 class Dog implements Performs {
     6     @Override public void speak() { System.out.println("Dog Speaking..."); }
     7     @Override public void sit() { System.out.println("Dog Sitting..."); }
     8     public void run() { System.out.println("Dog Running..."); }
     9 }
    10 class Robot implements Performs {
    11     @Override public void speak() { System.out.println("Robot Speaking..."); }
    12     @Override public void sit() { System.out.println("Robot Sitting..."); }
    13     public void calc() { System.out.println("Robot Calculating..."); }
    14 }
    15 class Actions {
    16     public static void perform(Performs p) {
    17         p.speak();
    18         p.sit();
    19     }
    20 }
    21 public class DogsAndRobots {
    22     public static void main(String[] args) {
    23         Actions.perform(new Dog());
    24         Actions.perform(new Robot());
    25     }
    26 }

    (1)反射

     1 import java.lang.reflect.InvocationTargetException;
     2 import java.lang.reflect.Method;
     3 
     4 class Dog1 {
     5     public void speak() { System.out.println("Dog1 Speaking..."); }
     6     public void sit() { System.out.println("Dog1 Sitting..."); }
     7     public void run() { System.out.println("Dog1 Running..."); }
     8 }
     9 class Robot1 {
    10     public void speak() { System.out.println("Robot1 Speaking..."); }
    11     public void sit() { System.out.println("Robot1 Sitting..."); }
    12     public void calc() { System.out.println("Robot1 Calculating..."); }
    13 }
    14 class Actions1 {
    15     public static void perform(Object obj) {
    16         Class<?> objClass = obj.getClass();
    17         try {
    18             Method speak = objClass.getMethod("speak");
    19             speak.invoke(obj);
    20             Method sit = objClass.getMethod("sit");
    21             sit.invoke(obj);
    22         } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
    23             e.printStackTrace();
    24         }
    25     }
    26 }
    27 public class DogsAndRobots1 {
    28     public static void main(String[] args) {
    29         Actions1.perform(new Dog1());
    30         Actions1.perform(new Robot1());
    31     }
    32 }

    (2)将一个方法应用于序列 (apply方法可以接受任何实现Iterable接口的事物,然而,这样的代码还是不够泛化。)

     1 import java.lang.reflect.InvocationTargetException;
     2 import java.lang.reflect.Method;
     3 import java.util.ArrayList;
     4 import java.util.List;
     5 
     6 class Dog2 {
     7     public void speak() { System.out.println("Dog2 Speaking..."); }
     8     public void sit() { System.out.println("Dog2 Sitting..."); }
     9     public void run(int length) { System.out.println("Dog2 runs " + length + " miles."); }
    10 }
    11 
    12 class SmartDog extends Dog2 {}
    13 
    14 class Actions2 {
    15     // PECS
    16     public static <T, S extends Iterable<? extends T>> void apply(S seq, Method f, Object... args) {
    17         seq.forEach(p -> {
    18             try {
    19                 f.invoke(p, args);
    20             } catch (IllegalAccessException | InvocationTargetException e) {
    21                 e.printStackTrace();
    22             }
    23         });
    24     }
    25 }
    26 
    27 class FilledList<T> extends ArrayList<T> {
    28     // PECS
    29     public FilledList(Class<? extends T> type, int size) throws Exception {
    30         for(int i = 0; i < size; i++) {
    31             add(type.newInstance());
    32         }
    33     }
    34 }
    35 
    36 public class DogsAndRobots2 {
    37     public static void main(String[] args) throws Exception {
    38         List<Dog2> dog2s = new ArrayList<>();
    39         for (int i = 0; i < 3; i++) {
    40             dog2s.add(new Dog2());
    41         }
    42         Actions2.apply(dog2s, Dog2.class.getMethod("speak"));
    43         Actions2.apply(new FilledList<>(SmartDog.class, 2), SmartDog.class.getMethod("run", int.class), 1);
    44     }
    45 }

    (3)用适配器仿真潜在类型机制

      1 import java.util.*;
      2 
      3 interface Addable<T> { void add(T t); }
      4 
      5 interface Generator<T> { T next(); }
      6 
      7 class SimpleQueue<T> implements Iterable<T> {
      8     private LinkedList<T> storage = new LinkedList<T>();
      9     public void add(T t) { storage.offer(t); }
     10     public T get() { return storage.poll(); }
     11     public Iterator<T> iterator() {
     12         return storage.iterator();
     13     }
     14 }
     15 
     16 class Dog3 {
     17     public void speak(){ System.out.println("Dog2 Speaking..."); }
     18     public void sit() { System.out.println("Dog2 Sitting..."); }
     19     public void run(int length) { System.out.println("Dog2 runs " + length + " miles."); }
     20 }
     21 
     22 class BigDog extends Dog3 {}
     23 class SmallDog extends Dog3 {}
     24 
     25 class Fill {
     26     // Classtoken version:
     27     public static <T> void fill(Addable<T> addable, Class<? extends T> classToken, int size) {
     28         for (int i = 0; i < size; i++)
     29             try {
     30                 addable.add(classToken.newInstance());
     31             } catch (Exception e) {
     32                 throw new RuntimeException(e);
     33             }
     34     }
     35 
     36     // Generator version:
     37     public static <T> void fill(Addable<T> addable, Generator<T> generator, int size) {
     38         for (int i = 0; i < size; i++)
     39             addable.add(generator.next());
     40     }
     41 }
     42 
     43 // To adapt a base type, you must use composition.
     44 // Make any Collection Addable using composition:
     45 class AddableCollectionAdapter<T> implements Addable<T> {
     46     private Collection<T> c;
     47 
     48     public AddableCollectionAdapter(Collection<T> c) {
     49         this.c = c;
     50     }
     51 
     52     public void add(T item) {
     53         c.add(item);
     54     }
     55 }
     56 
     57 // A Helper to capture the type automatically:
     58 class Adapter {
     59     public static <T> Addable<T> collectionAdapter(Collection<T> c) {
     60         return new AddableCollectionAdapter<>(c);
     61     }
     62 }
     63 
     64 // To adapt a specific type, you can use inheritance.
     65 // Make a SimpleQueue Addable using inheritance:
     66 class AddableSimpleQueue<T> extends SimpleQueue<T> implements Addable<T> {
     67     public void add(T item) { super.add(item); }
     68 }
     69 
     70 public class DogsAndRobots3 {
     71     public static void main(String[] args) {
     72         List<Dog3> dog3s = new ArrayList<>();
     73         // Adapt a Collection:
     74         Fill.fill(new AddableCollectionAdapter<>(dog3s), BigDog.class, 3);
     75         // Helper method captures the type:
     76         Fill.fill(Adapter.collectionAdapter(dog3s), SmallDog.class, 2);
     77         for(Dog3 elem : dog3s) {
     78             System.out.println(elem.getClass().getSimpleName());
     79         }
     80         System.out.println("----------------------");
     81         // Use an adapted class:
     82         AddableSimpleQueue<Dog3> dog3Queue = new AddableSimpleQueue<>();
     83         Fill.fill(dog3Queue, BigDog.class, 4);
     84         Fill.fill(dog3Queue, SmallDog.class, 1);
     85         for(Dog3 elem : dog3Queue) {
     86             System.out.println(elem.getClass().getSimpleName());
     87         }
     88         //        BigDog
     89         //        BigDog
     90         //        BigDog
     91         //        SmallDog
     92         //        SmallDog
     93         //        ----------------------
     94         //        BigDog
     95         //        BigDog
     96         //        BigDog
     97         //        BigDog
     98         //        SmallDog
     99     }
    100 }
  • 相关阅读:
    js打开新窗口
    JS普通浏览器页面传参
    MUI之移动APP页面之间传递参数
    flex布局原理
    css3之Tab页面切换
    css之左边竖条的实现方法
    “程序猿”——要理清你的思路!
    win32调试——OutputDebugString
    des加密——补齐
    SVN 过滤文件
  • 原文地址:https://www.cnblogs.com/storml/p/8331543.html
Copyright © 2011-2022 走看看