1、认识异常
在java中,程序执行的过程中发生不正常的行为叫做异常,比如:
算数异常:
System.out.println(10 / 0);
// 执行结果
Exception in thread "main" java.lang.ArithmeticException: / by zero
数组越界异常:
int[] arr = {1, 2, 3};
System.out.println(arr[100]);
// 执行结果
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 100
空指针异常:
int[] arr = null;
System.out.println(arr.length());
// 执行结果
Exception in thread "main" java.lang.NullPointerException
2、下面是异常体系结构图
Throwable是顶层类派生出Error和Exception两个子类
Error:是指虚拟机无法解决的问题,比如:JVM内部错误,资源内耗问题;代表:StackOverflowError和OutOfMemoryError,一旦发生回力乏术。
Exception:是指我们程序员可以通过代码进行处理的一些异常,使程序能够正常运行
3、异常抛出
package Exceprion;
import java.io.FileNotFoundException;
import java.io.IOException;
public class File {
public void openFile(String Filename) throws IOException {
if(Filename.endsWith(".ini")){
throw new IOException("文件不是.ini结尾");
}
if(Filename.equals("config.ini")){
throw new FileNotFoundException("文件名配置错误");
}
{
System.out.println("文件正确打开");
}
}
public void readconfig(){
}
public static void main(String[] args) throws IOException {
File file=new File();
// file.openFile("config,ini");
file.openFile("config.ini");
//一般情况下异常都不进行处理,只是为了把异常暴露出来,然后给出提示信息,然后发现程序中的问题
}
}
注意:
throw必须写在方法体内部
抛出的对象必须是Exception或者是Exception的子类
如果抛出的是runtimeException或者runtimeException的子类,则可以不用处理,直接交给虚拟机进行处理
如果抛出的是编译异常,用户必需要进行处理,否则编译不通过
异常一旦抛出,后续代码将不会通过编译进行执行
3.1异常的捕获
异常的捕获也就是异常的处理的具体方式,主要有两种:一种是异常声明throws,而另一种是try-catch语句
3.1.1异常声明throws
处在方法声明参数列表之后,当方法中抛出编译时异常,用户不想处理该异常,可以通过throws抛出给方法的调用者进行处理,这种方式不处理异常,只是提醒方法的调用者处理异常
package Exceprion;
public class Person implements Cloneable{
String name;
String gender;
int age;
public Person(String name, String gender, int age) {
this.name = name;
this.gender = gender;
this.age = age;
}
@Override
public Object clone() throws CloneNotSupportedException {
return new Person(name,gender,age);
}
@Override
public String toString() {
return '['+name+','+gender+','+age+']';
}
public static void main(String[] args) throws CloneNotSupportedException {
Person p1=new Person("小七","男",18);
//代码在编译时报出 cloneNotSupportedException
Object p2=p1.clone();
System.out.println(p2);
//System.out.pritln(); 语法错误这不是异常,
}
}
注意:
(1)throws必须跟在方法的参数列表之后
(2)throws声明的异常必须是Exception或者Exception的子类
(3)方法内部如果抛出了多个异常,throws必须跟多个异常类型,之间用逗号隔开,如果多个异常类型是父子类型,可以直接声明父类异常
(4)调用声明抛出异常的方法时,调用者必须对该异常进行处理,或者连续使用throws抛出给方法的调用者————alt+insert快速进行处理
3.2、try-catch语句捕获异常并处理
throws对异常并没有真正处理,而是将异常报告给抛出异常方法的调用者,由调用者处理。如果真正要对异常进行处理,就需要try-catch。
package Exceprion;
import java.io.FileNotFoundException;
import java.io.IOException;
public class File2 {
public void openConfig(String filename) throws FileNotFoundException{
if(!filename.equals("config.ini")){
throw new FileNotFoundException("配置文件名字不对");
}
// 打开文件
}
public void readConfig(){
}
public static void main(String[] args) {
File2 file2 = new File2();
try{
file2.openConfig("config.ini");
System.out.println("文件打开成功");
}
catch (IOException e){
// 异常的处理方式
//System.out.println(e.getMessage());// 只打印异常信息
//System.out.println(e); // 打印异常类型:异常信息
e.printStackTrace(); // 打印信息最全面
}
// 一旦异常被捕获处理了,此处的代码会执行
System.out.println("异常如果被处理了,这里的代码也可以执行");
}
}
注意:
(1)try块内抛出异常之后位置的代码不再执行
(2)如果抛出异常类型与catch时异常类型不匹配,则异常不会被成功捕获,也不会被处理,异常会被继续抛出,直到JVM收到中断程序----异常是按照类型来捕获的
(3)try中可能会抛出多个异常对象,则必须使用多个catch来进行捕获,即多种异常,多次捕获
(4)如果异常具有子父类关系,则一定要子类在前catch,父类在后catch,否则语法错误
(5)可以使用catch捕获多个异常,但是这种写法不推荐
(6)由于 Exception 类是所有异常类的父类. 因此可以用这个类型表示捕捉所有异常.
4、Finally
在写程序时,有些特定的代码,不论程序是否发生异常,都需要执行,比如程序中打开的资源:网络连接、数据库连接、IO流等,在程序正常或者异常退出时,必须要对资源进进行回收。另外,因为异常会引发程序的跳转,可能导致有些语句执行不到,finally就是用来解决这个问题的。
语法格式:
try{
// 可能会发生异常的代码
}catch(异常类型 e){
// 对捕获到的异常进行处理
}finally{
// 此处的语句无论是否发生异常,都会被执行到
}
// 如果没有抛出异常,或者异常被捕获处理了,这里的代码也会执行
注意:finally中的代码一定会执行,一般在finally中进行一些资源扫尾的工作
5、用户异常登录问题:
package Exceprion;
import org.omg.CORBA.portable.UnknownException;
import java.io.IOException;
import java.util.Scanner;
//实现用户登录系统
public class UserLogin {
public static String name="乔文博";
public static String password="123456789";
public static void main(String[] args) throws IOException {
System.out.println("请输入登录名:");
Scanner sc=new Scanner(System.in);
String name=sc.nextLine();
System.out.println("请输入用户密码:");
String password=sc.nextLine();
compare(name,password);
}
public static void compare(String name,String password) throws IOException {
if(!UserLogin.name.equals(name)){
throw new IOException("用户名异常!!!");
}
else if(!UserLogin.password.equals(password)){
throw new IOException("密码登录异常!!!");
}
else{
System.out.println("登录成功!!");
}
}
}