学习日志03 java
最近有点懈怠了,多多实践,多敲代码,多多专注!
1 ArithmeticException
ArithmeticException
是 Java 中的一个异常类,它继承自 RuntimeException
,用于表示在算术运算中出现的错误。这个异常通常在以下情况下抛出:
-
整数除以零:当你尝试用一个整数(如
int
、long
等)除以零时,会抛出ArithmeticException
。java
int result = 10 / 0; // 这行代码会抛出 ArithmeticException
-
模运算(取余)中除数为零:同样,整数的模运算中如果除数是零,也会抛出此异常。
java
int remainder = 10 % 0; // 这行代码也会抛出 ArithmeticException
-
其他情况:在极少数情况下,某些库或自定义代码可能会显式抛出这个异常,但最常见的场景还是整数除零。
注意事项
-
浮点数除零:对于浮点数(如
float
和double
),除以零不会抛出异常,而是返回无穷大(Infinity
)或 NaN(Not a Number)。java
double result = 10.0 / 0.0; // 返回 Infinity double invalid = 0.0 / 0.0; // 返回 NaN
-
如何避免:在进行除法或模运算前,应先检查除数是否为零。
java
int divisor = 0; if (divisor != 0) {int result = 10 / divisor; } else {System.out.println("除数不能为零"); }
-
异常处理:如果你无法在代码中预先检查除数是否为零,可以使用
try-catch
块捕获异常。java
try {int result = 10 / divisor; } catch (ArithmeticException e) {System.out.println("发生算术异常: " + e.getMessage()); }
总结
ArithmeticException
主要用于处理整数运算中的除零错误,是一个运行时异常(不需要显式捕获)。在编写代码时,建议通过条件判断避免除零操作,或使用异常处理机制增强程序的健壮性。
2 java里面的异常体系结构
写捕获异常的时候要从小到大写,要不然会被覆盖。
3 throw new RuntimeException(e);
的含义
package Exception;public class Test2 {public static void main(String[] args) {int a =1;int b =0;try {System.out.println(a/b);} catch (Exception e) {throw new RuntimeException(e);} finally {}}
}
throw new RuntimeException(e);
的含义是把捕获到的异常 e
封装成一个新的运行时异常 RuntimeException
,然后再次抛出。
---------------------------------------------------------------------------------------------------------------------------------Q:new出来的这个异常对象是我随便想叫什么名字的吗?(・∀・(・∀・(・∀・*)
A:在 Java 里,通过new
关键字创建异常对象时,异常变量的命名规则和普通变量是一样的。也就是说,你能按照自己的想法来命名,不过为了保证代码的可读性,一般会使用能体现异常类型或者含义的名称。
=========================================================================
这里的 e
是原始异常对象,作为参数传入,它会成为新异常的原因(cause)。这种做法被称作异常包装或者异常链。
为什么要进行异常包装?
- 隐藏底层实现细节:假设你设计的是一个数据库工具类,当出现
SQLException
时,你不想让上层调用者直接处理这个特定的数据库异常,于是将其包装成更通用的RuntimeException
。 - 异常类型转换:受检查异常(像
IOException
)无法直接抛出,这时可以把它包装成运行时异常,从而避免进行throws
声明。 - 添加更多上下文信息:你可以创建自定义的异常类,然后把原始异常包装在其中,为异常处理提供更多的信息。
异常包装的示例
下面是一个简单的工具类示例,展示了如何使用异常包装:
public class FileUtils {public static String readFile(String path) {try {return Files.readString(Path.of(path));} catch (IOException e) {// 将受检查异常包装成运行时异常throw new RuntimeException("读取文件失败: " + path, e);}}
}
处理包装后的异常
在调用栈的上层,你可以捕获这个包装后的异常,并且通过 getCause()
方法获取原始异常:
java
try {FileUtils.readFile("nonexistent.txt");
} catch (RuntimeException e) {System.err.println("发生错误: " + e.getMessage());// 获取原始异常Throwable originalCause = e.getCause();if (originalCause instanceof IOException) {System.err.println("原始错误: 文件不存在");}
}
你提供的代码存在的问题
在你的代码里,捕获到 ArithmeticException
后又把它包装成 RuntimeException
抛出,这是多此一举的。因为 ArithmeticException
本身就是运行时异常,完全可以直接抛出。更合适的处理方式应该是:
java
try {System.out.println(a/b);
} catch (ArithmeticException e) {System.err.println("除数不能为零!");// 或者记录日志// logger.error("除数为零", e);
}
总结来说,异常包装是一种很有用的技巧,但要根据具体场景合理运用。在你的代码中,这样的包装并没有实际价值。
4 有关new出来的异常对象的命名
变量命名规范
下面是一些常见的命名方式:
java
try {// 执行可能会抛出异常的代码
} catch (ExceptionType e) { // 通常使用单个字母,像e、exthrow new RuntimeException("错误信息", e);
}// 或者使用更具描述性的名称
try {// ...
} catch (FileNotFoundException fileNotFoundEx) {throw new RuntimeException("文件未找到", fileNotFoundEx);
}// 也可以使用全小写加下划线的形式(不过这种方式不太常用)
try {// ...
} catch (SQLException sql_exception) {// ...
}
命名建议!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- 保持简洁:使用
e
、ex
或者简单的描述,例如fileError
。 - 类型清晰:命名要能体现异常的类型,比如
networkException
、parseError
。 - 避免重复:不要使用和已有变量相同的名称。
异常类名与变量名的区别
需要注意的是,异常类名(像RuntimeException
)是固定的,必须使用已有的类或者自定义类,而异常对象的变量名(如e
)则可以自由命名。
java
// 正确:使用已有的异常类,变量名可自由选择
catch (Exception e) {throw new MyCustomException("自定义错误", e); // MyCustomException 是自定义的异常类
}// 错误:不能随意编造异常类名
catch (Exception e) {throw new MyRandomException(); // 编译会报错,因为 MyRandomException 类不存在
}
总结
你可以自由命名异常对象的变量,但异常类名必须是已存在的类。建议采用简洁且能描述异常性质的命名方式,比如:
java
try {int result = divide(1, 0);
} catch (ArithmeticException divisionError) {throw new RuntimeException("除法运算失败", divisionError);
}
5 介绍throw和throws
throw
和 throws
是 Java 中用于处理异常的两个关键字,它们的主要区别在于位置和用途:
一、基本用法
1. throw
(主动抛出异常)
- 位置:用在方法内部,用于主动抛出一个异常对象。
- 语法:
throw new ExceptionType("错误信息");
- 示例:
java
public void divide(int a, int b) {if (b == 0) {throw new ArithmeticException("除数不能为零"); // 主动抛出异常}System.out.println(a / b); }
2. throws
(声明异常)
- 位置:放在方法签名后面,用于声明该方法可能会抛出的异常。
- 语法:
returnType methodName(params) throws ExceptionType1, ExceptionType2... { ... }
- 示例:
java
public void readFile(String path) throws FileNotFoundException {File file = new File(path);if (!file.exists()) {throw new FileNotFoundException("文件不存在"); // 抛出异常}// ... }
二、核心区别
---------------------------------------------------------------------------------------------------------------------------------
对比项 | throw | throws |
---|---|---|
位置 | 方法内部 | 方法签名后面 |
作用 | 主动抛出一个异常对象 | 声明方法可能抛出的异常类型 |
语法 | throw new Exception(...); | void method() throws Exception {...} |
异常类型 | 只能抛出一个具体的异常对象 | 可以声明多个异常类型,用逗号分隔 |
处理要求 | 必须被捕获(try-catch )或继续向上抛出 | 调用者必须处理受检查异常(Checked Exception) |
三、联系与配合
-
受检查异常必须配合
throws
:- 如果方法内部抛出受检查异常(如
IOException
),则必须在方法签名中用throws
声明。
java
public void writeFile() throws IOException { // 必须声明 throwsFileWriter writer = new FileWriter("test.txt");// ... }
- 如果方法内部抛出受检查异常(如
-
异常传递链:
throw
抛出的异常可以通过throws
层层向上传递,直到被try-catch
捕获。
java
public void methodA() throws IOException {throw new IOException("文件错误"); // 抛出异常 }public void methodB() throws IOException {methodA(); // 未处理异常,继续向上抛 }public void methodC() {try {methodB(); // 最终捕获异常} catch (IOException e) {e.printStackTrace();} }
四、常见误区
-
throw
后不能有后续代码:java
public void test() {throw new RuntimeException();System.out.println("永远执行不到"); // 编译错误! }
-
throws
不负责处理异常:throws
只是声明异常,真正的处理(try-catch
)要在调用链的上层完成。
-
运行时异常(RuntimeException)不强制要求
throws
:java
public void divide(int a, int b) {if (b == 0) {throw new ArithmeticException(); // 无需声明 throws} }
五、总结
throw
:用于 “制造” 异常,是异常的源头。throws
:用于 “传递” 异常,提醒调用者处理潜在的异常。- 配合使用:当方法内部
throw
受检查异常时,必须用throws
声明;调用者可以继续throws
或用try-catch
捕获。
6 自定义异常在实际应用中的经验总结
1 处理运行时异常时,采用逻辑去合理规避同时辅助 try-catch 处理
2 在多重 catch 块后面,可以加一个 catch (Exception)(放一个最大的异常哈) 来处理可能会被遗漏的异常
3 对于不确定的代码,也可以加上 try-catch,处理潜在的异常(IDE一般会报错,这个时候呢alt + enter 可以自动提示)
4 尽量去处理异常,增加一些处理异常的代码块!!切忌只是简单地调用 printStackTrace () 去打印输出(这个是默认的处理哈)
5具体如何处理异常,要根据不同的业务需求和异常类型去决定(这个多多实践吧,,,)
6 尽量添加 finally 语句块去释放占用的资源(IO Scanner异常之类的哈,涉及到资源的释放)