我们可以选择抛出这个异常,然后程序终止,也可以选择将错误输出给用户,然后继续运行。
捕捉异常是我们程序员应该做的事,这能让我们的程序变得更加和谐。我们不能碰到异常就随随便便让程序闪退,也不能随随便便把一些乱七八糟用户看不懂的提示信息给到用户。
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
claculate();
}
public static void claculate()
{
System.out.println("请输入两个整数:");
Scanner input = new Scanner(System.in);
int num1 = input.nextInt();
int num2 = input.nextInt();
int result = devide(num1,num2);
System.out.printf("%s/%s=%s\n",num1,num2,result);
}
public static int devide(int num1,int num2)
{
return num1/num2;
}
}
下面是一个简单的异常信息,这个异常是因为,我在一个除法运算的例子中用0做被除数,这会引发异常。
Exception in thread "main" java.lang.ArithmeticException: / by zero
at ExceptionDemo.Test.devide(Test.java:26)
at ExceptionDemo.Test.claculate(Test.java:19)
at ExceptionDemo.Test.main(Test.java:7)
一条一条分析
Exception in thread "main" //这里指的是异常的线程名
java.lang.ArithmeticException: / by zero //这里是异常的类型与异常爆发的原因
接下去的那三条,就是异常的栈信息
at ExceptionDemo.Test.devide(Test.java:26)
at ExceptionDemo.Test.claculate(Test.java:19)
at ExceptionDemo.Test.main(Test.java:7)
第一行就是引发程序出现异常的根源,下面的那些,都是一层调用一层的信息。由26引发异常,上一个调用来自19行,19行的上一个调用来自7行。
下面仅做了解。
异常是可以被处理的,例如IOException(输出输入异常)、RunntimeException(运行时异常)。
RunntimeException包含了ArithmeticException算数异常、NullPointerException空指针异等等。
在编译期间,所有的非RunntimeException都必须处理。
try
{
//可能引发异常的代码
}
catch(小异常 异常变量名)
{
//指定类型异常发生时,需要执行的代码
}
catch(Exception ex)
{
//指定类型异常发生时,需要执行的代码
}
finally
{
//无论是否发生异常,都一定会执行的代码
}
你可以捕捉多种异常,不过需要满足一个规则——捕捉异常类型的步骤,需要从子类到父类。这件事,儿子能够自己解决,就不需要找到爸爸了。
我们可以在catch里面,提示给用户错误的信息。
catch(Exception ex)
{
ex.printStackTrace(); //输出完整的异常信息(包含也引发异常的调用栈信息)
}
或者是
catch(Exception ex)
{
String msg = ex.getMessage(); //得到异常信息
System.out.println("出现异常,异常信息为" + msg);
}
如果碰到了有些异常,我们处理不了或者是不处理的,我们就需要通过throws语句,通知调用方问题,由调用方自己来处理。
try
{
//可能引发异常的代码
}
catch(小异常 异常变量名)
{
throws; //处理不了,抛给调用方
}
finally
{
//无论是否发生异常,都一定会执行的代码
}
package ExceptionDemo;
public class ExamException extends Exception{
private static final long serialVersionUID = 1L; //默认生成的异常序列号
public ExamException()
{
super(); //调用父类的无参构造函数
}
public ExamException(String msg)
{
super(msg);
}
//cause内部的、根源的异常
public ExamException(String msg,Throwable cause)
{
super(msg,cause);
}
public ExamException(Throwable cause)
{
super(cause);
}
}
所有自定义的异常类都要继承自Exception类。在这个类中重载了一些方法,一般按照这个类写即可。
public class Student {
public void kaoShi(int a,int b) throws ExamException
{
//当两个操作数超过100时,我们就抛出异常
if(a >= 100 || b >= 100)
{
//创建异常对象
ExamException ee = new ExamException("题目太难了,不会做");
throw ee;
}
else
{
int sum = a + b;
System.out.println(sum);
}
}
}
这是一个学生类,这个学生类进行考试,一旦考试的题目太难,我们就抛出异常。如果只写throw是不行的,你还需要声明,你这个方法可能会抛出什么异常。
public class Teacher {
public void schoolTest() throws ExamException
{
Student stu = new Student();
stu.kaoShi(200,1);
}
}
如果你在这个调用的地方,不想捕捉,就继续在方法参数列表后面,继续抛出这个异常。
public class School {
public static void main(String[] args) {
Teacher teacher = new Teacher();
System.out.println("举行全校统考");
try
{
teacher.schoolTest();
}
catch(ExamException ee)
{
System.out.println(ee.getMessage());
}
finally
{
System.out.println("放学");
}
}
}
我们选择在这里捕捉异常,并处理掉。
如果我们想处理,就用try-catch,如果你不处理,就要throws抛出。
如果用户在catch块中使用了return语句,同时又在finally编写了代码。若是在try块中发生了异常,finally中的代码会执行吗。
如果catch块中有return,那么finally后面的语句是不会执行的。
如果catch块中有return,那么finally块中的return没有意义。
如果catch块中有return,那么执行顺序如下,先执行完catch块中除return之外的所有代码,然后去执行finally块中的全部代码。最后,再回来执行catch中的return语句。
2018/4/17 15:38:18 @Author:云都小生