在java语言中,将程序执行中发生的不正常情况称为"异常"
异常的体系结构
java.lang.Throwable
|- - - -java.lang.Error: 一般不编写针对性的代码进行处理
|- - - -java.lang.Exception: 可以进行异常的处理
|- - - - 编译时异常(checked)
|- - - -IOException
|- - - -FileNotFoundException
|- - - -ClassNotFoundException
|- - - - 运行时异常(unchecked)
|- - - -NullPointerException
|- - - -ArrayIndexOutOfBoundsException
|- - - -ClassCastException
|- - - -NumberFormatException
|- - - -InputMismatchException
|- - - -ArithmeticException
常见的异常处理有哪些?举例说明
public class ExceptionTest{
// ArrayIndexOutOfBoundsException
@Test
public void test2(){
int[] arr = new int[10];
System.out.println(arr[10]);
}
//NullPointerException
@Test
public void test1(){
int[] arr = null;
System.out.println(arr[3]);
}
//ClassCastException
@Test
public void test3(){
// 骗过编译器,但是运行过不了。
Object obj = new Date();
String str = (String)obj;
}
// NumberFormatException
@Test
public void test4(){
String str = "123";
str = "abc"
int num = Integer.parseInt(str);
}
// InputMismatchException 输入不匹配,比如我们这里输入一个abc就会报错
@Test
public void test5(){
Scanner scanner = new Scanner(System.in);
int score = scanner.nextInt();
System.out.println(score);
}
// ArithmeticException
@Test
public void test6(){
int a = 10;
int b = 0;
System.out.println(a/b);
}
//**************************编译时异常************************
@Test
public void test7(){
File file = new File("hello.txt");
FileInputStream fis = new FileInputStream(file);
int data = fis.read();
while(data != -1){
System.out.println((char)data);
data = fis.read()
}
fis.close();
}
}
异常处理机制: try-catch-finaly
java提供的是异常处理的抓抛模型
java程序的执行过程中如果出现异常,会生成一个异常类对象,该异常对象将被提交给Java运行时系统,这个过程称为抛出异常
异常对象的生成:
由虚拟机自动生成: 程序运行过程中,虚拟机检测到程序发生了问题,如果在当前代码中没有找到相应的处理程序,就会在后台自动创建一个对应异常类的实例对象并抛出- - - -自动抛出
由开发人员手动创建: Exception exception = new ClassCastException(); — —创建好的异常对象不抛出对程序没有任何影响,和创建一个普通对象一样。
/**
* try{
* // 可能出现异常的代码
* } catch(异常类型1 变量名1){
* //处理异常的方式1
* }// catch可以写多个
* finally{
*
* }
*/
public class ExceptionTest1 {
@Test
public void test1(){
String str = "123";
str = "abc";
try{
int num = Interger.parseInt(str);
} catch(NumberFormatException e){
System.out.println("出现数值转换异常了,不要着急。。。");
}
// finally 是可选的
// 注意你上方异常捕获了之后,下方的程序是可以正常运行的。
System.out.println("hello --- 2");
}
}
使用try将可能出现异常代码包装起来,在执行过程中,一旦出现异常,就会生成一个对应异常类的对象,根据此对象的类型,去catch中进行匹配
一旦try中的异常对象匹配到某一个catch时,就进入catch中进行异常处理,一旦处理完成,就跳出当前的try-catch结构。(在没有写finally的情况)
我们公司出了一个考题:
getCustomerinfo()方法如下,try中可以捕获三种类型的异常,如果在该方法运行中产生了一个IOException,将会输出什么结果
public void getCustomerinfo(){
try{
//do something that may cause an Exception
} catch(FileNotFoundException ex){
System.out.println("FileNotFoundException ");
} catch(IOexception ex){
Sytem.out.println("IOexception!");
} catch(Exception ex){
Sytem.out.println("Exception!");
}
}
// 答案是IOexception!
记住子类异常一定要声明在父类的上面。否则,报错。
常用的异常对象处理方法:
- String getMessage();
- printStackTrace();
什么时候用finally
这个就不得不提一下jvm的垃圾回收机制了,对于一些jvm无法主动回收的物理链接,我们推荐大家为了避免内存泄漏和浪费内存的情况,像数据库连接、输入输出流、网络编程中的socket等资源,JVM是不能自动回收的,我们需要自己去手动的释放资源。此时的资源释放我们就会放在finally中。
public class FinallyTest{
@Test
public void test2(){
FileInputStream fis = null;
try{
File file = new File("hello.txt");
FileInputStream fis = new FileInputStream(file);
int data = fis.read();
while(data != -1) {
System.out.println((char)data);
data = fis.read();
}
} catch(FileNotFoundException e){
e.printStackTrace();
} catch(IOException e){
e.printStackTrace();
} finally{
try{
fis.close();
} catch(IOException e){
e.printStackTrace();
}
}
}
}
异常处理的方式二: throws
public class ExceptionTest2 {
public void method1() throws FileNotFoundException,IOException{
File file = new File("hello.txt");
FileInputStream fis = new FileInputStream(file);
int data = fis.read();
while(data != -1) {
System.out.println((char)data);
data = fis.read();
}
fis.close();
}
}
"throws + 异常类型"写在方法声明处。指明此方法执行时,可能会抛出异常类型。一旦当方法体执行时,出现异常,仍会在异常代码处生成一个异常类的对象,这个只能算把异常抛出去了,还没有做任何的处理,因为你没有处理异常,所以异常代码后续的代码就不再执行了。
手动抛出异常
public class StudentTest {
}
class Student{
private int id;
public void regist(int id){
if(id > 0){
this.id = id;
}else{
//System.out.println("您输入的数据非法!");
// 手动抛出异常对象,运行异常,就是说你可能会出错可能不错,那你上级调用的时候就可处理也可不处理
// throw new RuntimeException("您的输入数据非法!");
// 这个就包含了编译异常,那编译异常你就不得不去处理了。
throw new Exception("您的输入数据非法!");
}
}
}
如何自定义异常
- 继承于现有的异常结构: RuntimeException、Exception
- 提供全局常量:serialVersionUID
- 提供重载的构造器
public class MyException extends RuntimeExcption{
// UID我乱写的,作用是跨系统的时候,除了类名之外,还有版本号用来区别A系统的对象,是不是B系统的类
static final long serialVersionUID = -12874029734092183490217L;
public MyException(){
}
public MyException(String msg){
super(msg);
}
}