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 }

 

转载于:https://www.cnblogs.com/storml/p/8331543.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值