目录标题
1初始异常
1.1什么是异常?
- 什么是异常,异常机制有什么用?
- 1.以下程序执行过程中发生了不正常的情况,这种不正常的情况叫做:异常
- java是很完善的语言,提供了异常的处理方式,以下程序原执行过程总出现了不正常情况
- java吧该异常信息打印输出到控制台,工程许愿参考。程序员看到异常信息之后,可以对:
- 程序进行修改,让程序更加健壮
- 什么是异常:程序执行过程中的不正常情况
- 异常的作用:增强程序的健壮性
- 处理异常的第一种方式:
-
在方法生命的位置上使用throws关键字抛出,谁调用我这个方法,我就抛给谁,抛给调用者来处理
-
这种异常处理态度:上报
- 处理异常的第二种方式:
-
使用try...catch语句对异常进行捕捉
-
这个异常不会上报,自己就把这个是处理了
-
异常抛出到此为止,不再上抛了
1.2异常引例
public class Exception01 {
public static void main(String[] args) {
int a = 10;
int b = 0;
/*if(b==0){
System.out.println("除数不能为0");
return;
}*/
//程序执行到此处说明除数一定不为0
int c = a/b; //实际上JVA在执行到此处的时候,会new异常对象:new ArithmeticException(String s)
//并且JVM将new的异常对象抛出,打印输出信息到控制台了
System.out.println(100/0); //此处也发生了new ArithmeticException(String s) 异常
System.out.println(a + "/" + b + "=" + c);
}
}
1.3执行结果
1.3.1结果展示
1.3.2结果说明
以下程序执行程序出现了:
- Exception in thread “main” java.lang.ArithmeticException: / by zero
- at com.power.javase.exception.Exception.main(Exception.java:22)
- 这个信息被我们称为算术运算异常
2初始异常
2.1异常类创建异常对象
java语言中异常是以什么形式存在的呢?
每一个异常类都可以创建异常对象
2.2代码展示
public class Exception02 {
public static void main(String[] args){
//通过"异常类"实例化“异常对象”
NumberFormatException nfe= new NumberFormatException("数字格式化异常!");
System.out.println(nfe.toString());
//通过"异常类"实例化“异常对象”
NullPointerException npe = new NullPointerException("空指针异常");
System.out.println(npe.toString());
}
}
2.3执行结果
3运行时异常编写程序时可以不处理
3.1代码展示
注意: System.out.println(100/0);中100/0是运行时异常,可以不进行处理
package com.power.javase.exception;
/**
* java 的异常处理机制
*
*/
public class ExceptionTest03 {
public static void main(String[] args) {
/**
*
* 程序执行到此处发生了ArithmeticException异常,
* 底层new了一个ArithmeticException异常对象,
* 然后抛出了,由于是main方法调用了100/0,
* 所以这个异常ArithmeticException抛给了main方法
* main方法没有处理,将这个异常自动抛给了JVM,
* JVM最终终止程序的执行
*
* ArithmeticException继承RuntimeException,属于运行时异常
* 在编写程序阶段不需要对这种异常进行预先的处理
*/
System.out.println(100/0);
//这里的HelloWorld没有输出,没有执行
System.out.println("Hello World");
}
}
3.2执行结果
显示异常
4方法声明位置上使用throws【方法一】
- 处理异常的第一种方式:
在方法生命的位置上使用throws关键字抛出,谁调用我这个方法,我就抛给谁,抛给调用者来处理 - 这种异常处理态度:上报
4.1代码展示
package com.power.javase.exception;
/*
以下代码标错的原因是什么?
因为doSome()声明位置上使了:throws ClassNotFoundException
而ClassNotFoundException(类没找到异常)是编译时异常。必须编写代码处理,没有处理
编译器报错。
*/
public class ExceptionTest04 {
public static void main(String[] args) throws ClassNotFoundException {
/**
* main()方法中调用doSome()方法
* //因为doSome()方法声明位置上有:ClassNotFoundException
* 我们在调用doSome()方法的时候必须对这种异常进行预先的处理
* 如果我们不处理,编译器就会报错
* 报错信息:
* Error:(17, 15) java: 未报告的异常错误java.lang.ClassNotFoundException; 必须对其进行捕获或声明以便抛出
*/
doSome();
}
/**
* doSome方法在方法声明的位置上是用来:throws
* 这个代码表示doSome()方法在执行过程中,有可能会出现ClassNotFoundException异常
* 叫做类没找到异常,这个异常直接父类是:Exception,所以ClassNotFoundException属于编译时异常
*/
public static void doSome() throws ClassNotFoundException{
System.out.println("doSome!!!");
}
}
4.2执行结果
成功调用
5try…catch捕捉异常【方法二】
使用try…catch语句对异常进行捕捉
这个异常不会上报,自己就把这个是处理了
5.1代码展示
package com.power.javase.exception;
public class ExceptionTest05 {
//第一种处理凡是:在方法生命的位置上继续使用throws来完成异常的继续上抛,抛给调用者
/*
public static void main(String[] args) {
doSome();
}
*/
//第二种处理方式:try ....catch 进行捕捉
public static void main(String[] args) {
try{
doSome();
}catch (ClassNotFoundException e){
e.printStackTrace();
}
}
public static void doSome() throws ClassNotFoundException{
System.out.println("doSome!!!");
}
}
5.2执行结果
成功调用
6异常处理的原理
注意:只要异常没有捕捉,采用上报的发放时,此方法的
- 希望调用者来处理,选择throws上报
- 自己捕捉使用try…catch,不上报
6.1代码展示
package com.power.javase.exception;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
public class ExceptionTest06 {
//一般不建议在main方法上使用throws,因为这个异常如果真的发生了,一定会传给JVM。JVM只有终止。
//异常处理机制的作用就是增强程序的健壮性
public static void main(String[] args) {
System.out.println("main begin");
try{
//try尝试
m1();
}catch(FileNotFoundException e){
//catch是捕捉异常之后走的分支
System.out.println("文件不存在,可能路径错误,也可能是该文件被删除了!");
}
System.out.println("main over");
}
public static void m1()throws FileNotFoundException {
System.out.println("m1 begin");
m2();
System.out.println("m1 over");
}
public static void m2()throws FileNotFoundException{
System.out.println("m2 begin");
//编译器报错原因是:m3()方法声明位置上有:throws FileNotFoundException
//我们在这里调用m3()没有对异常尽心能够与处理,所以编译报错
m3();
System.out.println("m2 over");
}
public static void m3() throws FileNotFoundException {
//创建一个输入流对象,该流指向一个文件
/*
编译时报错的原因是什么?
第一:这个调用了一个构造方法:FileInputStream(String name)
第二:这个构造方法的声明位置上有throws FileNotFoundException
第三:通过类的继承结构看到:FileNotException父类是IOException,IOException的父类是Exception
最终得知:FileNotFoundException是编译时异常
*/
//new FileInputStream("D:\\a.txt");
//我们采用第一种方式:在方法声明的位置上使用throws继续上抛
//一个方法体当中的代码出现异常之后,如果上报的话,此方法结束。
new FileInputStream("D:\\a.1txt");
}
}
6.2执行结果
7深入try…catch
深入try…catch
1.catch后面的小括号中的类型可以是具体的异常类型,也可使该异常类型的父类型
2.catch 可以写多个。见一些catch的时候,精确的一个一个处理,这样有利于程序的调试
3.catch写多个的时候,从上到下必须遵守从小到大
7.1代码展示
public class ExceptionTest07 {
private static Object ArithmeticException;
public static void main(String[] args) {
/*try{
FileInputStream fis = new FileInputStream("D:\\a.1txt");
}
catch(IOException e){ //多态:IOExceptFileNotFoundExceptionion e = new e
System.out.println("文件不存在!");
}*/
/*try{
FileInputStream fis = new FileInputStream("D:\\a.1txt");
fis.read();
}
catch(FileNotFoundException e){ //多态:IOException e = new FileNotFoundException e
System.out.println("文件不存在!");
}
catch(IOException e){
System.out.println("读文件错了");
}*/
System.out.println("hellw world");
//编译报错
/*
try{
FileInputStream fis = new FileInputStream("D:\\a.1txt");
fis.read();
}
catch(IOException e){
System.out.println("读文件错了");
}
catch(FileNotFoundException e){ //多态:IOException e = new FileNotFoundException e
System.out.println("文件不存在!");
}*/
//JDK8的新特性
try {
//创建输入流
FileInputStream fis = new FileInputStream("D:\\a.1txt");
//进行数学运算
System.out.println(100 / 0);
} catch (FileNotFoundException | ArithmeticException | NullPointerException e) {
System.out.println("文件不存在!");
}
}
}
7.2执行结果
8异常对象的两个非常重要的方法
异常对象有两个非常重要的方法:
(1)获取异常简单的描述信息:
String msg = exception.getMessage();
System.out.println(msg);
(2) 打印异常追踪的堆栈信息:
exception.printStackTrace();
8.1代码展示
package com.power.javase.exception;
public class ExceptionTest08 {
public static void main(String[] args) {
//这里只是为了测试getMassage()方法和printStackTrace()方法
//这里只是new了异常对象,但是没有将异常对象抛出。JVM会认为这是一个普通的java对象
NullPointerException e = new NullPointerException("空指针异常fadil");
//获取异常简单描述:这个信息实际上就是过偶早方法上面的String参数
String msg = e.getMessage();
System.out.println(msg);
//打印异常堆栈信息
//java后台采用异常堆栈追踪信息的时候,采用了异步线程的方式打印的。
e.printStackTrace();
System.out.println("hello world");
}
}
8.2执行结果
9出现异常时,怎样快速调试
/*
异常对象有两个非常重要的方法:
获取异常简单的描述信息:
String msg = exception.getMeggage();
打印异常追踪的堆栈信息:
exception.printStackTrace();
我们以后怎么看异常的追踪信息,我们应该怎么看,可以快速的调试程序呢?
异常信息追踪信息,从上往下以下一行一行的看
但是需要注意的是:SUN写的代码就不用看了
*/
9.1代码展示
package com.power.javase.exception;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
public class ExceptionTest09 {
public static void main(String[] args) {
try{
m1();
}catch(FileNotFoundException e){
//获取简单的描述信息
String msg = e.getMessage();
System.out.println(msg); //D:\a.1txt (系统找不到指定的文件。)
//打印异常堆栈追踪信息
//在实际开发中,建议使用这个,养成好习惯
// e.printStackTrace();
/*
ava.io.FileNotFoundException: D:\a.1txt (系统找不到指定的文件。)
at java.io.FileInputStream.open0(Native Method)
at java.io.FileInputStream.open(FileInputStream.java:195)
at java.io.FileInputStream.<init>(FileInputStream.java:138)
at java.io.FileInputStream.<init>(FileInputStream.java:93)
at com.power.javase.exception.ExceptionTest09.m3(ExceptionTest09.java:30)
at com.power.javase.exception.ExceptionTest09.m2(ExceptionTest09.java:27)
at com.power.javase.exception.ExceptionTest09.m1(ExceptionTest09.java:24)
at com.power.javase.exception.ExceptionTest09.main(ExceptionTest09.java:16)
30导致27,27导致24,24导致16,
*/
}
//这里程序不耽误执行,很健壮(服务器不会因为遇到异常而宕机)
System.out.println("Hello World!");
}
public static void m1() throws FileNotFoundException{
m2();
}
public static void m2() throws FileNotFoundException{
m3();
}
public static void m3() throws FileNotFoundException{
new FileInputStream("D:\\a.1txt");
}
}
9.2执行结果
10读取文件时异常使用方法
关于try…catch中的finally字句:
1.在finally语句中的代码时最后执行的,并且是一定会执行的,即使try语句块中的代码出现了异常
finally字句必须和try一起出现,不能单独编写
2.finally语句通常使用在那些情况下呢?
通常在finally语句块中完成资源的释放/关闭
因为finally中的代码块比较有保障
即使try语句块中的代码出现异常,finally中代码也会正常执行
3.流使用完需要关闭,因为流是占用资源的,即使以上程序出现异常,流也是必须要关闭
10.1代码展示
package com.power.javase.exception;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class ExceptionTest10 {
public static void main(String[] args) {
FileInputStream fis = null; //声明位置放到try外面,这样在finally中才能用
try{
//创建输入流对象
fis = new FileInputStream("D:\\a.1txt");
//开始读文件...
String s = null;
//这里一定会出现空指针异常
s.toString();
//流使用完需要关闭,因为流是占用资源的
//即使以上程序出现异常,流也是必须要关闭
//放在这里有可能流关不了
}catch(FileNotFoundException e){
/*String stg = e.getMessage();
System.out.println(stg);*/
//e.printStackTrace();
System.out.println(e.getMessage()); //2和3本质区别在于一个需要输出 System.out.println()函数
}finally{
System.out.println("Hello haoke");
//流的关闭放到这里比较保险
//finally中代码是一定会执行的
//即使try中出现了异常!
if(fis != null){ //避免空指针异常
try{
//close()方法有异常,采用捕捉的方式
fis.close();
}catch(IOException e){
e.printStackTrace();
}
}
}
}
}
10.2执行结果
正确的文件名是D:\a.txt,此处我指定的是错误的文件名(D:\a.1txt)
11 try-catch- finally执行顺序
try和finally,没有catch可以吗?可以
try不能单独使用
try finally 可以联合使用
以下代码的执行顺序:
先执行try......
再执行finally
最后执行return (return执行方法必然结束)
11.1代码展示
package com.power.javase.exception;
/*
finally语句:放在finally里面的代码是一定会执行的
*/
public class ExceptionTest11 {
public static void main(String[] args) {
try{
System.out.println("try.........");
return;
}finally{ //就算try中有return语句,finally也会执行到
//finally中的语句会执行,能执行到
System.out.println("finally...........");
}
//这里不能写语句,因为这个代码是无法执行到的
//System.out.println("hello world");
}
}
11.2执行结果
12唯有 System.exit(0),finally语句不再执行
System.exit(0);只有这种情况下,退出JVM之后,finally语句中的代码不再执行
12.1代码展示
package com.power.javase.exception;
/*
fially
*/
public class ExceptionTest12 {
public static void main(String[] args) {
try{
System.out.println("try...");
//退出JVM
System.exit(0);//退出JVM之后,finally语句中的代码就不执行了
}finally{
System.out.println("finally...");
}
}
}
12.2执行结果
13Finanlly面试题
13.1代码展示
package com.power.javase.exception;
/*
finally面试题
*/
public class ExceptionTest13 {
public static void main(String[] args) {
int result = m();
System.out.println(result);
}
/*
java语法规则(有一些规则是不能破坏的,一旦这么说来,就必须这么做)
Java中有一条这样的规则:
方法体中的代码必须遵循自上而下书匈奴以此逐行执行(恒古不变的语法)
Java中还有一条语法规则:
return语句一旦执行,整个方法必须结束(恒古不变的语法)
*/
public static int m(){
int i=100;
try{
//这行代码出现在int i = 100 的下面,所以最终解雇必须是返回100
//return 语句还必须保证是最后执行的。一旦执行,整个方法结束
return i;
}finally{
i++;
}
}
}
13.2反编译过程
可以看出,此时找了一个临时变量
反编译之后的效果 找了个临时变量
public static int m(){
int i = 100;
int j = i;
i++;
return j;
}
13.3执行结果
执行结果为100
14初始异常
fianl finally finalize 有什么区别?
final关键字
final修饰的类无法继承
final 修饰的方法无法覆盖
final 修饰的变量不能重新赋值
finally 关键字
和try联合使用
finally语句块中的代码时必须执行的
finalize 标识符
是一个Object类中的方法名
这个方法是由垃圾回收器GC负责调用的
14.1代码展示
package com.power.javase.exception;
/*
fianl finally finalize 有什么区别?
final关键字
final修饰的类无法继承
final 修饰的方法无法覆盖
final 修饰的变量不能重新赋值
finally 关键字
和try联合使用
finally语句块中的代码时必须执行的
finalize 标识符
是一个Object类中的方法名
这个方法是由垃圾回收器GC负责调用的
*/
public class ExceptionTest14 {
public static void main(String[] args) {
//final是一个关键字,表示最终的,不可变的
final int i = 100;
//i = 200;
//finally也是一个关键字,和try联合使用,使用在异常处理机制中
//再finally语句块中的代码是一定会执行的
try{
}finally{
System.out.println("finally.....");
}
//finalize()是Object类中的一个方法,作为方法名出现
//所以finalize()是标识符
Object object;
}
}
//final 修饰的类无法继承
final class A{
//常量
public static final double PI=3.1415926;
}
class B{
//final修饰的方法无法覆盖
public final void doSome(){
}
}
14.2执行结果
15怎么样自定义异常
15.1自定义异常方法
1、SUN提供的JDK内置的异常肯定是不够用的。在实际开发过程中,有很多业务,
这些业务踹你异常之后,JDK都是没有的。和业务挂钩的。那么异常我们
程序员可以自己编写吗?
可以。
2.Java中怎么自定义异常呢?
两步?
第一步:编写一个类继承Exception或者RuntimeException
第二部:提供两个构造方法,一个无参的,一个带有String参数
死记硬背。
15.2代码展示
以下两个代码块含义一样
public class MyException extends Exception{ //编译时异常
public MyException(){
}
public MyException(String s){
super(s);
}
}
package com.power.javase.exception;
栈操作异常:自定义异常
*/
public class MyStackOperationException extends Exception{
//无参构造
public MyStackOperationException(){ //编译时异常
}
//有参构造
public MyStackOperationException(String s){
super(s);
}
}