JavaSE学习总结(四)

try-catch-finally 如何使用?

  • try块 : 用于捕获异常。其后可接零个或多个 catch 块,如果没有 catch 块,则必须跟一个 finally 块。

  • catch块 : 用于处理 try 捕获到的异常。

  • finally 块 : 无论是否捕获或处理异常,finally 块里的语句都会被执行。当在 try 块或 catch 块中遇到 return 语句时,finally 语句块将在方法返回之前被执行。

如果try语句里有return,返回的是try语句块中变量值。 
详细执行过程如下:
	a.如果有返回值,就把返回值保存到局部变量中;
	b.执行jsr指令跳到finally语句里执行;
	c.执行完finally语句后,返回之前保存在局部变量表里的值。
	如果try,finally语句里均有return,忽略try的return,而使用finally的return.
public static void main(String[] args) {
    System.out.println(f(2));
}

public static int f(int value) {
    try {
        return value * value;
    } finally {
        if (value == 2) {
            return 0;
        }
    }
}

输出:

0

finally 中的代码一定会执行吗?

不一定的!在某些情况下,finally 中的代码不会被执行。

就比如说 finally 之前虚拟机被终止运行的话,finally 中的代码就不会被执行

try {
    System.out.println("Try to do something");
    throw new RuntimeException("RuntimeException");
} catch (Exception e) {
    System.out.println("Catch Exception -> " + e.getMessage());
    // 终止当前正在运行的Java虚拟机
    System.exit(1);
} finally {
    System.out.println("Finally");
}

Output:

Try to do something
Catch Exception -> RuntimeException

另外,在以下 2 种特殊情况下,finally 块的代码也不会被执行:

  1. 程序所在的线程死亡。
  2. 关闭 CPU。

throw 和 throws 的区别是什么?

Java 中的异常处理除了包括捕获异常和处理异常之外,还包括声明异常和拋出异常,可以通过 throws 关键字在方法上声明该方法要拋出的异常,或者在方法内部通过 throw 拋出异常对象。

throws 关键字和 throw 关键字在使用上的几点区别如下:

  • throw 关键字用在方法内部,只能用于抛出一种异常,用来抛出方法或代码块中的异常,受查异常和非受查异常都可以被抛出。

  • throws 关键字用在方法声明上,可以抛出多个异常,用来标识该方法可能抛出的异常列表。一个方法用 throws 标识了可能抛出的异常列表,调用该方法的方法中必须包含可处理异常的代码,否则也要在方法签名中用 throws 关键字声明相应的异常。

举例如下:

throw 关键字:

public static void main(String[] args) {
		String s = "abc";
		if(s.equals("abc")) {
			throw new NumberFormatException();
		} else {
			System.out.println(s);
		}
		//function();
}

throws 关键字:

public static void function() throws NumberFormatException{
		String s = "abc";
		System.out.println(Double.parseDouble(s));
	}
	
	public static void main(String[] args) {
		try {
			function();
		} catch (NumberFormatException e) {
			System.err.println("非数据类型不能转换。");
			//e.printStackTrace();
		}
}

JVM 是如何处理异常的?

在一个方法中如果发生异常,这个方法会创建一个异常对象,并转交给 JVM,该异常对象包含异常名称,异常描述以及异常发生时应用程序的状态。创建异常对象并转交给 JVM 的过程称为抛出异常。可能有一系列的方法调用,最终才进入抛出异常的方法,这一系列方法调用的有序列表叫做调用栈。

JVM 会顺着调用栈去查找看是否有可以处理异常的代码,如果有,则调用异常处理代码。当 JVM 发现可以处理异常的代码时,会把发生的异常传递给它。如果 JVM 没有找到可以处理该异常的代码块,JVM 就会将该异常转交给默认的异常处理器(默认处理器为 JVM 的一部分),默认异常处理器打印出异常信息并终止应用程序。

异常传递

异常传递是指异常在方法之间传递的过程。当在Java程序中抛出异常时,JVM会在当前方法的调用堆栈中查找匹配的异常处理器来处理异常。如果在当前方法的调用堆栈中找不到任何匹配的异常处理器,则异常将继续向调用方传递,直到找到可以处理异常的异常处理器或将异常传递到程序的顶层,这时程序将终止并输出异常信息。

总结:

Java程序中,当发生异常时,会将异常的信息打包进一个异常对象中,并通过throw关键字抛出该异常对象。异常被抛出后,JVM会在当前方法中查找匹配的异常处理器进行处理,如果当前方法没有找到匹配的异常处理器,JVM会递归地查找当前方法的调用方法,并在调用方法中进行处理,直到找到匹配的异常处理器。如果 JVM 没有找到可以处理该异常的代码块,JVM 就会将该异常转交给默认的异常处理器(默认处理器为 JVM 的一部分),默认异常处理器打印出异常信息并终止应用程序。

