尧图精选

JavaSE加强:异常、泛型、集合框架吗,,

🕒 发布时间:2026/9/25 19:14:04 📁 来源:尧图网络
一、异常异常程序出现的非正常情况会终止程序正常执行。Java 异常顶层父类Throwable分为两大分支Error系统级错误、Exception代码级异常1. 运行时异常RuntimeException特点编译不报错运行才报错可处理可不处理又叫非受检异常NullPointerException 空指针异常引用变量为 null调用方法/属性触发IndexOutOfBoundsException 索引越界异常数组、字符串、集合索引超出范围ArrayIndexOutOfBoundsException 数组越界ClassCastException 类型转换异常2. 编译时异常除Runtime外所有异常特点编译阶段直接报错必须处理否则无法运行又叫受检异常常见文件异常、IO异常、日期解析异常、网络异常3. 异常两种处理方式try-catch捕获异常程序可以继续运行throws抛出异常交给上层调用者处理4. 自定义异常继承 RuntimeException自定义运行异常/** * 自定义运行时异常不需要编译强制处理 */ public class BusinessRuntimeException extends RuntimeException { // 无参构造 public BusinessRuntimeException() { super(); } // 带异常信息 public BusinessRuntimeException(String message) { super(message); } // 异常信息 原始异常对象包装根源异常 public BusinessRuntimeException(String message, Throwable cause) { super(message, cause); } }使用演示public class TestRuntimeEx { public static void main(String[] args) { int age -5; if(age 0){ // 抛出运行时异常编译不会报错不用强制try‑catch throw new BusinessRuntimeException(年龄不能为负数当前 age); } } }继承 Exception自定义编译异常/** * 自定义编译期受检异常 */ public class CheckBusinessException extends Exception { public CheckBusinessException() { super(); } public CheckBusinessException(String message) { super(message); } public CheckBusinessException(String message, Throwable cause) { super(message, cause); } }使用演示public class TestCheckEx { // 受检异常必须throws声明否则编译报错 public static void checkScore(int score) throws CheckBusinessException{ if(score 0 || score 100){ throw new CheckBusinessException(分数必须0‑100之间输入score); } } public static void main(String[] args) { try { checkScore(120); } catch (CheckBusinessException e) { e.printStackTrace(); } } }5.处理异常的方法方案一层层上抛最外层捕获异常记录下异常信息并影响用户观看的信息进行提示自定义异常沿用上面//自定义运行时业务异常 public class BusinessRuntimeException extends RuntimeException{ public BusinessRuntimeException(String message) { super(message); } }底层 DAO/Service 层只抛异常不处理public class UserService { /** * 查询用户出现问题向上抛出本方法不捕获 */ public void queryUser(Integer userId) { if(userId null || userId 0){ //业务出错抛出自定义异常向上抛 throw new BusinessRuntimeException(用户ID非法); } if(userId 999){ throw new BusinessRuntimeException(该用户账号已被封禁); } System.out.println(查询用户成功); } }中间层继续向上抛不捕获public class UserController { private UserService userService new UserService(); //这里不写try-catch异常继续向外抛给调用者main public void getUserInfo(Integer userId){ userService.queryUser(userId); } }最外层 (main) 统一捕获打印日志 用户友好提示public class MainTest { public static void main(String[] args) { UserController controller new UserController(); Integer userId -2; try { //调用异常会从service→controller→抛到这里 controller.getUserInfo(userId); }catch (BusinessRuntimeException e){ //①记录完整异常信息给开发人员排查问题日志生产环境用log System.out.println(【系统日志开发看】异常堆栈信息); e.printStackTrace(); //②给用户看的提示简洁友好不能输出堆栈 System.out.println(【给用户提示】操作失败e.getMessage()); }catch (Exception e){ //兜底捕获所有其他未知异常 System.out.println(【系统日志】未知异常); e.printStackTrace(); System.out.println(【给用户提示】系统繁忙请稍后重试); } } }输出结果【系统日志开发看】异常堆栈信息 com.xxx.BusinessRuntimeException: 用户ID非法 at UserService.queryUser(UserService.java:8) ... 【给用户提示】操作失败用户ID非法方案二最外层捕获异常后尝试重新修复示例模拟网络请求捕获异常后重试修复//自定义运行时异常 class NetworkException extends RuntimeException{ public NetworkException(String msg){ super(msg); } } public class NetService { private int failCount 0; //模拟网络失败次数 //模拟调用远程网络接口偶尔会网络异常 public void callRemoteApi(){ failCount; //模拟前2次网络报错第3次成功 if(failCount 2){ throw new NetworkException(网络连接失败连接超时); } System.out.println(远程接口调用成功获取数据完成); } }最外层捕获异常尝试修复重试public class RetryMain { public static void main(String[] args) { NetService netService new NetService(); int maxRetry 3; //最大重试次数 int current 0; while(current maxRetry){ try { netService.callRemoteApi(); //正常执行无异常修复成功跳出循环 System.out.println(✅操作完成无需重试); break; }catch (NetworkException e){ current; if(current maxRetry){ //达到最大重试修复失败返回用户错误 System.out.println(【日志】多次重试仍然失败); e.printStackTrace(); System.out.println(【给用户】网络异常请检查网络后再尝试); }else{ //捕获异常执行修复操作休眠等待然后重试 System.out.printf(⚠️捕获异常%s开始第%d次重试修复%n,e.getMessage(),current); try { Thread.sleep(1000); //等待1秒模拟修复等待网络恢复 } catch (InterruptedException ie) { ie.printStackTrace(); } } }catch (Exception e){ //其他不可预期异常无法修复直接结束 e.printStackTrace(); System.out.println(【给用户】系统发生未知错误); break; } } } }输出效果⚠️捕获异常网络连接失败连接超时开始第1次重试修复 ⚠️捕获异常网络连接失败连接超时开始第2次重试修复 远程接口调用成功获取数据完成 ✅操作完成无需重试二、泛型 Generic1. 作用统一集合存储的数据类型集合中只能存放指定类型数据避免向下转型时出现类型转换异常 ClassCastException编译阶段做类型校验编译期就发现类型错误提高代码安全性没有泛型时集合存 Object取出来需要强制类型转换极易报类型转换异常。2. 使用格式标准格式集合数据类型 对象名 new 集合数据类型();示例ListString list new ArrayListString();JDK7 钻石语法JDK7 及以后右边的泛型类型可以省略只写一对尖括号 钻石语法ListString list new ArrayList();⚠️注意不是返回 Object编译期会根据左边String推导右边类型运行时擦除为 Object。3. 泛型特点泛型尖括号内只能写引用类型不能写基本数据类型基本类型必须使用对应的包装类✅ListInteger❌Listint泛型只在编译阶段生效运行阶段会发生泛型擦除全部变为 Object。泛型是编译期语法糖JVM 运行看不到泛型信息。不写泛型就是裸类型默认当作Object处理//裸泛型等价于ListObject List list new ArrayList(); list.add(abc); list.add(123);4. 通配符?通配符一般用于方法参数用来接收多种泛型类型的集合不能 add 添加元素。List?无限定通配符可以接收任意泛型类型的 Listpublic void show(List? list){ //可以获取元素取出是Object不能add除了null Object o list.get(0); }List? extends Animal上限通配符含义只能接收Animal或者Animal 的子类集合规则可以获取元素不能添加元素// Dog Cat 继承 Animal public void test(List? extends Animal list){ Animal a list.get(0); //获取没问题 //list.add(new Dog()); //报错不能添加 }List? super Animal下限通配符含义只能接收Animal或者Animal 的父类集合规则可以存 Animal 以及它的子类对象获取出来只能是 Objectpublic void test(List? super Animal list){ list.add(new Dog()); //可以存Animal子类 Object obj list.get(0); //取出只能用Object接收 }记忆口诀? extends T上界取元素可以存元素不行? super T下界存元素可以取元素只能 Object5. 自定义泛型类类名后面E,T,K,V定义泛型符号符号只是占位符大写字母习惯。 EElement 元素TType 类型返回值KKey 键VValue 值/** * 自定义泛型类 * TT是占位符创建对象的时候确定真实类型 */ public class MyGenericT { private T data; public T getData() { return data; } public void setData(T data) { this.data data; } }使用创建对象时指定真实类型// T替换为String MyGenericString g1 new MyGeneric(); g1.setData(张三); String s g1.getData(); // T替换为Integer MyGenericInteger g2 new MyGeneric(); g2.setData(100);如果创建对象不指定泛型T 就变为 Object。6. 自定义泛型接口接口上定义泛型T两种实现方式//泛型接口 public interface MyInterfaceT { void show(T t); }方式 1实现类确定具体类型//实现类直接写死类型TString public class Impl1 implements MyInterfaceString{ Override public void show(String s) { System.out.println(s); } }方式 2实现类继续保留泛型创建对象时确定类型//实现类也带上T把泛型继续传递 public class Impl2T implements MyInterfaceT{ Override public void show(T t) { System.out.println(t); } } //使用 Impl2Integer impl new Impl2(); impl.show(666);7. 自定义泛型方法方法上单独定义泛型跟类的泛型无关写在返回值前面Tpublic class MyUtil { //泛型方法T写在返回类型前面 public T void print(T t){ System.out.println(t); } //有返回值的泛型方法 public T T getObj(T t){ return t; } }调用时传入什么参数编译器自动推导 T 的类型MyUtil util new MyUtil(); util.print(hello); //TString util.print(999); //TInteger三、集合框架重点集合存储多个引用类型对象的容器长度可变功能比数组更强大。集合两大根接口Collection、Map1. Collection 单列集合存单个元素1List 接口有序、可重复、有索引ArrayList底层数组根据索引查询快、增删慢线程不安全开发最常用ListString namesnew ArrayList();LinkedList底层链表增删快、查询慢适合频繁增删数据2Set 接口无序、不可重复、无索引HashSet底层哈希表去重、无序效率高 去重依赖hashCode() equals()LinkedHashSet保留存储顺序不可重复2. Map 双列集合存键值对key-valuekey 唯一、value 可重复、无序HashMap底层哈希表查询增删极快线程不安全开发首选LinkedHashMap保留键值对存储顺序3. 集合通用方法所有Collection都有add()添加元素remove()删除元素contains()判断是否包含元素size()获取集合元素个数clear()清空集合isEmpty()判断是否为空4. 集合遍历方式普通for循环有索引集合增强for循环所有单列集合//增强for循环(既可以遍历数组也可以遍历集合) //本质是遍历迭代器的简化写法 ArrayListString namesnew ArrayList(); for(String name:names){ System.out.pringtln(name); }迭代器 Iterator通用遍历可遍历同时删除ArrayListString namesnew ArrayList(); IteratorString itnames.iterator(); while(it.hasNext()){ String nameit.next(); System.out.println(name); }//迭代器只能遍历集合Lambda表达式public interface IterableT{ default void forEach(Consumer? super T action){ objects.requireNoNull(action);//判断集合是否为空 for(T t:this){ action.accept(t); } } } public class a{ ArrayListString namesnew ArrayList(); //写法一 names.forEach(new ConsumerString(){ Override public void accept(String s){ System.out.println(s); } }); //写法二 names.forEach(s-System.out.println(s)); //写法三 names.forEach(System.out::println); }当遍历集合时又存在增删集合元素的行为时可能出现业务异常这种现象便称为并发修改异常问题5. 数组和集合区别数组长度固定可以存基本类型/引用类型集合长度可变只能存引用类型
上一篇/下一篇内容由系统自动关联 返回资讯列表 →