文章目录
一、初始异常
异常是程序中的一些错误,但并不是所有的错误都是异常,并且错误有时候是可以避免的。
java中常见异常:
1.数组越界异常
public static void main(String[] args) {
int[] arr = {1,2,3,4};
System.out.println(arr[5]);
}
2.算术异常
public static void main(String[] args) {
System.out.println(1/0);
}
3.输入异常
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();//这里输入1.0
}
4.空指针异常
public static void main(String[] args) {
int[] arr = null;
System.out.println(arr.length);
}
java中不同类型的异常,都有对象类型的提示.
二、异常的层次
2.1 异常的体系结构
所有的异常类是从 java.lang.Exception 类继承的子类。
2.2 异常的分类
1.检查性异常也称为编译时异常(Checked Exception):最具代表的检查性异常是用户错误或问题引起的异常,这是程序员无法预见的。例如要打开一个不存在文件时,一个异常就发生了,这些异常在编译时不能被简单地忽略。
2.运行时异常也称为非受检查异常(Unchecked Exception): 运行时异常是可能被程序员避免的异常。与检查性异常相反,运行时异常可以在编译时被忽略。比如:NullPointerException、ArrayIndexOutOfBoundsException、ArithmeticException。
三、异常的处理
在Java中,异常处理主要的5个关键字:throw、try、catch、final、throws。
3.1 异常的捕获
使用 try 和 catch 关键字可以捕获异常。try/catch 代码块放在异常可能发生的地方。Catch 语句包含要捕获异常类型的声明,使用 try/catch 的语法如下:
try
{
// 程序代码
}catch(ExceptionName e1)
{
//Catch 块
}
具体实例:
public static void main(String[] args) {
try{
int[] arr = {1,2,3};
arr[3] = 1;
}catch(ArrayIndexOutOfBoundsException e) {
e.printStackTrace();//打印异常信息
System.out.println("数组越界异常!");
}
System.out.println("out");
}
我们可以发现系统处理完异常后,程序正常进行到结束.
多重捕获块:
public static void main(String[] args) {
try{
int arr[] = {0,1,2};
arr[3] = 0;
System.out.println(2/arr[0]);
}catch(ArrayIndexOutOfBoundsException e) {
e.printStackTrace();//打印异常信息
System.out.println("数组越界异常!");
}catch(ArithmeticException e) {
e.printStackTrace();//打印异常信息
System.out.println("算术异常!");
}
System.out.println("out");
}
捕获多个异常:
try{
}catch(ArrayIndexOutOfBoundsException | NullPointerException e) {
}
如果异常之间具有父子关系,一定是子类异常在前catch,父类异常在后catch,否则编译报错.
public static void main(String[] args) {
try{
}catch(Exception e) {
}catch(ArrayIndexOutOfBoundsException e) {
}
}
也可以一个catch捕获,不建议,代码可阅读性差:
public static void main(String[] args) {
try{
}catch(Exception e) {
}
}
阅读时不知道这里的异常到底是什么异常.
3.2 异常的抛出
在编写程序时,如果程序中出现错误,此时就需要将错误的信息告知给调用者,比如:参数检测。在Java中,可以借助throw关键字,抛出一个指定的异常对象,将错误信息告知给调用者。具体语法如下:
throw关键字:
public static int fun(int[] arr,int index) {
if(index < 0 || index >= arr.length) {
throw new ArrayIndexOutOfBoundsException("数组越界!");
}
if(null == arr) {
throw new NullPointerException("数组为空!");
}
return arr[index];
}
public static void main(String[] args) {
int[] arr = {0,1,2};
System.out.println(fun(arr, 3));
}
我们可以自己指定异常信息.
throws关键字:
下面方法的声明抛出一个 RemoteException 异常:
public void deposit(double amount) throws RemoteException
{
throw new RemoteException();
}
一个方法可以声明抛出多个异常,多个异常之间用逗号隔开。例如,下面的方法声明抛出 RemoteException 和 InsufficientFundsException:
public void withdraw(double amount) throws RemoteException,
InsufficientFundsException
{
}
3.3 finally的使用
在写程序时,有些特定的代码,不论程序是否发生异常,都需要执行,比如程序中打开的资源:网络连接、数据库连接、IO流等,在程序正常或者异常退出时,必须要对资源进进行回收。另外,因为异常会引发程序的跳转,可能导致有些语句执行不到,finally就是用来解决这个问题的。
public static void main(String[] args) {
try{
int[] arr = {1,2,3};
arr[3] = 1;
}catch(ArrayIndexOutOfBoundsException e) {
e.printStackTrace();
}finally {
System.out.println("finally已执行!");
}
}
相信大家有一个疑问,try-catch后面的代码会执行,为什么还要使用finally?
public static int get() {
Scanner scanner = null;
int n = 0;
try{
scanner = new Scanner(System.in);
n = scanner.nextInt();
return n;
}catch(InputMismatchException e) {
e.printStackTrace();
}finally {
System.out.println("finally!");
}
System.out.println("try-catch执行完毕!");
if(null != scanner) {
scanner.close();
}
return n;
}
public static void main(String[] args) {
int n = get();
}
当我们输入的值为整型类型时,就会出现类型泄露.
这里执行到第二步程序就终止了,没有对scanner进行释放,只有在finally中加上才能实现程序的安全性.
finally的危险性:
public static int func1() {
try{
return 1;
}finally {
return 2;
}
}
public static void main(String[] args) {
System.out.println(func1());
}
这里输出的是1还是2?
3.4 JVM处理异常
如果我们一直将异常向上抛,抛给主方法还没有处理,系统将会抛给JVM处理,异常终止程序.try中的异常如果没有catch捕捉处理也是一样的.
public static void func2() {
int[] arr = {1,2,3};
arr[3] = 1;
}
public static void main(String[] args) {
func2();
System.out.println("main未处理异常!");
}
四、自定义异常类
在 Java 中你可以自定义异常。编写自己的异常类时需要记住下面的几点:
可以像下面这样定义自己的异常类:
class MyException extends Exception{
}
实现一个登录功能,自定义异常类
public class NameException extends Exception{
public NameException(String message) {
super(message);
}
}
public class PassException extends Exception{
public PassException(String message) {
super(message);
}
}
private String Name = "zd";
private String Word = "000000";
public static void login(String Name,String Word)throws NameException,WordException {
if(!Name.equals(Name)) {
throw new UserNameException("用户名错误!");
}
if(!Word.equals(Word)) {
throw new PassWordException("密码错误!");
}
System.out.println("登录成功!");
}
public static void main(String[] args) {
try {
login("zd","000000");
}catch (NameException e) {
e.printStackTrace();
}catch (WordException e) {
e.printStackTrace();
}
}