如果想要详细了解这个问题,可以参考这篇文章——JVM是如何处理异常的。

异常使用有哪些需要注意的地方?

  • 不要把异常定义为静态变量,因为这样会导致异常栈信息错乱。

  • 每次手动抛出异常,我们都需要手动 new 一个异常对象抛出。

  • 抛出的异常信息一定要有意义。建议抛出更加具体的异常比如字符串转换为数字格式错误的时候应该抛出NumberFormatException而不是其父类IllegalArgumentException。

  • 使用日志打印异常之后就不要再抛出异常了(两者不要同时存在一段代码逻辑中)。

Java常见异常有哪些?

java.lang.IllegalAccessError:违法访问错误。当一个应用试图访问、修改某个类的域(Field)或者调用其方法,
但是又违反域或方法的可见性声明,则抛出该异常。

java.lang.InstantiationError:实例化错误。当一个应用试图通过Javanew操作符构造一个抽象类或者接口时抛出该异常。

java.lang.OutOfMemoryError:内存不足错误。当可用内存不足以让Java虚拟机分配给一个对象时抛出该错误。

java.lang.StackOverflowError:堆栈溢出错误。当一个应用递归调用的层次太深而导致堆栈溢出或者陷入死循环时抛出该错误。

java.lang.ClassCastException:类造型异常。假设有类ABA不是B的父类或子类),OA的实例,
那么当强制将O构造为类B的实例时抛出该异常。该异常经常被称为强制类型转换异常。

java.lang.ClassNotFoundException:找不到类异常。当应用试图根据字符串形式的类名构造类,
而在遍历CLASSPAH之后找不到对应名称的class文件时,抛出该异常。

java.lang.ArithmeticException:算术条件异常。譬如:整数除零等。

java.lang.ArrayIndexOutOfBoundsException:数组索引越界异常。当对数组的索引值为负数或大于等于数组大小时抛出。

java.lang.IndexOutOfBoundsException:索引越界异常。当访问某个序列的索引值小于0或大于等于序列大小时,抛出该异常。

java.lang.InstantiationException:实例化异常。当试图通过newInstance()方法创建某个类的实例,而该类是一个抽象类或接口时,
抛出该异常。

java.lang.NoSuchFieldException:属性不存在异常。当访问某个类的不存在的属性时抛出该异常。

java.lang.NoSuchMethodException:方法不存在异常。当访问某个类的不存在的方法时抛出该异常。

java.lang.NullPointerException:空指针异常。当应用试图在要求使用对象的地方使用了null时,抛出该异常。
譬如:调用null对象的实例方法、访问null对象的属性、计算null对象的长度、使用throw语句抛出null等等。

java.lang.NumberFormatException:数字格式异常。当试图将一个String转换为指定的数字类型,
而该字符串确不满足数字类型要求的格式时,抛出该异常。

java.lang.StringIndexOutOfBoundsException:字符串索引越界异常。当使用索引值访问某个字符串中的字符,
而该索引值小于0或大于等于序列大小时,抛出该异常。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
学习JavaSE可以通过以下几个步骤进行: 1. 了解JavaSE的基础知识:JavaSEJava的标准版,主要用于开发桌面应用程序。你可以开始学习JavaSE的基础语法、数据类型、控制流程等内容。可以参考\[3\]中提到的Java是一种跨平台、面向对象的高级程序设计语言,其语法和C++类似。 2. 学习JavaSE的核心概念:JavaSE包含了许多核心概念,如面向对象编程、异常处理、多线程等。你可以通过阅读相关的教程、书籍或参加培训课程来深入学习这些概念。 3. 实践编写JavaSE程序:学习JavaSE最好的方式是通过实践编写程序来加深理解。你可以尝试编写一些简单的JavaSE应用程序,如控制台程序、图形界面程序等。通过实践,你可以更好地理解JavaSE的各种特性和用法。 4. 参考JavaSE的官方文档和教程:JavaSE有详细的官方文档和教程,你可以参考官方文档来了解JavaSE的各种API和用法。此外,还可以参考一些优秀的JavaSE教程和书籍,如《Java核心技术》等。 总结起来,学习JavaSE需要掌握基础知识、核心概念,并通过实践编写程序来加深理解。同时,参考官方文档和教程可以帮助你更好地学习和应用JavaSE。 #### 引用[.reference_title] - *1* *2* *3* [教你如何正确学习JAVASE](https://blog.csdn.net/jsqzy/article/details/120726118)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

路上阡陌

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值