1.异常体系
- 几乎所有的代码都会出现异常,为了保证程序在出现异常后可以正常执行完毕,最大化的减少损失的一种保护手段。
- Java中异常也是类。
- 异常类继承关系:只有Throwable以及其子类能够进行异常捕获与处理。
- Error: 描述JVM运行时内部错误,栈溢出,堆溢出;
- Exception: 程序中普遍存在的,由于代码问题产生的;
- IOException: 由于输入输出产生的异常 ,如在程序中打开一个并不存在的文件;
- RuntimeException: 发生在运行时异常,编译时不报错。如数组越界异常,类型转换异常,空指针异常(NPE)
受查异常:除了非受查异常的所有异常类都属于受查异常。即强制用户进行处理。
非受查异常:Error, RuntionException及其子类。即不强制用户进行处理。
2. 异常处理
异常处理:当异常产生时,尽量保证异常之后的代码可以执行。
异常处理的三种格式:
1. try...[1...N]catch...
2. try...finally...
3. try...[1...N]catch...finally...
- try : 所有可能出现异常的代码;
- catch : 当相应异常出现时,捕获该异常,然后自定义处理方式;
- finally :保证重点代码 (如:IO流的关闭,JDBC资源的释放以及网络的连接关闭)一定会执行的机制,无论是否产生异常,finally代码中的内容一定会被执行。
举例:产生异常
public class ExceptionTest {
public static void main(String[] args) {
System.out.println("1.数学计算前...");
System.out.println("2.数学计算中..."+(10/0)); //运行时异常
System.out.println("3.数学计算后..."); //不能被执行
}
}
/**
1.数学计算前...
Exception in thread "main" java.lang.ArithmeticException: / by zero
at www.csdn.qh.ExceptionTest.main(ExceptionTest.java:11)
*/
举例:异常处理
如果有异常出现,执行catch语句;如果没有异常,不执行catch语句
public class ExceptionTest {
public static void main(String[] args) {
System.out.println("1.数学计算前...");
try {
System.out.println("2.数学计算中..."+(10/0));
} catch (Exception e) {
System.out.println("异常被处理了");
}
System.out.println("3.数学计算后...");
}
}
/**
1.数学计算前...
异常被处理了
3.数学计算后...
*/
以上代码中虽然进行了异常处理,但是你根本不知道程序产生了什么异常,所以为了获取异常具体信息,可以直接输出异常类对象,或者调用异常类中提供的printStackTrace()
方法进行完整异常信息的输出。
举例:输出异常信息
public class ExceptionTest {
public static void main(String[] args) {
System.out.println("1.数学计算前...");
try {
System.out.println("2.数学计算中..."+(10/0));
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("3.数学计算后...");
}
}
/**
1.数学计算前...
java.lang.ArithmeticException: / by zero
3.数学计算后...
*/
举例:使用try...catch...finally...
异常处理1
finally作为程序统一出口。
public class ExceptionTest {
public static void main(String[] args) {
System.out.println("1.数学计算前...");
try {
System.out.println("2.数学计算中..."+(10/0));
} catch (Exception e) {
e.printStackTrace();
}finally {
System.out.println("不管是否有异常,都会执行此句");
}
System.out.println("3.数学计算后...");
}
}
/**
1.数学计算前...
java.lang.ArithmeticException: / by zero
不管是否有异常,都会执行此句
at www.csdn.qh.ExceptionTest.main(ExceptionTest.java:12)
3.数学计算后...
*/
举例:使用try...catch...finally...
异常处理2
public class ExceptionTest {
public static void main(String[] args) {
System.out.println(test()); //2
}
public static int test(){
try {
System.out.println(10/0);
return 0;
}catch (ArithmeticException e){
return 1;
}finally {
return 2;
}
}
}
不管try中是否有异常,finally中的代码都会被执行,且优先于try和catch中的代码
举例:将JVM退出exit(),这样不会执行finally
public class Test {
public static void main(String[] args) {
try {
System.out.println("1");
//系统退出
exit(0);
} catch (Exception e) {
System.out.println("2");
} finally {
System.out.println("3");
}
}
}
//1
2.1 非运行时异常(非受查异常)
*Error、RuntimeException及其子类,*不强制用户进行处理。
public class Test {
public static void main(String[] args) {
System.out.println("1.计算开始");
try{
fun();
System.out.println("2.计算开始");
}catch (Throwable e){ //也可以替换成Error
e.printStackTrace(); //java.lang.StackOverflowError
}
System.out.println("3.计算结束");
}
private static void fun() {
fun();
}
}
2.2 受查异常
在IDE工具中,代码底下画红线,不能编译通过,必须要尽心处理。
public class TestString {
public static void main(String[] args) {
File file = new File("abc.txt");
try {
InputStream inputStream = new FileInputStream(file);
} catch (FileNotFoundException e) { //继承IOException
e.printStackTrace();
}
}
}
3.throws
throws:用在方法声明上,明确表示该方法可能会产生异常。当产生异常时,将异常扔给调用者,谁调谁处理。
public class Test {
public static void main(String[] args) {
try {
System.out.println(caculate(10,0));
} catch (Exception e) {
e.printStackTrace();
}
}
private static int caculate(int a, int b)throws Exception {
return a/b;
}
}
//java.lang.ArithmeticException: / by zero
当出现异常时,方法将异常扔回给调用者,当调用者不处理时,可以继续往回扔。实际就是一个帅锅过程
举例:主方法抛出异常
public class Test {
public static void main(String[] args) throws Exception{
System.out.println(caculate(10,0));
}
private static int caculate(int a, int b)throws Exception {
return a/b;
}
}
//Exception in thread "main" java.lang.ArithmeticException: / by zero
4. throw
throw:用在方法中,表示人为进行异常对象的产生。一般与自定义异常类搭配使用。
举例:throw的非受查异常
public class Test {
public static void main(String[] args) {
test(); //运行时异常可以不处理
}
private static void test() {
throw new RuntimeException("扔个异常");
}
}
举例:throw的受查异常
public class TestString {
public static void main(String[] args) throws Exception{
test(); //运行时异常可以不处理
}
private static void test() throws Exception{
throw new Exception("扔个异常"); //报红应处理,此处不处理扔出去
}
}
总结:Exception和RuntimeException的区别
- 使用Exception是RuntimeException的父类,使用Exception定义的异常要求必须使用异常处理,而使用RuntimeException定义的异常可以由用户选择性的来进行异常处理
- 常见的RuntimeException:classCastException、NullPointerException等
5. 自定义异常类
- 在Java中,针对可能出现的公共程序问题都会提供有相应的异常信息,但是这些异常信息往往不够我们使用。所以我们可以自己定义一个属于自己的异常类
- 自定义异常类可以继承两种父类:Exception,RuntimeException
举例:自定义异常类
public class TestString {
public static void main(String[] args) {
int a = 1;
int b = 1;
int c = a+b;
if(c == 2){
throw new AddEexception("此时1+1不能等于2");
}
}
}
class AddEexception extends RuntimeException{
public AddEexception(String msg){
super(msg);
}
}