java中的异常及处理方式
java中的异常有三种
1.语法错误/编译错误:
在IDE(集成开发环境)工具(eclipse,myeclipse等)中写代码,代码写错了,在工具中用红波浪线或红叉来表示。如果显示红波浪线,此代码是不能通过工具进行编译的,不能编译就不能执行
2.逻辑错误
前提是语法没有错误
程序能编译,能运行,但结果错误
一般原因就是代码的逻辑写错了,最终结果也是错误的
3.运行错误/异常/例外
前提是逻辑没有错误,但在运行期间因为某种原因导致错误,而程序意外终止,这种错误就叫做运行错误(异常/例外)。一场是在运行期间发生的。
比如:
//这两个值需要重键盘录入
int num1,num2;
int result=num1/num2;
如果num2录入的是非零值,程序可以正常运行
如果num2录入的是0,程序就不能正常运行,代码逻辑正确,但有运行错误(异常/列外),且程序终止
有了异常最直接的结果就是程序终止了,这不是程序的目的所以要处理异常,处理异常的目的有两个
1.避免程序意外中止
2.如果出现了一场,程序不能中止,还要给一个友好提示
程序意外中止:就是程序执行到某一行的位置的时候不执行了
jvm就不再继续执行这个程序了
处理java异常的方法有三种
1.方法一:用java代码提供的一场处理机制,try catch finally 等
public class Demo1 {
@Test
public void testMethod2(){
/**
* 用java提供的 try catch 方式容错
* */
Scanner input=new Scanner(System.in);
System.out.println("请输入第一个数字");
int num1=input.nextInt();
System.out.println("请输入第二个数字");
int num2=input.nextInt();
int result=Integer.MIN_VALUE;
try{
result=num1/num2;
}catch(ArithmeticException e){
System.out.println("分母不能为0");
}
System.out.println("result="+result);
System.out.println("程序正常结束");
}
}
2.方法二:用java的逻辑代码来处理,即用纯java代码来容错
public class Demo1 {
@Test
public void testMethod1(){
/**
* 用純java代碼的方式來容錯
* */
Scanner input=new Scanner(System.in);
System.out.println("请输入第一个数字");
int num1=input.nextInt();
System.out.println("请输入第二个数字");
int num2=input.nextInt();
int result=Integer.MIN_VALUE;
if(num2!=0){
result =num1/num2;
}else{
System.out.println("分母不能为0");
}
System.out.println("result="+result);
System.out.println("程序正常结束");
}
}
使用try catch finally的注意事项
一般情况下,try 块中监视的是代码,需要程序员猜测try块中有多少种可能的异常,在try块中的代码可能有n种异常
那么就在try块的下面写n个catch,且catch抓取的异常类型是不同的
如果发生了异常,但是没有catch块来抓取,程序还是会意外中止
为了解决这个问题,需要添加第n+1个catch
这个catch的异常类型是Exception异常类型,即catch(Exception e)
且此catch必须放在所有的catch的最后
什么是finally
finally 块中放置若干的java代码,一般情况下
finally块中的代码是用来释放try块中申请的内存空间
try块中如果有异常,会抛出异常
在某一个catch块接收到系统抛出的异常(必须保证catch抓取的异常类型和抛出的异常类型一致)
然后对应catch块中的代码就被执行了.catch块中一般有两类代码
一个是栈的轨迹,另一个是友好的交互或提示的代码
执行完当前的catch块中的代码后,会跳过后面的所有的catch块
执行finally块中的代码,执行完finally块中的代码后,继续执行finally块后面的代码,即没有异常
最终会执行finally,用于销毁申请的内存空间
异常的继承层次
- 顶级类:Throwable
Throwable类只有两个子类
- Exception类:是程序员能够写代码处理的异常的根类
Exception异常分为两类:
-免检异常:不添加try catch finally,程序是能够编译执行的执行时出发符合的异常,程序还是会意外中止
异常类型 | 异常含义 |
---|---|
RuntimeException | 运行错误 |
ArithmeticException | 算数异常 |
NullPointException | 空指针异常 |
ArrayIndexOutOfBoundsException | 数组下标越界异常 |
NumberFormatException | 数字格式异常 |
InputMismatchException | 输入不匹配异常 |
… | … |
- 必检异常: 必须添加try catch,如果不添加,则会有红波浪线提示,说明程序不能编译
异常类型 | 异常含义 |
---|---|
Exception | 所有程序员能处理的异常的根类 |
SQLException | sql数据库异常 |
ClassNotFoundException | 类没有发现 异常 |
FileNotFoundException | 文件没有找到异常 |
… | … |
ERROR
Error类不是程序员能使用的,一般情况下是给jvm使用的
比如
要往U盘中写入一个文件,但没有U盘这个设备,异常错误抛给jvm来处理
如何判断异常是免检的还是必检的
如果程序员在写代码的时候,代码没有错误,但报了红波浪线并提示"UNhandle Exception Type XXXException" (无法处理异常类型 XXXException为具体的异常类型)
必检异常必须添加try catch,否则红波浪线就不会消失.快捷键(Alt+Shift+Z)来调try catch代码块的模板
throw关键字
在java中有一个Exception类.这个类有很多的子类且没各子类都对应一个异常类型
这些异常类型都是java类库自带的异常类型
NullPointerException
ArrayIndexOutofBoundsException
类似这些异常都是java定义的规则,触犯规则就抛异常
即系统定义的规则,系统检测到就由系统抛出
java中不可能把所有项目中遇到的异常都实现写好已换成那个类
由程序员根据实际业务需求抛出异常
比如:
年龄在1到100岁之间,如果不在范围内就抛出相应的异常
程序员定规则,程序员用java代码检测,程序员抛出
实现的方式有两种:
方式一:
用try catch finally throw
方式二:
用java逻辑代码来处理
throws关键字
throws关键字放在方法声明的后面,可以写很多个异常类型,之间用逗号间隔,表明此方法体可能会抛出的异常.这些异常不在当前方法中用try catch finally来处理
**注意:**Exception类型必须放在throws后所有的异常的后面
throws的应用场景:
一般情况下,写类库的时候,类库是提供给其他项目使用的。类中的方法如果有异常,那么就是用throws抛出,然后谁调用谁就用try catch 来处理
自定义异常
程序员自己创建的java类,但是必须继承自Exception及其子类中的任何类都可以
那么此类就是自定义异常类
自定义异常类,是作为本项目的异常类型的补充
例
自定义异常类AgeMessage类
public class AgeMessage extends Exception{
public void AgeMessage(){
super("年龄范围不匹配");
}
public void AgeMessage(String message){
super(message);
}
public String getMessage(){
return "错误信息提示";
}
}
Demo类 抛出异常,打印错误信息
public class Demo{
private void setAge(int age) throws AgeException{
if(age>=1&&age<=100){
this.age=age;
}else{
throw new AgeException("调用有参处理信息");
}
}
public void Method1(){
try{
setAge(1000);
}catch(AgeException e){
System.out.println(e.getMessage());
}
}
}
应用场景
java不可能把所有的项目中出现的异常都实现准备好
所以程序员根据需求定义异常类
在自定义的异常类中提供异常错误信息