读懂代码中的<>
哈喽各位大一的小伙伴刚接触Java进阶内容大家一定在集合、类、方法里见过无数次符号比如ArrayListString、HashMapK,V。很多人初学只会照搬代码却完全不懂这个尖括号到底是什么、有什么用。今天这篇博客专门为大一新生拆解Java泛型核心知识从零搞懂泛型的作用、用法和底层逻辑全程无晦涩源码通俗易懂看完就能直接上手写代码一、什么是泛型通俗理解首先抛开书本官方定义给大家一个最直白的解释泛型就是“类型参数”让类、方法、接口可以适配任意数据类型实现代码通用同时固定类型、杜绝类型混乱。我们写普通代码时变量、方法的参数类型都是固定的比如int、String一个方法只能处理一种类型的数据。但泛型相当于给代码开了一个“万能模板”不提前指定具体类型在使用时再确定类型。既可以复用一套代码处理不同数据类型又不会丢失类型安全性。二、为什么需要泛型没有泛型会怎样很多同学疑惑我不用泛型也能写代码为什么非要学它我们通过一段无泛型的代码痛点案例瞬间看懂泛型的价值。1. 没有泛型集合存储任意类型存在安全隐患Java中集合默认可以存储所有Object类型数据也就是任意对象。import java.util.ArrayList; public class GenericTest { public static void main(String[] args) { // 无泛型集合可以存任意类型数据 ArrayList list new ArrayList(); list.add(Java学习); list.add(123); list.add(3.14); // 取值时需要强制类型转换 String str (String) list.get(0); System.out.println(str); // 运行报错类型转换异常 String num (String) list.get(1); } }痛点总结存储无限制可以同时存字符串、数字、小数数据杂乱取值强转繁琐每次取值都要手动类型转换代码冗余编译不报错运行报错最致命语法没问题运行程序直接崩溃2. 有泛型全程类型安全代码更简洁我们用泛型改造上面的代码指定集合只能存储String类型import java.util.ArrayList; public class GenericTest { public static void main(String[] args) { // 泛型指定该集合只能存储String类型 ArrayListString list new ArrayList(); list.add(Java学习); // 编译直接报错无法存入非String类型数据 // list.add(123); // 无需强转直接取值 String str list.get(0); System.out.println(str); } }泛型核心优势大一必记类型安全错误在编译阶段就被发现不会拖到运行时省去强转取值自动匹配类型简化代码代码复用一套逻辑适配多种数据类型三、泛型核心符号新手必认Java泛型有固定的占位符符号都是大写单个字母含义固定不用死记记住常用的即可T (Type)代表任意数据类型最常用K (Key)代表键类型多用于MapV (Value)代表值类型多用于MapE (Element)代表集合元素类型多用于List、Set四、泛型三大核心用法新手入门重点泛型主要分为泛型类、泛型方法、泛型接口逐个手把手教大家掌握。1. 泛型类在类定义时定义泛型整个类内部都可以使用该类型适合通用工具类场景。语法格式public class 类名T {}实战案例自定义一个通用的容器类可以存储任意类型数据// 定义泛型类T为未知类型 public class ContainerT { // 使用泛型定义成员变量 private T data; // 泛型参数方法 public void setData(T data) { this.data data; } // 泛型返回值方法 public T getData() { return data; } } // 测试类 class Test { public static void main(String[] args) { // 指定泛型为String类型 ContainerString strContainer new Container(); strContainer.setData(大一学Java泛型); System.out.println(strContainer.getData()); // 指定泛型为Integer类型 ContainerInteger intContainer new Container(); intContainer.setData(2026); System.out.println(intContainer.getData()); } }核心特点创建对象时确定泛型类型一旦确定全程类型固定。2. 泛型方法方法单独定义泛型优先级高于类泛型适合某个方法需要通用、类不需要通用的场景。语法格式public T 返回值类型 方法名(T 参数) {}实战案例写一个通用的打印方法支持任意类型参数public class GenericMethod { // 定义泛型方法 public static T void printInfo(T t) { System.out.println(数据内容 t); System.out.println(数据类型 t.getClass().getSimpleName()); } public static void main(String[] args) { // 自动匹配任意类型 printInfo(Java泛型方法); printInfo(666); printInfo(3.1415); } }运行结果会自动识别字符串、整数、小数类型真正实现一个方法适配所有类型。3. 泛型接口接口中定义泛型实现类可以指定具体类型保持接口的通用性集合框架中大量使用List、Map都是泛型接口。语法格式public interface 接口名T {}实战案例// 定义泛型接口 public interface GenericInterfaceT { void show(T t); } // 实现类指定具体泛型类型为String class StringImpl implements GenericInterfaceString { Override public void show(String s) { System.out.println(字符串内容 s); } } // 实现类指定具体泛型类型为Integer class IntegerImpl implements GenericInterfaceInteger { Override public void show(Integer num) { System.out.println(数字内容 num); } }五、新手必懂泛型通配符 ?我们在看源码或别人代码时经常看到List?这个?就是泛型通配符代表任意未知类型。1. 无界通配符 ?List?可以接收任意泛型类型的集合适合只读取数据、不修改数据的场景。2. 上限通配符 ? extends T代表只能接收T类型及T的子类比如? extends Number可以接收Integer、Double、Long等数字类型。3. 下限通配符 ? super T代表只能接收T类型及T的父类使用场景相对较少了解即可。六、大一新手常见误区避坑指南误区1泛型不能用基本数据类型泛型只能存引用类型必须用包装类Integer、Double、Boolean不能用int、double误区2泛型不参与编译泛型是编译期机制运行时会被擦除泛型擦除目的是兼容旧版本Java代码误区3随意使用通配符通配符多用于参数接收日常自定义类和方法优先用T、E、K、V不要滥用?七、总结新手学泛型记住这4句话泛型的核心是模板复用类型安全T/E/K/V是类型占位符使用时才确定具体类型泛型类适配全局类型泛型方法适配单个方法? 是通配符代表任意未知类型多用于参数接收总的来说泛型是Java进阶的基础核心也是集合框架、框架开发的必备知识点。大一刚开始学不用深究底层擦除原理先熟练掌握基础用法能看懂、会写泛型代码后续进阶会轻松很多