Java泛型通配符
来源:互联网 发布:域名运营商查询 编辑:程序博客网 时间:2024/05/18 02:29
1.通配类型的诞生
在Java泛型当中, 严格的泛型类型系统难免让人觉得有点不快。比如Pair<Apple>
并不是Pair<Fruit>
的子类, 两者并无关联。所以对于下面这样的方法是不可以传入Pair<Apple>
的。:
public static void printFruits(Pair<Fruit> f)
为了解决这个问题,Java的设计人员发明了通配类型。在通配类型中,类型参数可以代表不同的类型。例如:Pair<? extends Fruit>
可以代表任何Pair泛型,只要类型参数是Fruit的子类。那么对于上面的难题,只要将方法稍加修改:
public static void printFruits(Pair< ? extends Fruit> f)
就可以愉快地传入Pair<Apple>
啦!
2.通配类型的烦恼
当然,对于通配类型来说,也会出现各种各样的小问题。看下面代码:
Pair<Manager> managerBuddies = new Pair<>(ceo, cfo); Pair<? extends Employee> wildcardBuddies = managerBuddies; // OK wildcardBuddies.setFirst(lowlyEmployee); // compile-time error
这里的意思是建了一个Manage Pair,里面放了一个ceo,一个cfo,然后使用通配类型建立了一个Pair,指向一对普通Employee或者高级Manager。这里指向了刚刚创建的Manage Pair,但是之后却不能进行修改了。这是因为通配Pair的方法是这样的:
(? extends Employee) getFirst() void setFirst(? extends Employee)
这里编译器只知道它此方法需要Employee的子类, 但是又不知道具体的类型。 由于?可能与其不符,所以编译器拒绝传递具体的类型来进行修改,偏于保守。而getFirst方法的返回值是完全可以用Employee对象及其父类对象接收的。
3.通配类型的父类bound问题
? super Manager
这个通配符被限制为所有Manager的父类型。这里与上文情况相反,可以提供参数给方法,但不能使用返回值。Pair<? super Manager>
有以下方法:
void setFirst(? super Manager) (? super Manager) getFirst()
对于这里的setFirst方法,只能传入Manager对象或者Manager的子类。因为这里的(? super Manager)是Manager的父类,如果对其进行修改,不能传入Employee或者更高的Object,因为可能是个Manager对象。而对于getFirst方法,返回值只能拿Object对象来接收。
总结一下就是:上限的通配符–>写; 下限通配符号–>读。
4.通配类型的父类bound其他应用
public static <T extends Comparable<T>> Pair<T> minmax(T[] a) { if(a == null || a.length == 0) return null; T min = a[0]; T max = a[0]; for (int i = 0; i < a.length; i++) { if (min.compareTo(a[i]) > 0) min = a[i]; if (max.compareTo(a[i]) < 0) max = a[i]; } return new Pair<>(min, max); } public static void main(String[] args) { LocalDate[] birthdays = { LocalDate.of(1906, 12, 9), LocalDate.of(1815, 12, 10), LocalDate.of(1903, 12, 3), LocalDate.of(1910, 6, 22), }; Pair<LocalDate> mm = minmax(birthdays); System.out.println("min = " + mm.getFirst()); System.out.println("max = " + mm.getSecond()); }
对于上面的代码,实现了找出T[]中的最大最小元素放入Pair中的操作。值得注意的是这里使用的是T extends Comparable<T>
,对于很多类如String类这里都不回会有问题,因为它实现了Comparable<String>
接口,满足T extends Comparable<T>
,但是对于有的类型如例子中的LocalDate类,继承了别的类(这里是ChronoLocalDate),而别的类实现了Comparable<ChronoLocalDate>
接口,所以这里要将T extends Comparable<T>
修改成T extends Comparable<? super T>
,即可满足条件。
5.无界通配类型
//Pair<?>有以下的方法 ? getFirst() void setFirst(?)
这里的getFirst返回值只能赋给Object对象, 而setFirst却不能被调用(setFirst(null)可以),用Object对象作为参数也不可以。而对于(raw type)Pair却可以使用任何对象作为参数来调用setFirst.
这样的类型经常在检查空指针时候使用,例如:
public static boolean hasNulls(Pair<?> p) { return p.getFirst() == null || p.getSecond() == null; } //使用泛型方法代替也可以 public static <T> boolean hasNulls(Pair<T> p) { return p.getFirst() == null || p.getSecond() == null; }
- java泛型通配符
- java泛型通配符
- java泛型通配符
- Java泛型通配符
- Java泛型通配符
- Java泛型通配符
- java泛型通配符
- java泛型通配符
- Java 泛型类型通配符
- Java 通配符泛型例子
- Java 泛型通配符?解惑
- JAVA泛型和通配符
- Java泛型之通配符
- Java泛型中的通配符
- Java 泛型通配符?解惑
- Java 泛型通配符?解惑
- Java泛型通配符解惑
- Java 泛型通配符?解惑
- caffe中特殊的layer解释
- 获取其他App中资源的方法
- c++中的类型转换
- python计算运行时间(转)
- 1748. The Most Complex Number/LG的数学计划~~~持续更新ing(反素数求解)
- Java泛型通配符
- The application's PagerAdapter changed the adapter's contents without calling PagerAdapter#notifyDat
- 网络流24题—— 试题库问题
- ZooKeeper集群-搭建指南
- Fresco基本使用
- 欢迎使用CSDN-markdown编辑器
- libgdx绘制线段
- LG 的数学计划 ---- 第四步 快速幂
- [LeetCode] 287. Find the Duplicate Number