泛型无法适用重载的场景:both methods have same erasure
泛型无法适用重载的场景:both methods have same erasure
- 问题描述
- 问题分析
- 解决方案
- 方案一:针对集合对象,方法声明不同基类/实现类作为方法参数类型(不推荐)
- 方案二:设置共同基类/接口,抽象出方法所需要内容
- 方案三:在方法中,直接使用映射机制
- 可重现问题代码
- 方案一:代码实现(不推荐)
- 方案二:代码实现
- 方案三:代码实现
问题描述
针对集合对象,假设有一套根据其元素上相同名称的属性值进行排序的方法/算法。
由于集合的元素对象除Object
外没有共同的基类,此时,首先想到的做法便是”重载“。
但方法重载时,参数数量和集合一样,但泛型的不一样,仍被编译器视为相同的方法,提示诸如:
‘specialSort(List)’ clashes with ‘specialSort(List)’;both methods have same erasure
问题分析
泛型,作为JDK5时代引入的”语法糖“,在编译的时候是会被抹除的,换言之,specialSort(List<Dog>)
和specialSort(List<Apple>)
在编译时都会变成specialSort(List)
,因此不符合重载的原则(变量名相同、参数类型或数量不同)。
解决方案
方案一:针对集合对象,方法声明不同基类/实现类作为方法参数类型(不推荐)
既然List<Dog>
和List<Apple>
在编译时都回变成List
,如果我已知其中一个集合对象是ArrayList
对象,以List<Apple>
为例,那就可以将其对应的方法参数类型改成ArrayList<Apple>
。再或者,直接将其中一个方法改成Collection
。
如此,因为参数类型不同,便满足重载的条件。
个人认为,这样的做法会大大影响代码的可读性,且会造成大量的冗余代码,虽然能解决问题,但真的不推荐。
此方案参考自:both methods have same erasure:如何无损扩展代码
方案二:设置共同基类/接口,抽象出方法所需要内容
如果两个是类型相近的类,如Dog
和Cat
,那么可以考虑新建一个公共基类,随后在基类中暴露出为方法所需要的属性获取方法。
在可重现问题代码
中,方法目的是为了按特殊规则排序,那么也可以选择直接在基类中实现Comparable
接口,重写比较的方法。
但对于类型不相近,或较难抽象出公共基类的类,那这个方案就显得不适用了。
方案三:在方法中,直接使用映射机制
在我看来,这是最暴力的方案了,方法中先可以直接通过映射机制获取到对象的属性值,随后便可以进行原来的逻辑代码操作了。
这个方案,不需要重载,省去了那些冗余的逻辑代码,只是反射机制需要格外的开销。
可重现问题代码
class Dog {private String name;private int age;public Dog(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}
}class Apple {private String name;private int age;public Apple(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}
}@Test
void test() {List<Dog> dogList = Lists.newArrayList();dogList.add(new Dog("Dog B", 2));dogList.add(new Dog("Dog A", 2));dogList.add(new Dog("Dog A", 1));specialSort(dogList);System.out.println(JSON.toJSONString(dogList));List<Apple> appleList = Lists.newArrayList();appleList.add(new Apple("Apple B", 2));appleList.add(new Apple("Apple A", 2));appleList.add(new Apple("Apple A", 1));specialSort(appleList);System.out.println(JSON.toJSONString(appleList));
}public static void specialSort(List<Dog> dogList) {dogList.sort((o1, o2) -> {int result = 0;if (o1.getAge() != o2.getAge()) {result = o1.getAge() - o2.getAge();} else {Objects.requireNonNull(o1.getName());Objects.requireNonNull(o2.getName());result = ObjectUtils.compare(o1.getName(), o2.getName());}return result;});
}public static void specialSort(List<Apple> appleList) {appleList.sort((o1, o2) -> {int result = 0;if (o1.getAge() != o2.getAge()) {result = o1.getAge() - o2.getAge();} else {Objects.requireNonNull(o1.getName());Objects.requireNonNull(o2.getName());result = ObjectUtils.compare(o1.getName(), o2.getName());}return result;});
}
方案一:代码实现(不推荐)
// Class Dog 和 Class Apple 的定义不变
@Test
void test() {ArrayList<Dog> dogList = Lists.newArrayList();dogList.add(new Dog("Dog B", 2));dogList.add(new Dog("Dog A", 2));dogList.add(new Dog("Dog A", 1));specialSort(dogList);System.out.println(JSON.toJSONString(dogList));ArrayList<Apple> appleList = Lists.newArrayList();appleList.add(new Apple("Apple B", 2));appleList.add(new Apple("Apple A", 2));appleList.add(new Apple("Apple A", 1));specialSort(appleList);System.out.println(JSON.toJSONString(appleList));
}
public static void specialSort(List<Dog> dogList) {dogList.sort((o1, o2) -> {int result = 0;if (o1.getAge() != o2.getAge()) {result = o1.getAge() - o2.getAge();} else {Objects.requireNonNull(o1.getName());Objects.requireNonNull(o2.getName());result = ObjectUtils.compare(o1.getName(), o2.getName());}return result;});
}
public static void specialSort(ArrayList<Apple> appleList) {appleList.sort((o1, o2) -> {int result = 0;if (o1.getAge() != o2.getAge()) {result = o1.getAge() - o2.getAge();} else {Objects.requireNonNull(o1.getName());Objects.requireNonNull(o2.getName());result = ObjectUtils.compare(o1.getName(), o2.getName());}return result;});
}
方案二:代码实现
abstract class ParentClass {public abstract String getName();public abstract int getAge();
}class Dog extends ParentClass{private String name;private int age;public Dog(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}
}class Apple extends ParentClass{private String name;private int age;public Apple(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}
}
@Test
void test() {List<Dog> dogList = Lists.newArrayList();dogList.add(new Dog("Dog B", 2));dogList.add(new Dog("Dog A", 2));dogList.add(new Dog("Dog A", 1));specialSort(dogList);System.out.println(JSON.toJSONString(dogList));List<Apple> appleList = Lists.newArrayList();appleList.add(new Apple("Apple B", 2));appleList.add(new Apple("Apple A", 2));appleList.add(new Apple("Apple A", 1));specialSort(appleList);System.out.println(JSON.toJSONString(appleList));
}public static <T extends ParentClass> void specialSort(List<T> list) {list.sort((o1, o2) -> {int result = 0;if (o1.getAge() != o2.getAge()) {result = o1.getAge() - o2.getAge();} else {Objects.requireNonNull(o1.getName());Objects.requireNonNull(o2.getName());result = ObjectUtils.compare(o1.getName(), o2.getName());}return result;});
}
方案三:代码实现
// Class Dog 和 Class Apple 的定义不变
@Test
void test() {List<Dog> dogList = Lists.newArrayList();dogList.add(new Dog("Dog B", 2));dogList.add(new Dog("Dog A", 2));dogList.add(new Dog("Dog A", 1));specialSort(dogList);System.out.println(JSON.toJSONString(dogList));List<Apple> appleList = Lists.newArrayList();appleList.add(new Apple("Apple B", 2));appleList.add(new Apple("Apple A", 2));appleList.add(new Apple("Apple A", 1));specialSort(appleList);System.out.println(JSON.toJSONString(appleList));
}
public static void specialSort(List list){list.sort((o1, o2) -> {int result = 0;// 暂不考虑特殊异常处理try {String method = "getAge";int age1 = (int) o1.getClass().getMethod(method).invoke(o1),age2 = (int) o2.getClass().getMethod(method).invoke(o2);if (age1 != age2) {result = age1 - age2;} else {method = "getName";String name1 = (String) o1.getClass().getMethod(method).invoke(o1),name2 = (String) o2.getClass().getMethod(method).invoke(o2);Objects.requireNonNull(name1);Objects.requireNonNull(name2);result = ObjectUtils.compare(name1, name2);}} catch (Exception e) {System.out.println(e.getMessage());e.printStackTrace();}return result;});}
泛型无法适用重载的场景:both methods have same erasure相关推荐
- both methods have same erasure, yet neither overrides the other
文章目录 both methods have same erasure, yet neither overrides the other 1.编译报错 both methods have same e ...
- 泛型与操作符重载杂谈
泛型基础 1.为什么要用泛型类,我们先来看一段代码: 以交换两个数为例,可能需要定义多个重载方法 public static void swap(ref int x,ref int y) { int ...
- C#笔记09 结构、枚举、异常、泛型、操作符重载、dll、垃圾回收与资源清理、XML注释
文章目录 结构体struct 枚举enum 异常Exception 执行try最近的最贴切的catch 继承Exception以定义异常 泛型 泛型的约束where 操作符重载 类型转换操作符重载 d ...
- Java筑基——泛型的点点滴滴
目录 1. 泛型的作用 2. 泛型类 3. 泛型接口 4. 泛型方法 5. 泛型擦除 5.1 擦除是什么? 5.2 擦除时使用边界替换类型参数 5.3 擦除会插入类型转换来保持类型安全 5.4 擦除会 ...
- 深入理解 Java 泛型
首先提个问题: Java 泛型的作用是什么?泛型擦除是什么?泛型一般用在什么场景? 如果这个问题你答不上来,那这篇文章可能就对你有些价值. 读完本文你将了解到: 什么是泛型 为什么引入泛型 泛型的使用 ...
- java 泛型全解 - 绝对最详细
背景 对于java的泛型我一直属于一知半解的,平常真心用的不多.直到阅读<Effect Java>,看到很多平常不了解的用法,才下定决心,需要系统的学习,并且记录下来. 1.泛型的概述: ...
- Java泛型的定义和使用详解
目录 一,为什么我们需要泛型 二,什么是泛型,泛型的定义 三,如何定义和使用泛型 四.限定类型变量 五.泛型中的约束和局限性 六.泛型类型的继承规则 七.通配符类型 八.虚拟机是如何实现泛型的? 一, ...
- 3万字死磕Java泛型所有细节知识点,看这一篇就够了
1 泛型 1.0 前言--为什么要死磕Java泛型 不知道阅读这篇文章的你是否曾跟我一样,在没有阅读<Java核心技术>前查阅了大量的Java泛型文章,但是在实际使用泛型的过程中,总是觉得 ...
- 泛型爪哇(Generic Java)
泛型爪哇(Generic Java) Java 可能即将有一场大变革 译者:陈崴 侯捷注:本文系北京<程序员>杂志 2001/05 的文章.译笔顺畅,技术饱满. 承译者陈崴先生与<程 ...
最新文章
- 详解linux系统的启动过程及系统初始化
- kali linux提示安装系统失败,kali“安装系统”失败分析及解决
- 基于单目视觉的智能车辆视觉导航系统设计
- luncene 查询字符串的解析—QueryParser类
- VTK修炼之道24:图像基本操作_单颜色通道图像合成彩色
- GPS服务端解析程序编写日记之--vs2010中多种语言开发及调试的若干注意事项
- python中的栈结构_python中有栈吗
- [转载]DB2数据库移植罕见成绩片面理睬(4)
- outlook的插件管理(Web界面)
- 我又踩坑了!如何为HttpClient请求设置Content-Type标头?
- caffe(CPU版本)配置 及MNIST调用
- 93.复原IP地址(力扣leetcode) 博主可答疑该问题
- cr全称是什么意思_魔兽世界CR是团灭的意思 他的全称是什么呢?
- 打卡项目php,Thinkphp框架早起打卡项目(深蓝引擎Z)趣步模式+完整数据+全开源源码...
- 卡方检验结果表格中出现非常多个卡方值和P值的原理和实现步骤
- 五个拿来就能用的炫酷登录页面
- win10服务器只显示4g内存,64位win10识别到了4G内存,却只用了3.1G,为什么?
- 阿里巴巴与山东省人民政府签署战略合作协议
- Fabric CA的基础知识
- 应用统计学与R语言实现学习笔记(三)——描述性统计
热门文章
- 越老越吃香的计算机专业,大四学长:最有前途的4个理工专业,毕业工作不愁,还越老越吃香...
- 大话水声通信技术---(BFSK仿真)
- 如何在ubuntu中安装无线网卡驱动(迅捷FW150UH)
- driver failed programming external connectivity on endpoint rabbitmq (204c074dd525374b10eec763a068ec
- 2020美团面试真题解析
- 检验c语言程序是否正确的程序,c语言实习心得体会范文
- excel多表格数据汇总如何实现
- 百度云盘搜索引擎【升级版】
- 融资破局 |中英美三国多层次资本市场和STO融资的比较及借鉴
- 计算机辅助测试题,2017计算机辅助设计练习题