异常
异常发生的原因
用户输入非法数据
要打开的文件不存在
网络通信时连接中断,或者JVM内存溢出
异常的分类
Throwable 异常类的父类
|--Error类 错误类的父类 不属于程序员负责解决的 通过程序也解决不了
|--Exception 所有能够解决的异常类的父类
|--RuntimeException 运行时异常 在程序的运行时会报错 原因是程序员在写程序时逻辑有问题,但是编译语法是通过的,也叫未建成异常,可以解决也可以不解决(数据运算)
|-- 非RuntimeException 非运行时异常,是编译器可以判断出可能会出现异常的情况,编译器可以进行判断,也叫做已检查异常,对于已检查异常我们必须进行处理,否则编译不通过
常见的运行时异常(未检查异常)
1.数组下标越界异常
案列:
package com.baizhi.entity;
public class TestException {
public static void main(String[] args) {
int[] a = new int[3];
//下标0--2
System.out.println(a[3]);
}
}
异常的信息:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3
at com.baizhi.entity.TestException.main(TestException.java:7)
==========================================
2.空指针异常
案列:
package com.baizhi.entity;
public class TestException {
public static void main(String[] args) {
int[] a = new int[3];
//下标0--2
a = null;
System.out.println(a[0]);
}
}
异常的信息:
Exception in thread "main" java.lang.NullPointerException
at com.baizhi.entity.TestException.main(TestException.java:7)
========================================
3.类型转换异常
案例:
package com.baizhi.entity;
public class Demo {
public static void main(String[] args) {
Animal animal = new Dog();
Cat c = (Cat) animal;
}
}
class Animal{}
class Dog extends Animal(){}
class Cat extends Animal(){}
异常的信息:
Exception in thread "main" java.lang.ClassCastException: com.baizhi.entity.Dog2cannot be cast to com.baizhi.entity.Cat
at com.baizhi.entity.TestException.main(TestException.java:5)
=================================================
4. 数字格式化转换异常
案例:
package com.baizhi.entity;
public class TestException {
public static void main(String[] args) {
String s = "网通";
int i = Integer.parseInt(s);
System.out.println(i);
}
}
异常的信息:
Exception in thread "main" java.lang.NumberFormatException: For input string: "网通"
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Integer.parseInt(Integer.java:492)
at java.lang.Integer.parseInt(Integer.java:527)
at com.baizhi.entity.TestException.main(TestException.java:5)
========================================================================
5.算数异常 除0异常
案列:
package com.baizhi.entity;
public class TestException {
public static void main(String[] args) {
int a = 10;
int b = 0;
System.out.println(a/b);
}
}
异常的信息:
Exception in thread "main" java.lang.ArithmeticException: / by zero
at com.baizhi.entity.TestException.main(TestException.java:7)
异常的产生方式
1.自动产生异常
案例:
算数异常 除0异常
案列:
package com.baizhi.entity;
public class TestException {
public static void main(String[] args) {
int a = 10;
int b = 0;
System.out.println(a/b);
}
}
异常的信息:
Exception in thread "main" java.lang.ArithmeticException: / by zero
at com.baizhi.entity.TestException.main(TestException.java:7)
2.手动产生异常
语法:
throw 异常的对象
案例:
package com.baizhi.entity;
public class TestException {
public static void main(String[] args) {
m();
}
public static void m(){
throw new RuntimeException();
}
}
异常中的两个方法
getMassage():返回此 throwable的详细信息字符串。(常用)
printStackTrace():打印堆栈追踪信息。(常用)
getStackTrace():提供编程访问由printStackTrace()输出堆栈跟踪消息。
非运行时异常(已检查异常)
public static void m(int i) {
//运行时异常
if (i==1) {
throw new ArrayIndexOutOfBoundsException("数组下标越界异常");
}
//非运行时异常
if (i==2) {
throw new FileNotFoundException("文件找不到异常");
}
if(i==3){
throw new EOFException("文件到达末尾异常");
}
if (i==4) {
throw new ClassNotFoundException("类找不到异常");
}
}
已检查异常的处理方式
1.消极处理:将异常一层一层的向上抛出,谁调用我就抛给谁
案列:
import java.io.EOFException;
import java.io.FileNotFoundException;
public class Demo {
public static void main(String[] args) throws FileNotFoundException, EOFException, ClassNotFoundException {
m(2);
}
public static void m(int i) throws FileNotFoundException, EOFException, ClassNotFoundException {
if (i==1) {
throw new ArrayIndexOutOfBoundsException("数组下标越界异常");
}
if (i==2) {
throw new FileNotFoundException("文件找不到异常");
}
if(i==3){
throw new EOFException("文件到达末尾异常");
}
if (i==4) {
throw new ClassNotFoundException("类找不到异常");
}
}
}
常见的异常处理的结构有哪些?
try{}catch(){}
try{}catch(){}catch(){}
try{}catch(){}catch(){}finally{}
try{}catch(){}finally{}
try{ try{}catch(){} }catch(){}
try{}catch(){ try{}catch(){} }
try{}catch(){}catch(){}finally{ try{}catch(){}}
2.积极处理的方式:
语法:
try{
出现异常的代码;
}catch(异常类类名 引用名){
异常处理的代码;
}
案例1:
package cn.baizhi.day17;
import java.io.EOFException;
import java.io.FileNotFoundException;
public class Demo {
public static void main(String[] args) throws FileNotFoundException, EOFException, ClassNotFoundException {
m(2);
}
public static void m(int i) throws EOFException, ClassNotFoundException {
if (i==1) {
throw new ArrayIndexOutOfBoundsException("数组下标越界异常");
}
try {
if (i==2) {
throw new FileNotFoundException("文件找不到异常");
}
} catch (FileNotFoundException e) {
String message = e.getMessage();
System.out.println(message);
e.printStackTrace();
/*StackTraceElement[] stackTrace = e.getStackTrace();
for (int j = 0; j < stackTrace.length; j++) {
System.out.println(stackTrace[j]);
}*/
}
if(i==3){
throw new EOFException("文件到达末尾异常");
}
if (i==4) {
throw new ClassNotFoundException("类找不到异常");
}
}
}
案例2:当try块中存在多个异常时,可以只写一个catch块 但是catch块中的引用一定是try块中抛出的所有异常的父类,可以利用多态,使父类引用只想子类对象
package cn.baizhi.day17;
import java.io.EOFException;
import java.io.FileNotFoundException;
public class Demo {
public static void main(String[] args) {
m(2);
}
public static void m(int i) {
if (i==1) {
throw new ArrayIndexOutOfBoundsException("数组下标越界异常");
}
try {
if (i==2) {
throw new FileNotFoundException("文件找不到异常");
}
if(i==3){
throw new EOFException("文件到达末尾异常");
}
if (i==4) {
throw new ClassNotFoundException("类找不到异常");
}
} catch (Exception e) {
String message = e.getMessage();
System.out.println(message);
e.printStackTrace();
/*StackTraceElement[] stackTrace = e.getStackTrace();
for (int j = 0; j < stackTrace.length; j++) {
System.out.println(stackTrace[j]);
}*/
}
}
}
案列3:
try块后可以有多个catch块 可以对异常进行分别处理。处理的顺序是按照从上到下的顺序,进入符合的catch块中,需要注意的是,catch块中的异常一定是子类异常在前父类异常在后
package cn.baizhi.day17;
import java.io.EOFException;
import java.io.FileNotFoundException;
public class Demo {
public static void main(String[] args) {
m(3);
}
public static void m(int i) {
if (i==1) {
throw new ArrayIndexOutOfBoundsException("数组下标越界异常");
}
try {
if (i==2) {
throw new FileNotFoundException("文件找不到异常");
}
if(i==3){
throw new EOFException("文件到达末尾异常");
}
if (i==4) {
throw new ClassNotFoundException("类找不到异常");
}
} catch (FileNotFoundException e) {
String message = e.getMessage();
System.out.println(message);
e.printStackTrace();
/*StackTraceElement[] stackTrace = e.getStackTrace();
for (int j = 0; j < stackTrace.length; j++) {
System.out.println(stackTrace[j]);
}*/
}catch (EOFException e) {//区别
System.out.println(e.getMessage());
}catch (ClassNotFoundException e) {
System.out.println("已在此处理了类找不到异常");
}
}
}
反例:
package cn.baizhi.day17;
import java.io.EOFException;
import java.io.FileNotFoundException;
public class Demo {
public static void main(String[] args) {
m(3);
}
public static void m(int i) {
if (i==1) {
throw new ArrayIndexOutOfBoundsException("数组下标越界异常");
}
try {
if (i==2) {
throw new FileNotFoundException("文件找不到异常");
}
if(i==3){
throw new EOFException("文件到达末尾异常");
}
if (i==4) {
throw new ClassNotFoundException("类找不到异常");
}
} catch (Exception e) {//区别
String message = e.getMessage();
System.out.println(message);
e.printStackTrace();
/*StackTraceElement[] stackTrace = e.getStackTrace();
for (int j = 0; j < stackTrace.length; j++) {
System.out.println(stackTrace[j]);
}*/
//直接报错
}catch (EOFException e) {
System.out.println(e.getMessage());
}catch (ClassNotFoundException e) {
System.out.println("已在此处理了类找不到异常");
}
}
}
案列4:对于异常也可以进行单独的处理
package cn.baizhi.day17;
import java.io.EOFException;
import java.io.FileNotFoundException;
public class Demo {
public static void main(String[] args) {
m(3);
}
public static void m(int i) {
if (i==1) {
throw new ArrayIndexOutOfBoundsException("数组下标越界异常");
}
try {
if (i==2) {
throw new FileNotFoundException("文件找不到异常");
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
if(i==3){
throw new EOFException("文件到达末尾异常");
}
} catch (EOFException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
if (i==4) {
throw new ClassNotFoundException("类找不到异常");
}
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
finally块
finally块中的代码最后都会执行
package com.baizhi.entity;
注意:当一个有返回值的方法中的finally块中存在return语句会直接结束方法,那么try块和catch块中的return语句的返回值将没有机会返回
作用:finally块一般用于解决关闭资源的代码
public class TestException {
public static void main(String[] args) {
int m = m(1);
System.out.println(m);
}
//普通的方法
public static int m(int a){
try {
int result = 250/a;
return result;
}catch (RuntimeException e){
return -1;
}finally {
System.out.println("我被执行了");
return 3;
}
}
}
结果:我被执行了
3
关于异常中的注意
throw:写在方法中的用于手动抛出异常对象的语句
throws:声明在方法上,用于声明此方法抛出的异常,写在方法的形参列表后
自定义异常
自己定义一个异常类
自己定义的异常类一定是Throwable的子类
|--运行时异常 可以不处理
|-—非运行时异常 必须处理
注意:当对于RuntimeException可以不处理 所以可以对异常代码进行
try.....finally 或者 try...catch / try...catch..finally
当对于非运行时异常 处理异常是可以 try...catch / try...catch..finally
案例:
package cn.baizhi.day17;
import java.io.FileNotFoundException;
public class Demo1 {
public static void main(String[] args) throws FileNotFoundException, MyException {
m(2);
}
public static void m(int a) throws RuntimeException
{
try {
if (a==1) {
throw new RuntimeException();
}
}finally{
}
}
}
class MyRuntimeException extends RuntimeException{
public MyRuntimeException() {
// TODO Auto-generated constructor stub
}
public MyRuntimeException(String s) {
super(s);
}
@Override
public String getMessage() {
return super.getMessage();
}
}
class MyException extends Exception{
public MyException() {
}
public MyException(String s) {
super(s);
}
@Override
public String getMessage() {
return super.getMessage();
}
@Override
public void printStackTrace() {
super.printStackTrace();
}
}
方法覆盖时异常处理
在方法覆盖中,子类重写父类的方法时不能抛出比父类更多的异常,如果子类的方法存在比父类更多的异常,只能通过try...catch解决
方法覆盖:
1.方法名 参数列表 返回值必须相同
2.子类的访问修饰符和父类的相同或者比父类更宽
3.子类不能抛出比父类更宽、更多的异常