JavaSE——面向对象高级三(5/5)-泛型方法、泛型的通配符、泛型擦除和注意事项

简介: JavaSE——面向对象高级三(5/5)-泛型方法、泛型的通配符、泛型擦除和注意事项

泛型方法

修饰符 <类型变量,类型变量,...> 返回值类型 方法名(形参列表){

}

public static <T> void test(T t){
 
}

注意:下面这种不是泛型方法

1. public E get(int index){
2. return (E) arr[index];
3. }

具体体现:

public class Test{
    public static void main(String[] args){
        test(new Dog()); //假设传入了狗对象
    }
    
    //泛型方法
    public static <T> T test(T t){  //返回值类型也为T类型
        return t;
    }
}

泛型的通配符

来看一个需求:所有汽车一起参加比赛,需要汽车类、具体的汽车品牌类,然后设计方法只能让汽车一起比赛。

现在假设已经定义了Car、BMW、BENZ类。

第一种情况:(定义总体的汽车集合,将各种汽车都放进这个集合里面)

public class Test{
    public static void main(String[] args){
        ArrayList<Car> cars = new ArrayList<>(); //创建一个汽车集合
        
        //我们可以将一辆奔驰和宝马放进这个汽车集合里面
        cars.add(new BMW());
        cars.add(new BENZ());
        //然后调用比赛的函数,没有什么问题
        go(cars);
    }
 
    public static void go(ArrayList<Car> cars){
    }
}

第二种情况:(定义不同的具体汽车集合,例如宝马车为一个集合,奔驰车为一个集合)

public class Test{
    public static void main(String[] args){
        ArrayList<Car> cars = new ArrayList<>(); //创建一个汽车集合
        
        ArrayList<BMW> bmws = new ArrayList<>(); //创建宝马车集合
        bmws.add(new BMW());
        bmws.add(new BMW()); //加入两辆宝马进入这个集合
 
        ArrayList<BENZ> benzs = new ArrayList<>(); //创建奔驰车集合
        benzs.add(new BENZ());
        benzs.add(new BENZ()); //同样加入两辆奔驰进入这个集合
 
        //此时调用比赛方法
        go(bmws);
        go(benzs); 
        //会发现报错,无法调用,数据类型不一样
    }
 
    public static void go(ArrayList<Car> cars){
    }
}

此时的ArrayList<BMW>和ArrayList<BENZ>其实和ArrayList<Car>已经没有关系了,或者说不算作是同一个数据类型了,所以无法调用传参为ArrayList<Car>的go方法。

所以就需要用到泛型方法了

对go方法进行修改:

public static <T> void go(ArrayList<T> cars){
 
}

但这个还是存在问题的,比如这个方法不仅宝马、奔驰对象可以加入,其他一些对象,比如狗(Dog)对象也可以加入;这就不符合我们的需求了。所以再稍加修改:

public static <T extends Car> void go(ArrayList<T> cars){
 
}

这就是我们限定了T能接受的类型,它只能是Car类或者是Car的子类;Dog类和其他不是Car的子类的就会被踢出去了 。

这样其实就可以满足这个需求了。

接着我们就可以引入我们的通配符知识点了

我们看这里ArrayList<T>它自己就是一个泛型类,而前面又再定义了一个泛型方法,这是没有没有必要的,Java中提供了一种方案,让我们可以解决这个问题,也就是通配符

 通配符,在使用泛型的时候可以代表一切类型

public static void go(ArrayList<? extends Car> cars){
 
}

我们在定义泛型的时候一般用E、T、K、V......但是我们使用泛型的时候,就可以用“?”来表示一切类型,这里“? extends Car”的意思就是:可以传入一切是Car或者Car子类的类型。


这种写法称为上限技术,顾名思义Car类就是它最高可以传入的类型了;与其相反的就是下限技术:(用得稍微少一点)

public static void go(ArrayList<? super Car> cars){
 
}

也就是最低也要传入Car类,往上就是Car的父类。


小结

通配符

  • 就是“?”,可以在“使用泛型”的时候代表一切类型;E T K V是在定义泛型的时候使用。

