异常
异常
抽象类和接口的异同?
相同点:不能实例化;都可以包含抽象方法的。
不同点:
1)把抽象聪和接口的定义、内部结构 ,解释说明
2)
- 类:单继承性
- 接口:多继承
- 类与接口:多实现
工厂的设计模式
1.解决的问题
实现了创建者与调用者的分离,即将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的。
2.具体模式
- 简单工厂模式:用来生产同一等级结构中的任意产品。(对于增加新的产品,需要修改已有代码)
- 工厂方法模式:用来生产同一等级结构中的固定产品。(支持增加任意产品
- 抽象工厂模式:用来生产不同产品族的全部产品。(对于增加新的产品,无能为力﹔支持增加产品族
package com.xin.OOPTest.demo09;
public class Day72700 {
public static void main(String[] args) {
Day72700 day72700 = new Day72700();
day72700.method();
}
/*
在局部内部类的方法中(比如: show)如果调用局部内部类所声明的方法(比如: method )中的局部变量(比如:num)
要求此局部变量声明为final的。
jdk 7及之前版本:要求此局部变量显式的声明为final的
jdk 8及之后的版本:可以省略final的声明
*/
public void method(){
int num=10;
class AA{
public void show(){
// num=20;
System.out.println(num);
}
}
System.out.println(num);
}
}
7.1异常概述与异常体系结构
- 异常:在Java语言中,将程序执行中发生的不正常情况称为“异常(开发过程中的语法错误和逻辑错误不是异常)
- Java程序在执行过程中所发生的异常事件可分为两类:
- Error: Java虚拟机无法解决的严重问题。如:JVM系统内部错误、资源耗尽等严重情况。比如:StackOverflowError(栈溢出)和OOM(堆溢出)。一般不编写针对性的代码进行处理。
- Exception:其它因编程错误或偶然的外在因素导致的一般性问题,可以使用针对性的代码进行处理。例如:
- 空指针访问
- 试图读取不存在的文件
- 网络连接中断
- 数组角标越界
- 对于这些错误,一般有两种解决方法:一是遇到错误就终止程序的运行。另一种方法是由程序员在编写程序时,就考虑到错误的检测、错误消息的提示,以及错误的处理。
- 捕获错误最理想的是在编译期间,但有的错误只有在运行时才会发生。比如:除数为0,数组下标越界等
- 分类:编译时异常和运行时异常
一、异常体系结构
java.lang.Throwable
l-----java.lang.Error:一般不编写针对性的代码进行处理。
异常的处理:抓抛模型
-
过程一:"抛":程序在正常执行的过程中,一旦出现异常,就会在异常代码处生成一个对应异常类的对象。并将此对象抛出。—旦抛出对象以后,其后的代码就不再执行。
关于异常对象的产生:
- 系统自动生成的异常对象
- 手动的生成—个异常对象,并抛出throw
-
过程二:"抓":可以理解为异常的处理方式:1 try-catch-finally throws
二、 try-catch-finally的使用
try{
//可能出现异常的代码}
catch(异常类型1变量名1){
//处理异常的方式1
}catch(异常类型2变量名2){
//处理异常的方式2
}catch(异常类型3变量名3){
//处理异常的方式3
}
finally{
//一定会执行的代码
}
说明:
-
finally是可选的。
-
使用try将可能出现异常代码包装起来,在执行过程中,一旦出现异常,就会生成一个对应异常类的对象,根据此对象的类型,去catch中进行匹配
-
一旦try中的异常对象匹配到某一个catch时,就进入catch中进行异常的处理。一旦处理完成,就跳出当前的try-catch结构(在没有写finally的情况)。继续执行其后的代码
-
catch中的异常类型如果没有子父类关系,则谁声明在上,谁声明在下无所谓。
catch中的异常类型如果满足子父类关系,则要求子类一定声明在父类的上面。否则,报错 -
常用的异常对象处理的方式: String getMessage(), printstack
-
在try结构中声明的变量,再出了try结构以后,就不能再被调用
-
try-catch-finally结构可以嵌套
体会:
- 使用try-catch-finally处理编译时异常,是得程序在编译时就不再报错,但是运行时仍可能报错。
相当于我们使用try-catch-finally将一个编译时可能出现的异常,延迟到运行时出现。 - 体会2:开发中,由于运行时异常比较常见,所以我们通常就不针对运行时异常编写try-catch-finally了.
针对于编译时异常,我们说一定要考虑异常的处理。
package com.xin.exception;
public class Day72700 {
public static void main(String[] args) {
String str="123";
str="abc";
try{
int num=Integer.parseInt(str);
System.out.println("11111111111");//不能输出
}catch(NumberFormatException e){
System.out.println("出现数值转化异常");
System.out.println(e.getMessage());//For input string: "abc"
//e.printStackTrace();
}catch (NullPointerException e){
System.out.println("出现空指针异常");
}
System.out.println("22222222222222");//能输出
}
}
try-catch-finally中finally的使用:
- finally是可选的
- finally中声明的是一定会被执行的代码。即使catch中又出现异常了,try中有return语句,catch中有return语句等情况。
- 像数据库连接、输入输出流、网络编程Socket等资源,JVM是不能自动的回收的,我们需要自己手动的进行资源的释放。此时的资源释放,就需要声明在finally中。
package com.xin.exception;
public class Day72701 {
public static void main(String[] args) {
try{
int a=10;
int b=0;
System.out.println(a/b);
}catch (ArithmeticException e){
e.printStackTrace();
int a=1/0;// by zero
}catch (Exception e){
e.printStackTrace();
}finally{
System.out.println("文件号i");
}
}
}
异常处理的方式二:throws +异常类型
- "throws +异常类型"写在方法的声明处。指明此方法执行时,可能会抛出的异常类型。
一旦当方法体执行时,出现异常,仍会在异常代码处生成一个异常类的对象,此对象满足throws后异常类型时,就会被抛出。异常代码后续的代码,就不再执行!
2.体会:
-
try-catch-finally:真正的将异常给处理掉了。
-
throws的方式只是将异常抛给了方法的调用者。并没有真正将异常处理掉。
3.开发中如何选择使用try-catch-finally 还是使用throws ?
- 如果父类中被重写的方法没有throws方式处理异常,则子类重写的方法也不能使用throws,意味着如果
子类重写的方法中有异常,必须使用try-catch-finally方式处理。 - 执行的方法a中,先后又调用了另外的几个方法,这几个方法是递进关系执行的。我们建议这几个方法使用throw的方式进行处理。而执行的方法a可以考虑使用try-catch-finally方式进行处理。
package com.xin.exception;
import java.io.FileNotFoundException;
import java.io.IOException;
public class Day72702 {
public static void main(String[] args) {
Day72702 day72702 = new Day72702();
day72702.display(new SubClass());
}
public void display(SuperClass s){
try {
s.methed();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
class SuperClass{
public void methed()throws IOException{
}
}
class SubClass extends SuperClass{
@Override
public void methed() throws FileNotFoundException {
}
}
package com.xin.exception;
public class Day72703 {
public static void main(String[] args) {
Student student = new Student();
student.regist(-101);
System.out.println(student);
}
}
class Student{
private int id;
public void regist(int id){
if (id>0){
this.id=id;
}else {
// System.out.println("输入数据非法");//Student{id=0}可以输出
throw new RuntimeException("输入数据非法");//Student{id=0}不能输出
}
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
'}';
}
}
改进
package com.xin.exception;
public class Day72703 {
public static void main(String[] args) {
Student student = new Student();
try {
student.regist(-101);
System.out.println(student);////Student{id=0}不能输出
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
class Student{
private int id;
public void regist(int id) throws Exception {
if (id>0){
this.id=id;
}else {
// System.out.println("输入数据非法");//Student{id=0}可以输出
//throw new RuntimeException("输入数据非法");//Student{id=0}不能输出
throw new Exception("输入数据非法");
}
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
'}';
}
}
如何自定义异常类?
- 继承于现有的异常结构:RuntimeException . Exception
- 提供全局常量: serialVersionUID
- 提供重载的构造器
package com.xin.exception.demo01;
/**
* 自定义异常类
*/
public class EcDef extends Exception{
static final long serialVersionUID = -338751624229948L;
public EcDef(String message) {
super(message);
}
public EcDef() {
}
}
============
package com.xin.exception.demo01;
/*
编写应用程序EcmDef.java,接收命令行的两个参数,要求不能输入负数,计算两数相除。
对数据类型不一致(NumberFormatException)、缺少命令行参数(ArrayIndexOutOFBoundsException、
除0(ArithmeticException)及输入负数(EcDef 自定义的异常)进行异常处理。
*/
public class EcmDef {
public static void main(String[] args) {
String[] a=new String[2];
a[0]="112";
a[1]="55";
try {
int i=Integer.parseInt(a[0]);
int j=Integer.parseInt(a[1]);
int result = ecm(i ,j);
System.out.println(result);
} catch (NumberFormatException e) {
System.out.println("数据类型不一致");
}catch (ArrayIndexOutOfBoundsException e){
System.out.println("缺少命令行参数");
}catch (ArithmeticException e){
System.out.println("除0");
}catch (EcDef e){
System.out.println(e.getMessage());
}
}
public static int ecm(int i,int j) throws EcDef {
if (i<0||j<0){
throw new EcDef("分子或分母为负数了");
}
return i/j;
}
}
补充:
方法重写的规则之一:
子类重写的方法抛出的异常类型不大于父类被重写的方法抛出的异常类型
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?