本节先讲解如何限制类型参数的范围,再讲解通配符(?)。

类型参数的范围

在泛型中,如果不对类型参数加以限制,它就可以接受任意的数据类型,只要它是被定义过的。但是,很多时候我们只需要一部分数据类型就够了,用户传递其他数据类型可能会引起错误。例如,编写一个泛型函数用于返回不同类型数组(Integer 数组、Double 数组等)中的最大值:

  1. public <T> T getMax(T array[]){
  2. T max = null;
  3. for(T element : array){
  4. max = element.doubleValue() > max.doubleValue() ? element : max;
  5. }
  6. return max;
  7. }

上面的代码会报错,doubleValue() 是 Number 类及其子类的方法,不是所有的类都有该方法,所以我们要限制类型参数 T,让它只能接受 Number 及其子类(Integer、Double、Character 等)。

通过 extends 关键字可以限制泛型的类型的上限,改进上面的代码:

  1. public <T extends Number> T getMax(T array[]){
  2. T max = null;
  3. for(T element : array){
  4. max = element.doubleValue() > max.doubleValue() ? element : max;
  5. }
  6. return max;
  7. }

<T extends Number> 表示 T 只接受 Number 及其子类,传入其他类型的数据会报错。这里的限定使用关键字 extends,后面可以是类也可以是接口。如果是类,只能有一个;但是接口可以有多个,并以“&”分隔,例如 <T extends Interface1 & Interface2>。

这里的 extends 关键字已不再是继承的含义了,应该理解为 T 是继承自 Number 类的类型,或者 T 是实现了 XX 接口的类型。

通配符(?)

上一节的例子中提到要定义一个泛型类来表示坐标,坐标可以是整数、小数或字符串,请看下面的代码:

  1. class Point<T1, T2>{
  2. T1 x;
  3. T2 y;
  4. public T1 getX() {
  5. return x;
  6. }
  7. public void setX(T1 x) {
  8. this.x = x;
  9. }
  10. public T2 getY() {
  11. return y;
  12. }
  13. public void setY(T2 y) {
  14. this.y = y;
  15. }
  16. }

现在要求在类的外部定义一个 printPoint() 方法用于输出坐标,怎么办呢?

可以这样来定义方法:

  1. public void printPoint(Point p){
  2. System.out.println(“This point is: “ + p.getX() + “, “ + p.getY());
  3. }

我们知道,如果在使用泛型时没有指名具体的数据类型,就会擦除泛型类型,并向上转型为 Object,这与不使用泛型没什么两样。上面的代码没有指明数据类型,相当于:

  1. public void printPoint(Point<Object, Object> p){
  2. System.out.println(“This point is: “ + p.getX() + “, “ + p.getY());
  3. }

为了避免类型擦除,可以使用通配符(?):

  1. public void printPoint(Point<?, ?> p){
  2. System.out.println(“This point is: “ + p.getX() + “, “ + p.getY());
  3. }

通配符(?)可以表示任意的数据类型。将代码补充完整:

  1. public class Demo {
  2. public static void main(String[] args){
  3. Point<Integer, Integer> p1 = new Point<Integer, Integer>();
  4. p1.setX(10);
  5. p1.setY(20);
  6. printPoint(p1);
  7. Point<String, String> p2 = new Point<String, String>();
  8. p2.setX(“东京180度”);
  9. p2.setY(“北纬210度”);
  10. printPoint(p2);
  11. }
  12. public static void printPoint(Point<?, ?> p){ // 使用通配符
  13. System.out.println(“This point is: “ + p.getX() + “, “ + p.getY());
  14. }
  15. }
  16. class Point<T1, T2>{
  17. T1 x;
  18. T2 y;
  19. public T1 getX() {
  20. return x;
  21. }
  22. public void setX(T1 x) {
  23. this.x = x;
  24. }
  25. public T2 getY() {
  26. return y;
  27. }
  28. public void setY(T2 y) {
  29. this.y = y;
  30. }
  31. }

运行结果:
This point is: 10, 20
This point is: 东京180度, 北纬210度

但是,数字坐标与字符串坐标又有区别:数字可以表示x轴或y轴的坐标,字符串可以表示地球经纬度。现在又要求定义两个方法分别处理不同的坐标,一个方法只能接受数字类型的坐标,另一个方法只能接受字符串类型的坐标,怎么办呢?

这个问题的关键是要限制类型参数的范围,请先看下面的代码:

  1. public class Demo {
  2. public static void main(String[] args){
  3. Point<Integer, Integer> p1 = new Point<Integer, Integer>();
  4. p1.setX(10);
  5. p1.setY(20);
  6. printNumPoint(p1);
  7. Point<String, String> p2 = new Point<String, String>();
  8. p2.setX(“东京180度”);
  9. p2.setY(“北纬210度”);
  10. printStrPoint(p2);
  11. }
  12. // 借助通配符限制泛型的范围
  13. public static void printNumPoint(Point<? extends Number, ? extends Number> p){
  14. System.out.println(“x: “ + p.getX() + “, y: “ + p.getY());
  15. }
  16. public static void printStrPoint(Point<? extends String, ? extends String> p){
  17. System.out.println(“GPS: “ + p.getX() + “,” + p.getY());
  18. }
  19. }
  20. class Point<T1, T2>{
  21. T1 x;
  22. T2 y;
  23. public T1 getX() {
  24. return x;
  25. }
  26. public void setX(T1 x) {
  27. this.x = x;
  28. }
  29. public T2 getY() {
  30. return y;
  31. }
  32. public void setY(T2 y) {
  33. this.y = y;
  34. }
  35. }

