java异常机制
import java.util.Scanner;
public class Demo {
异常的引入
Exception in thread "main" java.lang.ArithmeticException: / by zero
at com.sxt.day1217.exception1.Demo.main(Demo.java:12)
* 异常对象信息
* 1:具体异常类 java.lang.ArithmeticException
* 2:异常信息 / by zero
* 3:异常发生的地方:at com.sxt.day1217.exception1.Demo.main
* 4:异常发生的行数:Demo.java:12
*
* 如何解决?
* 1:切记:不要改变变量的值(尤其是用户提供的值)
* 2:做if..else... 判断 堵漏洞
* 问题1:漏洞太多,不太好补
* 问题2:业务代码和处理漏洞的代码放一块了,没有做到分层处理
* 3:使用java中的异常处理机制
* 它将异常处理代码和和业务代码分离,使程序更优雅,更好的容错性,高键壮性
* 提前预防代码出错,就算代码错了,也不会影响后续的代码正常执行
*
* 1:最好不要让代码出错
* 2:如果异常了怎么办:解决异常
*
* 异常的3个关键字 块代码 static{},if(){} else{},switch(){},for(){},try{},catch(){},finally{}
* 声明在块代码中的变量,不能在块的外面使用,如果要使用,必须在块的外面声明而且赋初始值
*
*
* try:尝试着去运行有可能会出错的代码 ,把你认为有可能会出错的代码,放入try块中
* catch:1 如果代码出错了,进入catch块,捕获异常对象
* 2 如果代码没有出错,不进catch块,正常运行
* finally:表示最终的意思,无论什么情况,都会执行的意思
* 就算代码中有return语句,那么也会先把finally中的代码执行了,再return
* 但是:要把一种情况排除在外,JVM强制结束
* finally一般做程序的扫尾操作,关闭流文件,关闭数据连接,关闭socket
*
* try..catch..finally的组合方式
* 1:这3个都不能单独使用
* 2:try..catch..
* 3:try..finally..
* 4:try..catch..finally..
*
*
* 异常分类
* Throwable
* 2个子类
* Error, Exception
* Exception
* 2个子类
* RuntimeException:运行时异常
* 编译时异常(检查异常)
*
* 写出5个常见的运行时异常
* NullPointException 空指针异常
* ArrayIndexOutOfBoundsException 数组下标越界
* ArithmeticException:算术异常
* InputMismatchException 类型匹配异常
* StringIndexOutOfBoundsException 字符串下标越界
*/
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int d = 0;
try{
d = 100;
System.out.println("请输入第1个数");
int a = sc.nextInt();
System.out.println("请输入第2个数");
int b = sc.nextInt();
// System.out.println(d);
System.out.println(a/b);
//return;
System.exit(1); //JVM强制退出 一般参数为1即可
}catch(Exception e){
//System.out.println("进来?");
//System.out.println(e);
//System.out.println(e.toString());
e.printStackTrace(); //打印异常的堆栈信息
}finally{
System.out.println("我一定会执行");
}
//System.out.println("我可以执行吗");
//System.out.println(d);
}
}
public class Demo2 {
/*
* 异常堆栈信息的具体执行过程?
* 举例:写一个空指针异常
* 1:声明一个引用类型,并且赋值为null
* 2:使用这个null变量调用方法或者属性,都会产生空指针异常
*
* 注意:异常信息,是JVM给程序跑出来的,我们程序员加try..catch..,是为了是代码能正常的执行下去
* 注意:如果你知道你的代码有可能报什么异常,那么就在catch中写一个具体的异常类型
* 注意:如果你自己写的异常没有和代码抛出的异常匹配,那么他就不会进到catch中,导致的结果及时,后面的代码也不能执行了
* 注意:如果你不知道的你的代码会报什么异常,那么干脆直接写Exception异常,记着在catch中吧打印异常信息的代码加上
* ,便 于程序员寻找错误原因
* 注意:如果有多个方法调用,其中一个方法出错了,异常会报好几个地方,我们找异常的时候,从控制台的由上而下来找
* 注意:方法连续调用,在堆栈异常数组中,你有几个方法,就有几条跟踪信息,一般数组中的第一个是它具体异常信息
*
* 异常堆栈信息
* e.printStackTrace()
* java.lang.NullPointerException
* at com.sxt.day1217.exception1.Demo2.main(Demo2.java:18)
* StackTraceElement[] 异常堆栈元素数组
*
* String eName = e.getClass().getName(); //代表异常类名
String cName = el.getClassName(); //异常发生的java类的名字
String fName = el.getFileName(); //异常发生的java文件的名字
String mName = el.getMethodName(); //异常发生的方法名
int lineNum = el.getLineNumber();//异常发生的行数
String msg = e.getMessage();//异常原因
*
*/
public static void c(){
a();
}
public static void a(){
//int[] arr =null;
try {
System.out.println(10/0);
//NullPointerException
} catch (Exception e) {
StackTraceElement[] ste = e.getStackTrace();//
System.out.println(ste.length);
StackTraceElement el = ste[0];
String eName = e.getClass().getName(); //代表异常类名
String cName = el.getClassName(); //异常发生的java类的名字
String fName = el.getFileName(); //异常发生的java文件的名字
String mName = el.getMethodName(); //异常发生的方法名
int lineNum = el.getLineNumber();//异常发生的行数
String msg = e.getMessage();//异常原因
System.err.println(eName+" :"+msg+"\n\tat "+cName+"."+mName+"("+fName+lineNum+")");
//System.out.println(ste.length);
//String mes = e.getMessage();//异常原因
//System.err.println(mes);
e.printStackTrace();
}
System.out.println("我可以执行吗?");
}
public static void main(String[] args) {
c();
}
}
public class Demo3 {
/*
* 多重catch块
* 语法结构
* try{
* 尝试运行代码
* }catch(异常类型1 e){
* e.printStackTrace();
* }catch(异常类型2 e){
* e.printStackTrace();
* }catch(异常类型3 e){
* e.printStackTrace();
* }catch(异常类型4 e){
* e.printStackTrace();
* }...
* 注意:异常类型从具体到抽象(从子类到父类)
* 注意:不要把父异常写在钱,子异常写在后面,语法会报错,因为大异常会直接匹配这个具体异常,
* 后面的catch块压根不会执行
*
* 了解:嵌套异常
* try,catch,finally中都可以嵌套异常
*
*/
public static void main(String[] args) {
String s = null;
try {
System.out.println(s.length());
} catch (ArrayIndexOutOfBoundsException e) {
try{
}catch(ArrayIndexOutOfBoundsException e1){
try{
}catch(ArrayIndexOutOfBoundsException e2){
e2.printStackTrace();
}
e1.printStackTrace();
}
System.out.println("数组异常");
} catch(IndexOutOfBoundsException e){
System.out.println("下标异常");
} catch(RuntimeException e){
System.out.println("运行时异常");
} catch(Exception e){
System.out.println("异常");
}finally{
try{
} catch(Exception e){
}
}
System.out.println("正常执行");
}
}
public class Demo {
/*
* 异常分类
* 1:运行时异常
* 代码运行过程中,发生异常
* 2:编译时异常
* 编译器在检查代码是否有语法错误的时候,就发现异常了,这种异常必须处理,
如果不处理,代码不能运行
* 程序员更应该关注编译时异常
* 常见的编译异常
* ClassNotFoundException 类未找到
*/
public static void main(String[] args) {
try {
Class.forName("com.sxt.day1217.exception1.Demo");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
System.out.println("正常执行");
}
}
import java.io.IOException;
import javax.management.modelmbean.XMLParseException;
import javax.xml.stream.XMLStreamException;
import javax.xml.xpath.XPathException;
public class Demo {
/*
* try..catch是一种积极处理异常的方式
* throws是一种消极处理异常的方式
*
* 异常关键字
* throws:如果代码发生错误,就把这个错误异常类型声明在方法后面,谁调用,谁处理
* 注意:throws代表有可能会抛出异常
* 注意:如果最后一层是main方法,记着try..catch..,否则异常就传到JVM中了,后面的代码也不能正常执行了
* 注意:异常可以向上传递
* 注意:我们可以一次性向外声明多个编译时异常,谁调用,谁处理,类型,顺序,个数要一致
* 注意:向外声明的异常类型越具体,对调用者越好,很明确异常类型,可以快速的处理异常
* 注意:如果一个方法向外声明了一个异常,那么调用者必须声明一个大于等于这个异常的类型,反之则不行
*
*
*/
public static void show(){
try {
Class.forName("java.lang.String");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void show2(){
show();
}
public static void main(String[] args) {
show2();
System.out.println("我能执行吗?");
}
}
import javax.management.RuntimeErrorException;
public class Demo2 {
/*
* throw:在方法体中抛出一个异常对象,表示一定会抛出异常
* 在开发中,有时候,我们需要手动抛出一个异常对象,使得这个代码的走向,去另外一个地方
* 注意:throw表示一定会抛出异常,无论代码对错
* 注意:throw抛出的是一个异常对象
*
* 面试题:throws和throw的区别?
*
* 1:位置
* throws出现在方法头
* 而throw出现在方法体。
* 2:抛出区别
* throws表示出现异常的一种可能性,并不一定会发生这些异常;声明的是一个异常类型
* throw则是抛出了异常,执行throw则一定抛出了某种异常对象。
* 3 处理异常方式
* 两者都是消极处理异常的方式(这里的消极并不是说这种方式不好),只是抛出或者可能抛出异常,
* 但是不会由函数去处理异常,真正的处理异常由函数的上层调用处理。
*
* 编程习惯
* 1:在写程序时,对可能会出现异常的部分通常要用try{...}catch{...}去捕捉它并对它进行处理;
* 2 :用try{...}catch{...}捕捉了异常之后一定要对在catch{...}中对其进行处理,那怕是最简单的一句输出语句,
* 或栈输入e.printStackTrace();
* 3: 如果是捕捉IO输入输出流中的异常,一定要在try{...}catch{...}后加finally{...}把输入输出流关闭;
* 4:如果在函数体内用throw抛出了某种异常,最好要在函数名中加throws抛异常声明,
* 然后交给调用它的上层函数进行处理。
*
* 既要制造异常,还要处理异常
*/
public static void show(String url){
try {
throw new NullPointerException();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("你好吗");
/*if(url.equals("http://www.baidu.com")){
//request.url("http://www.baidu.com"); //正确跳转
}else{
try {
throw new Exception(url);
} catch (Exception e) {
// request.url("http://www.error.com");
e.printStackTrace();
}
}*/
//System.out.println(10/2);//正确代码
//throw new NullPointerException(); //异常代码
//return;
//System.out.println("123123"); //异常后面的代码
}
public static void main(String[] args) throws Exception {
show("http://www.baidu.com");
}
}
1.Error和Exception的区别
二者的不同之处:
Exception:
1.可以是可被控制(checked) 或不可控制的(unchecked)。
2.表示一个由程序员导致的错误。
3.应该在应用程序级被处理。
Error:
1.总是不可控制的(unchecked)。
2.经常用来用于表示系统错误或低层资源的错误。
3.如何可能的话,应该在系统级被捕捉。
Java 中定义了两类异常:
-
Checked exception: 这类异常都是Exception的子类 。异常的向上抛出机制进行处理,假如子类可能产生A异常,那么在父类中也必须throws A异常。可能导致的问题:代码效率低,耦合度过高。
-
Unchecked exception: 这类异常都是RuntimeException的子类,虽然RuntimeException同样也是Exception的子类,但是它们是非凡的,它们不能通过client code来试图解决,所以称为Unchecked exception 。
2Checked异常和Runtime异常的区别
最本质的区别是:
RuntimeException是运行时才会发生的异常
而受检查异常是编译时异常,编译器会分析哪些异常会在执行一个方法或者构造函数的时候抛出。
异常(Exception):你可以使用运行时异常或者编译时异常。
运行时异常(RuntimeException)也称作未检测的异常(unchecked exception),这表示这种异常不需要编译器来检测。RuntimeException是所有可以在运行时抛出的异常的父类。一个方法除要捕获异常外,如果它执行的时候可能会抛出RuntimeException的子类,那么它就不需要用throw语句来声明抛出的异常。
例如:NullPointerException,ArrayIndexOutOfBoundsException,等等
受检查异常(checked exception)都是编译器在编译时进行校验的,通过throws语句或者try{}cathch{} 语句块来处理检测异常。编译器会分析哪些异常会在执行一个方法或者构造函数的时候抛出。
3.Java异常处理中,关键字try、catch、finally、throw、throws分别代表什么含义?
1.try:它里面放置可能引发异常的代码
2.catch:后面对应异常类型和一个代码块,用于表明该catch块用于处理这种类型的代码块,可以有多个catch块。
3.finally:主要用于回收在try块里打开的物力资源(如数据库连接、网络连接和磁盘文件),异常机制总是保证finally块总是被执行。只有finally块,执行完成之后,才会回来执行try或者catch块中的return或者throw语句,
4.throw:用于抛出一个实际的异常,可以单独作为语句使用,抛出一个具体的异常对象。
5.throws:用在方法签名中,用于声明该方法可能抛出的异常。
4.throws和throw的区别
throw(异常对象)
用于程序出现某种逻辑时程序员主动抛出某种特定的的异常,记住是程序员主动 抛的
throws:
指的是方法可能抛出异常的声明,当某个方法可能会抛出某种异常时用于throws 声明可能抛出的异常,然后交给上层调用它的方法程序处理。