Java入门到精通(一)语言基础
java的异常机制是建立在C++的基础之上。
Thorwable类所有异常和错误的超类,有两个子类Error和Exception,分别表示错误和异常。其中异常类Exception又分为运行时异常(RuntimeException)和非运行时异常,这两种异常有很大的区别,也称之为不检查异常(Unchecked Exception) 和 检查异常(Checked Exception)。
运行时异常 —> UncheckedException 程序中可以选择捕获处理,也可以不处理。这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生。编译是可以通过的。
非运行时异常—>CheckedException 类型上都属于Exception类及其子类。从程序语法角度讲是必须进行处理的异常,如果不处理,程序就不能编译通过。如IOException、SQLException等以及用户自定义的Exception异常,一般情况下不自定义检查异常。
Error 和 Exception
Error是程序无法处理的错误,比如OutOfMemoryError、ThreadDeath等。这些异常发生时,Java虚拟机(JVM)一般会选择线程终止,程序将会终止。
Exception是程序本身可以处理的异常,这种异常分两大类,运行时异常和非运行时异常。程序中应当尽可能去处理这些异常。
常见的异常
异常类 | 意义 |
---|---|
ClassCastException | 类型转换异常 |
NullPointerException | 空指针异常 |
IndexOutOfBoundsException | 数组下标异常 |
ArithmeticException | 算术异常 |
NumberFormatException | 字符串转换为数字异常 |
IllegalArgumentException | 非法参数异常 |
SecurityException | 安全性异常 |
public class Demo {
public static void main(String[] args) {
int[] arr= new int[5];
System.out.println(arr[5]);
}
}
方法 | 介绍 |
---|---|
getMessage() | 获取有关异常事件信息 |
toString() | 获取异常的类型与性质 |
printStackTrace() | 获取异常发生时执行堆栈的内容 |
getCause() | 返回一个Throwable 对象代表异常原因 |
getStackTrace() | 返回一个包含堆栈层次的数组。下标为0的元素代表栈顶,最后一个元素代表方法调用堆栈的栈底 |
fillInStackTrace() | 用当前的调用栈层次填充Throwable 对象栈层次,添加到栈层次任何先前信息中 |
异常处理有两种解决的方案:一种try……catch(捕获并处理异常)语句,另外一种throw(抛出异常)。
try {
}catch (Exception e){
}finally {
}
try:一般都在try里面编写可能发生异常的代码块。
catch: 在try代码块发生异常时,只有进入catch语句块,异常才可以被处理,catch语句块可以有n个(并且子类必须在父类之前,否则就会发生错误)。
finally这个代码块是异常发生不发生都会执行的代码块,都是最后执行。一般情况下该部分都是释放资源或者关闭对象。finally不执行的情况:在finally里面发生异常。
public class Demo {
public static void main(String[] args) {
int[] arr = new int[]{
1,2,3,4,5};
try{
System.out.println("第五个元素"+arr[5]);
}catch (Exception e){
//这块也可以将Exception改为ArrayIndexOutOfException
System.out.println("下标不能大于4,数组下标异常");
}
}
}
从图中可以看出程序并没有因此中断而是对其异常进行了处理最后执行完成。
从上图中可以看出两个catch语句的顺序不一样导致了编译器出现了错误提示。Exception是所有的子异常的父类,如果将Exception放在子类之前那么后面的语句就不会执行,也就没有什么意义了。
throws关键词是在声明方法时候用来指定方法可能抛出的异常。
public class asdsad{
//主线程
public synchronized void main() throws Exception {
}
//子线程
public synchronized void child() throws Exception {
//这种就是throws在方法总抛出异常
}
public static void main(String[] args) throws Exception {
asdsad asdsad = new asdsad();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println();
try {
asdsad.child();
} catch (Exception e) {
e.printStackTrace();
}
}
}
},"子线程").start();
for (int i = 0; i < 10; i++) {
System.out.println();
asdsad.main();//这块也可以加try……catch语句 main() 后面就可以不需要了
}
}
}
如果方法抛出了异常(child、main),那么在调用的时候就要使用try……catch语句捕获并处理异常或者向上继续抛出异常就像如上代码调用main方法 把异常抛给了Exception处理。
这里需要注意:使用throws为方法抛出异常,如果子类继承父类,子类重写的方法和原父类方法抛出的异常相同、或者是其异常的子类,除非throws异常时RuntimeException。
throw关键词通常用于在方法体之中“制造一个异常”,程序在执行到throw语句时立即终止,它后面的语句都不会得到执行。
public class Demo {
public static void main(String[] args) {
int num_1 = 10;
int num_2 = 0;
if(num_2 == 0){
throw new ArithmeticException("除数不为0");
}
int res = num_1/num_2;
System.out.println(res);
}
}
throw通常用来抛出用户自定义异常,通过throw关键词抛出异常后,如果想在上一级代码中捕获并处理异常,最好在抛出异常的方法声明中使用throws关键词指明要抛出的异常;如果要捕捉throw抛出的异常,则使用try……catch代码块。
为什么要自定义异常?
就是java内置异常无法识别的情况下才自定义异常、比如:年龄不能为负数。
自定义异常使用场景:
程序中出现错误是符合java语法,编译器检测不出,也可以编译,比如:人的年龄不能为负数,人数不能为小数等等。(这块我总结的不全面)
int age = -10;
System.out.println("小明今年"+age);
如上就可以输出,要避免这种情况我们就可以自定义一个异常类。
public class ageDemo {
public static void ages(int age) throws MyException{
if(age<0){
throw new MyException("年龄不可以使用负数");
}else{
System.out.println("小明今年"+age);
}
}
public static void main(String[] args) {
int age = -10;
try {
ages(age);
} catch (MyException e) {
e.printStackTrace();
}
}
}
java异常强制用户去考虑程序的强健性和安全性。
应该遵循以下原则:
不全的内容请大佬补充
看完感觉有用的点个赞,没有的也点个赞
嘻嘻~