泛型的上下限

  • 泛型上限:? extends Car :?能接收的必须是Car或者其子类。
  • 泛型下限:? super Car:?能接收的必须是Car或者其父类。

泛型擦除和注意事项

泛型是工作在编译阶段的,一旦程序编译成class文件,class文件中就不存在泛型了,这就是泛型擦除。

泛型不支持基本数据类型,只能支持对象类型(引用数据类型)。

关于泛型擦除,我们要使用Java的反编译工具XJad来查看,


我们自己编写的代码在编译成class文件之后,泛型的数据类型都恢复成Object的了,底层会自己强转类型。也就是擦除了泛型。

第二点,泛型不支持基本数据类型,比如int、double,都是不支持的。

如果你非要使用基本数据类型,可以使用int类型的对象类型 Integer ,以及double类型的对象类型Double,例如:

public class Test{
    public static void main(String[] args){    
        //ArrayList<int> list1 = new ArrayList<>();
        //ArrayList<double> list1 = new ArrayList<>(); //都会报错
        
        //使用他们的对象类型就不会报错了
        ArrayList<Integer> list1 = new ArrayList<>();
        ArrayList<Double> list1 = new ArrayList<>();
    }
}

关于这些对象类型,接下来的文章会再详细了解。


至此,面向对象最核心的语法知识就全部学完了,接下来Java的学习,就是拿着这些语法知识去学习一个一个的API,API掌握得越多,Java的编程能力相对来说也就更强了,关于API的学习,前面我们学习过一些,接下来将更深入、更多地去学习。



END



目录
相关文章
|
Java C++ 索引
leetcode-541: 反转字符串 II
leetcode-541: 反转字符串 II
156 0
|
Unix Java C#
记一次对Pdfium .Net包装器的跨平台封装
PDFium 是一个开源的 PDF 渲染引擎,最初由 Google 和 Foxit Software 合作开发,并且使用 BSD 3-Clause 许可协议发布。它被设计用于在各种平台上渲染 PDF 文件,包括 Windows、macOS 和 Linux。
785 3
|
Oracle Java 关系型数据库
Java 开发者必备:JDK 版本详解与选择策略(含安装与验证)
Oracle Java SE 支持路线图显示,JDK 8(LTS)支持至2030年,非LTS版本如9-11每6个月发布且支持有限。JDK 11(LTS)支持至2032年,而JDK 17及以上版本现在提供免费商用许可。LTS版本提供长达8年的支持,每2年发布一次。Oracle JDK与OpenJDK有多个社区和公司构建版本,如Adoptium、Amazon Corretto和Azul Zulu,它们在许可证、商业支持和更新方面有所不同。个人选择JDK时,可考虑稳定性、LTS、第三方兼容性和提供商支持。
10392 26
|
DataWorks 数据管理 大数据
DataWorks操作报错合集之跨账号创建数据源时遇到报错,是什么导致的
DataWorks是阿里云提供的一站式大数据开发与治理平台,支持数据集成、数据开发、数据服务、数据质量管理、数据安全管理等全流程数据处理。在使用DataWorks过程中,可能会遇到各种操作报错。以下是一些常见的报错情况及其可能的原因和解决方法。
复现sci顶刊中的画中画(局部细节放大)
复现sci顶刊中的画中画(局部细节放大)
1989 0
|
搜索推荐 前端开发 算法
协同过滤算法|电影推荐系统|基于用户偏好的电影推荐系统设计与开发
协同过滤算法|电影推荐系统|基于用户偏好的电影推荐系统设计与开发
348 0
|
安全 前端开发 fastjson
浅谈Log4j2不借助dnslog的检测(二)
浅谈Log4j2不借助dnslog的检测
582 0
浅谈Log4j2不借助dnslog的检测(二)
|
Ubuntu
ubuntu18.04 运行时提示缺少libstdc++.so.6
解决方法:输入命令 sudo apt-get install lib32stdc++6 提示:ubuntu默认软件包管理器不是yum,而是dpkg,安装软件时用apt-get PS:在ubuntu下最好不要去装yum,不然可能会出现一些奇怪的问题
3647 0

热门文章

最新文章