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
Java泛型(11):潜在类型机制相关推荐
- Java 泛型的本质——类型擦除
文章目录 简介 Java泛型的类型擦除的证明例子 类型擦除到边界 擦除的代价与使命 使用泛型不是强制的 泛型代码边界的动作 非泛型类库和泛型类库:字节码一模一样 擦除的补偿 泛型与工厂模式 泛型数组 ...
- java泛型之有界类型
为什么80%的码农都做不了架构师?>>> 在前面的例子中,可以使用任意类替换类型参数.对于大多数情况这很好,但是限制能够传递给类型参数的类型有时是有用的.例如,假设希望创建一个 ...
- 15.17 对缺乏潜在类型机制的补偿
15.17.1 反射 可以使用反射来解决潜在的类型机制. class Mime{ public void walkAgainstTheWind()} public void sit(){print(& ...
- java泛型程序设计——通配符类型+通配符的超类型限定
[0]README 0.1) 本文描述+源代码均 转自 core java volume 1, 旨在理解 java泛型程序设计 的 通配符类型+通配符的超类型限定 的知识: [1]通配符类型相关 1. ...
- java 泛型参数具体类型获取、泛型返回具体类型获取
自从java支持泛型后,现在,spring生态中的框架及目前的应用都使用了泛型.有的框架如mybatis和spring都需要反射获取类型,以使得序列化和反序列化得以实现,但有时候我们根据项目的需要获取 ...
- java 泛型参数的类型_Java获得泛型参数类型
在Android开发中,使用Gson将json字符串转换为Java对象尤为常见.在这个转换过程中,通常会结合泛型参数.接口或者抽象类来封装处理. T t = new Gson().fromJson(r ...
- Java 泛型获取实体类型
学习了动态初始化类,如果参数是各种类型的,要如何处理呢? 这时候,需要用到泛型,而传的数据是实体类型,如果从泛型中获取实体类型呢? 需要使用反射,获得指定类的父类的泛型参数的实际类型,直接上代码 ge ...
- java 鸭子类_Java中实现鸭子类型机制
"当看到一只鸟走起来像鸭子.游泳起来像鸭子.叫起来也像鸭子,那么这只鸟就可以被称为鸭子."[引用维基] 一般而言,鸭子类型机制常见/用于动态语言,如Python.Ruby.JS.来 ...
- Java泛型总结---基本用法,类型限定,通配符,类型擦除
一.基本概念和用法 在Java语言处于还没有出现泛型的版本时,只能通过Object是所有类型的父类和类型强制转换两个特点的配合来实现类型泛化.例如在哈希表的存取中,JDK1.5之前使用HashMap的 ...
最新文章
- ad走线画直线_作为立体几何的热点,直线与平面的平行关系,到处都是考试的影子...
- 【热烈祝贺】俺们的S5PV210 工控板终于启动到wince桌面了!
- Python网络编程—(TCP、UDP区别)
- LeetCode 6. ZigZag Conversion
- binlog二进制文件解析
- 4e4 Coursework decomposition
- 通过添加HTTP Header实现上下文数据在WCF的自动传递
- Java黑皮书课后题第10章:*10.20(近似e)编程练习题5.26使用下面数列近似计算e(略),为了得到更好的精度,在计算中使用25位精度的BigDecimal
- 微信支付开发(6) 收货地址共享接口
- C++ preprocessor /lib/cpp fails sanity check See `config.log' for more details
- oracle中结果集合并
- VMware Horizon Client剪贴板异常问题解决
- 循环控制体重C语言,减重名医王存川教授告诫:越早控制体重,肥胖导致身体的伤害越小...
- 单个H扩展到多个H时,机器学习的保证
- Matlab取整函数
- 软件测试典型缺陷分析,软件测试缺陷分析方法简介
- PHICOMM(斐讯)N1盒子 - recovery模式救砖卡登录页LOGO卡1%卡4%卡26%
- github-production-release Git-2.28.0-64-bit
- 系统安全相关知识学习
- html5网页制作电脑版,页未央HTML5制作神器PC版
热门文章
- [激光原理与应用-32]:典型激光器 -4- 半导体泵浦固体激光器
- 项目管理十大管理过程和知识领域思维导图(系统集成项目管理),如何学习系统集成项目管理教程
- 儿童场景英语品牌“麦禾教育”完成天使轮融资,清科资管领投
- 一种自适应的柔性制造系统优化调度算法
- 空降兵变革是怎样失败的
- 行云海cms mysql检测不出版本_行云海CMS(XYHCMS)网站内容管理系统 v3.6 bulid1012
- 双一流大学名单--仅供参考
- MATLAB实现TCP/IP通信
- 双胞胎能互相人脸识别解锁支付软件?那是你不了解点面科技的虹膜识别技术
- 基于QR分解迭代求解方阵特征值和特征向量