Java泛型总结(快速上手详解)

Java系列文章目录

IDEA使用指南:快速高效掌握工具的配置与技巧(必用功能,JDK,Maven等)


一、前言

目的:对泛型的笔记总结

  • 此篇是对B站博主AlbertShen讲的泛型内容进行笔记总结
  • 个人感觉讲的详细且逻辑清晰所以也进行学习总结

二、学习内容:

  • 泛型概念
  • 泛型类
  • 类型参数的约束
  • 类型安全
  • 泛型方法
  • 通配符

三、问题描述

本人想加深对泛型的理解

  • 一些课本关于泛型的知识没有简洁的实践操作

四、解决方案:

4.1 泛型概念

允许在类、接口和方法中定义类型参数,从而实现代码的复用、类型安全
可以创建一个可以处理不同数据类型的类或方法,从而避免重复代码

  • 打印整型
package org.example;

public class IntegerPrinter {

    Integer content;
    IntegerPrinter(Integer content) {
        this.content = content;
    }

    public void print() {
        System.out.println(content);
    }

}

package org.example;
public class Main {
    public static void main(String[] args) {
        IntegerPrinter printer = new IntegerPrinter(123);
        printer.print();
    }
}
  • 打印字符串
package org.example;
public class Main {
    public static void main(String[] args) {
        StringPrinter printer = new StringPrinter("Hello");
        printer.print();
    }
}
package org.example;

public class StringPrinter {

    String content;
    StringPrinter(String content) {
        this.content = content;
    }

    public void print() {
        System.out.println(content);
    }

}
  • 泛型的引入

为了减少像上面这样重复的代码我们引入泛型

  • 使用泛型就在在大括号与类名之间添加 <>
  • 外界参数可作为特殊参数传入( T 与 K )
  • 特殊参数作为泛型使用
  • 可以是任何类型参数包括

在这里插入图片描述
在这里插入图片描述

4.2 类型参数的约束

有时候不需要满足所有类型要给一个限制

4.2.1 通过extend约束参数

  1. 参数解释

类型参数必须是Machine的子类
类型参数必须实现Thing接口方法

  • Thing 也是用 extends
  • 接口Thing必须放在Machine类后面

如图所示:

在这里插入图片描述

  1. Car 继承了 Machine 同时实现了Thing接口方法

观察下面两张图

在这里插入图片描述

  • 注意不管是父类还是子类只要参数类型实现了Thing方法即可

继承了Machine类
实现了Thing接口的方法

在这里插入图片描述

4.3 类型安全

4.3.1 类型安全举例

  1. 假如现在List的泛型参数使用Object这样就可以在列表加入任何类型

这样IDEA不报错

注意:不建议这样使用

在这里插入图片描述

  1. 运行后可以显示出结果

能运行也没报错为什么不建议用呢

在这里插入图片描述

  1. 尝试获取并显示列表里面的元素

在这里插入图片描述

  1. 运行出现错误

泛型的工作方式是在编译阶段进行类型检查不是在运行阶段
IDEA不报错但是运行报错
了解下面概念

类型擦除:

  • Java 编译器会在编译时将泛型类型替换为其原始类型。
  • 比如,List<String> 会被替换为List。这就导致了在运行时,无法根据类型信息判断某个对象是否真的符合指定的泛型。

编译时类型检查:

  • 在编译阶段,编译器检查代码以确保类型安全。这意味着,它会检查所有的类型引用,确保在编译时这些类型是合法的。
  • 例如,如果你创建了一个 List<String> 对象并添加了一个字符串,编译器会允许你这么做,因为这在类型上是合法的。

运行时类型错误:

  • 由于无论是 List<String>List<Integer> 还是 List<Object> 的实际实现类在运行时都是List
  • 运行时无法区分这些具体类型。这可能导致一些运行时错误。
  • 例如,当你尝试将一个非字符串对象从一个 List<Object> 强制转换为 String 时,就会抛出 ClassCastException。

总的来说原因如下

在运行时,JVM 会检查 list.get(1) 的实际类型,发现它是 Integer,而不是 String,因此会抛出 ClassCastException。

  • 当你尝试将 Object 强制转换为 String 时,Java 编译器并不会在编译阶段检查这个转换是否合法。它不会知道 list.get(1) 实际上是一个 Integer 对象。
  • 只有在运行时,JVM 才会检查这个具体的类型,结果会因为 Integer 不能转换为 String 而抛出
    ClassCastException。

此例目标类型String 对象类型Object

在这里插入图片描述

4.3.2 强制转换概念(补充)

一个类型的对象转换为另一个类型,但只有在这两种类型之间存在合法的转换时,这种转换才是有效的。
在 Java 中,强制转换(type casting)的成功与否取决于对象的实际类型以及目标类型之间的兼容性

类型兼容性:

  • Java 类型系统要求两种类型之间有直接的关系。
  • 例如,Integer 和 String 在类型层次结构中没有直接关系,不能互相转换。
  • 只有当对象的实际类型目标类型相同或是目标类型的子类型时,强制转换才是有效的。

此例目标类型String 对象类型Integer

运行时检查:

  • Java 在运行时会检查对象的实际类型
  • 如果你尝试将一个 Integer 对象强制转换为 String,Java 会发现这两者之间没有直接的转换路径,因此会抛出ClassCastException。
Object obj = new Integer(10); // obj 实际上是 Integer  
String str = (String) obj; // 试图将 Integer 转换为 String
  • 当你执行到 String str = (String) obj; 阶段时
  • Java 虚拟机会检查 obj 中实际存储的数据类型(即Integer)。
  • 由于 Integer 和 String 是不兼容的类型,JVM 会检测到这一点并抛出 ClassCastException。
Object obj = "Hello"; // obj 是 String 类型  
String str = (String) obj; // 成功转换

不能直接将一个对象强制转换为与其实际类型无关的类型,因为这没有逻辑上的支持,也违反了 Java 的类型安全

4.4 泛型方法与通配符

T是占位符

在这里插入图片描述

加上< T >告诉Java这是泛型

注意结构

在这里插入图片描述

跟之前一样可以用多个参数或者继承

在这里插入图片描述

  • 每次使用都要换比较麻烦所以引入泛型

在这里插入图片描述

  • 通配符传参

在这里插入图片描述
在这里插入图片描述

  • Super 与 Extends 的使用

在这里插入图片描述


五、总结:

5.1 学习总结:

  • 泛型概念:主要为了解决重复代码问题
  • 泛型类:学会使用 <> 与多参数的使用
  • 类型参数的约束:extends
  • 类型安全:注意类型转换问题
  • 泛型方法:<> 在 static 与 void 之间
  • 通配符:掌握通配符 ?与 extends

(后续有遇到问题再添加)


声明:如本内容中存在错误或不准确之处,欢迎指正。转载时请注明原作者信息(麻辣香蝈蝈)。

  • 17
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值