运行结果:
x: 10, y: 20
GPS: 东京180度,北纬210度

? extends Number 表示泛型的类型参数只能是 Number 及其子类,? extends String 也一样,这与定义泛型类或泛型方法时限制类型参数的范围类似。

不过,使用通配符(?)不但可以限制类型的上限,还可以限制下限。限制下限使用 super 关键字,例如 <? super Number> 表示只能接受 Number 及其父类。

注意:一般的项目中很少会去设计泛型,这里主要是让读者学会如何使用,为后面的教程做铺垫。

六. 异常处理
1.异常处理基础
2.异常类型
3.未被捕获的异常
4.try和catch的使用
5.多重catch语句的使用
6.try语句的嵌套
7.throw:异常的抛出
8.throws子句
9.finally块
10.Java的内置异常
11.创建自己的异常子类
12.断言
七. 多线程编程
1.线程的概念
2.Java线程模型
3.主线程
4.创建线程
5.创建多线程
6.isAlive()和join()的使用
7.线程优先级
8.线程同步
9.线程间通信
10.线程死锁
11.线程的挂起、恢复和终止

java泛型通配符和类型参数的范围相关推荐

  1. Java知多少(42)泛型通配符和类型参数的范围

    本节先讲解如何限制类型参数的范围,再讲解通配符(?). 类型参数的范围 在泛型中,如果不对类型参数加以限制,它就可以接受任意的数据类型,只要它是被定义过的.但是,很多时候我们只需要一部分数据类型就够了 ...

  2. 聊一聊Java 泛型通配符 T,E,K,V,?

    欢迎关注方志朋的博客,回复"666"获面试宝典 | 前言 Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制,该机制允许开发者 ...

  3. [转]JAVA泛型通配符T,E,K,V区别,T以及ClassT,Class?的区别

    原文地址:https://www.jianshu.com/p/95f349258afb 1. 先解释下泛型概念 泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被 ...

  4. 不正确 有三种形式 说法 通配泛型_一看就懂 详解JAVA泛型通配符T,E,K,V区别...

    1. 先解释下泛型概念 泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数.这种参数类型可以用在类.接口和方法的创建中,分别称为泛型类.泛型接口.泛 ...

  5. java 通配符 类_关于类:具有多个类的Java泛型通配符

    我想要一个类对象,但是我想要强制它所代表的任何类来扩展类A和实现接口B. 我能做到: Class extends ClassA> 或: Class extends InterfaceB> ...

  6. (转)JAVA泛型通配符T,E,K,V区别,T以及Class,Class的区别

    1. 先解释下泛型概念 泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数.这种参数类型可以用在类.接口和方法的创建中,分别称为泛型类.泛型接口.泛 ...

  7. JAVA泛型通配符T,E,K,V区别,T以及ClassT,ClassT的区别

    原文地址:https://www.jianshu.com/p/95f349258afb 1. 先解释下泛型概念 泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被 ...

  8. Java泛型 通配符? extends与super

    本文来源:https://i.cnblogs.com/EditPosts.aspx?opt=1 感谢博主.本文仅供参考学习. Java 泛型 关键字说明 ? 通配符类型 <? extends T ...

  9. 关于通配泛型类型有几种_5.7 泛型通配符和类型参数的范围

    本节先讲解如何限制类型参数的范围,再讲解通配符(?). 类型参数的范围 在泛型中,如果不对类型参数加以限制,它就可以接受任意的数据类型,只要它是被定义过的.但是,很多时候我们只需要一部分数据类型就够了 ...

最新文章

  1. 云环境上如何使用tensorboard
  2. 切割 Tomcat 的 catalina.out 文件,解决日志文件过大的问题
  3. 微信支付-我遇到的那些问题
  4. FGPA异步信号问题
  5. 国庆中秋活动——让孩子亲近数学并爱上数学:《数学小侦探》来袭(来自科大出版社的福利)
  6. @Transactional和@Async 使用场景
  7. shell 日期格式化输出
  8. 没有月亮的中秋,有CCNP伴我度过!
  9. ORA-12514 错误的处理
  10. CentOS7常用软件安装配置说明
  11. aws saa 认证价值大吗?aws认证指的是什么?
  12. ​NLP产业应用实战,评论观点抽取与分析和文本语义检索深度详解
  13. 网站安全公司waf防火墙的作用分析
  14. Spring BlazeDS Integration 的工作原理
  15. C# System.Data.Sqlite.dll 的注意事项
  16. 银行的atm是一台通用计算机,ATM自动取款机是不是所有银行通用的,要不...
  17. NISP二级题库总结
  18. 2021年10月TIOBE排行 榜首 Python yyds
  19. RK3588 AVS全景拼接技术案例
  20. 用Python统计中英文词频

热门文章

  1. js实现日期转换方法
  2. JAVA作业 02 JAVA语法基础
  3. 加密 解密常用的算法
  4. onpropertychange事件
  5. QUrl不同版本之间的坑
  6. 一招一式, 成就“霸业”必做的9件大事
  7. R 语言数据读取与存储
  8. 单核工作法13:永不拖延(上)
  9. Python练习:tkinter(1)
  10. 科大星云诗社动态20210417