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
95 0
复现sci顶刊中的画中画(局部细节放大)
复现sci顶刊中的画中画(局部细节放大)
1345 0
|
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、第三方兼容性和提供商支持。
9109 0
|
11天前
|
存储 关系型数据库 分布式数据库
PostgreSQL 18 发布,快来 PolarDB 尝鲜!
PostgreSQL 18 发布,PolarDB for PostgreSQL 全面兼容。新版本支持异步I/O、UUIDv7、虚拟生成列、逻辑复制增强及OAuth认证,显著提升性能与安全。PolarDB-PG 18 支持存算分离架构,融合海量弹性存储与极致计算性能,搭配丰富插件生态,为企业提供高效、稳定、灵活的云数据库解决方案,助力企业数字化转型如虎添翼!
|
10天前
|
存储 人工智能 搜索推荐
终身学习型智能体
当前人工智能前沿研究的一个重要方向:构建能够自主学习、调用工具、积累经验的小型智能体(Agent)。 我们可以称这种系统为“终身学习型智能体”或“自适应认知代理”。它的设计理念就是: 不靠庞大的内置知识取胜,而是依靠高效的推理能力 + 动态获取知识的能力 + 经验积累机制。
356 131
|
10天前
|
存储 人工智能 Java
AI 超级智能体全栈项目阶段二:Prompt 优化技巧与学术分析 AI 应用开发实现上下文联系多轮对话
本文讲解 Prompt 基本概念与 10 个优化技巧,结合学术分析 AI 应用的需求分析、设计方案,介绍 Spring AI 中 ChatClient 及 Advisors 的使用。
443 131
AI 超级智能体全栈项目阶段二:Prompt 优化技巧与学术分析 AI 应用开发实现上下文联系多轮对话
|
4天前
|
存储 安全 前端开发
如何将加密和解密函数应用到实际项目中?
如何将加密和解密函数应用到实际项目中?
206 138
|
10天前
|
人工智能 Java API
AI 超级智能体全栈项目阶段一:AI大模型概述、选型、项目初始化以及基于阿里云灵积模型 Qwen-Plus实现模型接入四种方式(SDK/HTTP/SpringAI/langchain4j)
本文介绍AI大模型的核心概念、分类及开发者学习路径,重点讲解如何选择与接入大模型。项目基于Spring Boot,使用阿里云灵积模型(Qwen-Plus),对比SDK、HTTP、Spring AI和LangChain4j四种接入方式,助力开发者高效构建AI应用。
405 122
AI 超级智能体全栈项目阶段一:AI大模型概述、选型、项目初始化以及基于阿里云灵积模型 Qwen-Plus实现模型接入四种方式(SDK/HTTP/SpringAI/langchain4j)