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

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

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

Java泛型(11):潜在类型机制相关推荐

  1. Java 泛型的本质——类型擦除

    文章目录 简介 Java泛型的类型擦除的证明例子 类型擦除到边界 擦除的代价与使命 使用泛型不是强制的 泛型代码边界的动作 非泛型类库和泛型类库:字节码一模一样 擦除的补偿 泛型与工厂模式 泛型数组 ...

  2. java泛型之有界类型

    为什么80%的码农都做不了架构师?>>>    在前面的例子中,可以使用任意类替换类型参数.对于大多数情况这很好,但是限制能够传递给类型参数的类型有时是有用的.例如,假设希望创建一个 ...

  3. 15.17 对缺乏潜在类型机制的补偿

    15.17.1 反射 可以使用反射来解决潜在的类型机制. class Mime{ public void walkAgainstTheWind()} public void sit(){print(& ...

  4. java泛型程序设计——通配符类型+通配符的超类型限定

    [0]README 0.1) 本文描述+源代码均 转自 core java volume 1, 旨在理解 java泛型程序设计 的 通配符类型+通配符的超类型限定 的知识: [1]通配符类型相关 1. ...

  5. java 泛型参数具体类型获取、泛型返回具体类型获取

    自从java支持泛型后,现在,spring生态中的框架及目前的应用都使用了泛型.有的框架如mybatis和spring都需要反射获取类型,以使得序列化和反序列化得以实现,但有时候我们根据项目的需要获取 ...

  6. java 泛型参数的类型_Java获得泛型参数类型

    在Android开发中,使用Gson将json字符串转换为Java对象尤为常见.在这个转换过程中,通常会结合泛型参数.接口或者抽象类来封装处理. T t = new Gson().fromJson(r ...

  7. Java 泛型获取实体类型

    学习了动态初始化类,如果参数是各种类型的,要如何处理呢? 这时候,需要用到泛型,而传的数据是实体类型,如果从泛型中获取实体类型呢? 需要使用反射,获得指定类的父类的泛型参数的实际类型,直接上代码 ge ...

  8. java 鸭子类_Java中实现鸭子类型机制

    "当看到一只鸟走起来像鸭子.游泳起来像鸭子.叫起来也像鸭子,那么这只鸟就可以被称为鸭子."[引用维基] 一般而言,鸭子类型机制常见/用于动态语言,如Python.Ruby.JS.来 ...

  9. Java泛型总结---基本用法,类型限定,通配符,类型擦除

    一.基本概念和用法 在Java语言处于还没有出现泛型的版本时,只能通过Object是所有类型的父类和类型强制转换两个特点的配合来实现类型泛化.例如在哈希表的存取中,JDK1.5之前使用HashMap的 ...

最新文章

  1. ad走线画直线_作为立体几何的热点,直线与平面的平行关系,到处都是考试的影子...
  2. 【热烈祝贺】俺们的S5PV210 工控板终于启动到wince桌面了!
  3. Python网络编程—(TCP、UDP区别)
  4. LeetCode 6. ZigZag Conversion
  5. binlog二进制文件解析
  6. 4e4 Coursework decomposition
  7. 通过添加HTTP Header实现上下文数据在WCF的自动传递
  8. Java黑皮书课后题第10章:*10.20(近似e)编程练习题5.26使用下面数列近似计算e(略),为了得到更好的精度,在计算中使用25位精度的BigDecimal
  9. 微信支付开发(6) 收货地址共享接口
  10. C++ preprocessor /lib/cpp fails sanity check See `config.log' for more details
  11. oracle中结果集合并
  12. VMware Horizon Client剪贴板异常问题解决
  13. 循环控制体重C语言,减重名医王存川教授告诫:越早控制体重,肥胖导致身体的伤害越小...
  14. 单个H扩展到多个H时,机器学习的保证
  15. Matlab取整函数
  16. 软件测试典型缺陷分析,软件测试缺陷分析方法简介
  17. PHICOMM(斐讯)N1盒子 - recovery模式救砖卡登录页LOGO卡1%卡4%卡26%
  18. github-production-release Git-2.28.0-64-bit
  19. 系统安全相关知识学习
  20. html5网页制作电脑版,页未央HTML5制作神器PC版

热门文章

  1. [激光原理与应用-32]:典型激光器 -4- 半导体泵浦固体激光器
  2. 项目管理十大管理过程和知识领域思维导图(系统集成项目管理),如何学习系统集成项目管理教程
  3. 儿童场景英语品牌“麦禾教育”完成天使轮融资,清科资管领投
  4. 一种自适应的柔性制造系统优化调度算法
  5. 空降兵变革是怎样失败的
  6. 行云海cms mysql检测不出版本_行云海CMS(XYHCMS)网站内容管理系统 v3.6 bulid1012
  7. 双一流大学名单--仅供参考
  8. MATLAB实现TCP/IP通信
  9. 双胞胎能互相人脸识别解锁支付软件?那是你不了解点面科技的虹膜识别技术
  10. 基于QR分解迭代求解方阵特征值和特征向量