目录
1.代码中的常见异常
1.1算术异常
1.2数组越界异常
1.3空指针异常
1.4输入类型异常
2.异常的基本用法
2.1 捕获异常
2.2 多个异常的捕捉
2.4finally的注意事项
2.5 抛出异常
3.自定义异常类
3.1用户登录
异常就是程序在运行时出现错误时通知调用者的一种机制
常见的算术异常就是指分母为零的情况
public class Abnormal {
public static void main(String[] args) {
System.out.println(5/0);
}
}
编译结果
public class Abnormal {
public static void main(String[] args) {
int[] array = {1,2,3,4,5};
System.out.println(array[10]);
}
}
我定义的数组下标最长为4,但是要访问下标为10的数字明显已经超出了,所以执行结果会显示越界
public class Abnormal {
public static void main(String[] args) {
String str = null;
System.out.println(str.length());
}
}
执行结果
import java.util.Scanner;
public class Abnormal {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
System.out.println(n);
}
}
我定义的是一个整型的数字,但是我输入的是字符串类型,所以会执行出错
程序先执行 try 中的代码如果 try 中的代码出现异常 , 就会结束 try 中的代码 , 看和 catch 中的异常类型是否匹配 .如果找到匹配的异常类型 , 就会执行 catch 中的代码如果没有找到匹配的异常类型 , 就会将异常向上传递到上层调用者 .无论是否找到匹配的异常类型 , fifinally 中的代码都会被执行到 ( 在该方法结束之前执行 ).如果上层调用者也没有处理的了异常 , 就继续向上传递 .一直到 main 方法也没有合适的代码处理异常,就会交给jvm来处理,此时程序就会异常终止。
基本语法
try {
有可能出现异常的语句;
}catch (异常类型 异常对象){
}
finally {
异常出口
}
举个算术异常的例子
public class Abnormal {
public static void main(String[] args) {
try {
System.out.println(10/0);
}catch (ArithmeticException e) {
e.printStackTrace();//找到异常出现的位置
System.out.println("捕捉到了算术异常");
}
System.out.println(555);
}
}
从执行结果来看,捕捉了异常之后并不会影响后面的代码运行
我们来看下如果不捕获异常的话,后面的代码会不会继续执行
public class Abnormal {
public static void main(String[] args) {
System.out.println(10/0);
System.out.println(55);
}
}
由执行结果可知,异常后面的代码不会继续执行
结构(就是可以有多个catch)
在catch多个时,最好是先子类后父类
try {
} catch(Exception e ) {
e.printStackTrace ( );
}catch(Exception e ) {
e.printStackTrace ( );
}
在程序中,我们可以写多个代码捕捉,但如果同时出现多个代码错误时,一次只能捕捉一次,从最开始定义的开始,解决完第一个才能捕捉下一个,如下所示
我们先举例一个空指针异常和数组越界异常的例子
首先会捕捉空指针,空指针解决后才会捕捉数组越界
public class Abnormal {
public static void main(String[] args) {
String str = null;
int[] array = {1,2,3};
try {
System.out.println(str.length());
System.out.println(array[5]);
}catch (NullPointerException e) {
e.printStackTrace();
System.out.println("捕获空指针异常");
}catch (ArrayIndexOutOfBoundsException e) {
e.printStackTrace();
System.out.println("捕获数组越界异常");
}
}
}
看执行结果可知,一次只抛出一个
2.3异常的父类
Exception 类是所有异常类的父类,因此可以用这个类型表示捕捉所有异常。
但父类捕捉到的异常不会告诉你是有什么异常,这个需要自己看。
public class Abnormal {
public static void main(String[] args) {
String str = null;
try {
System.out.println(str.length());
}catch (Exception e) {
e.printStackTrace();
System.out.println("有异常");
}
}
}
import java.util.Scanner;
public class Abnormal {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
try {
System.out.println(10/n);
}catch (Exception e) {
e.printStackTrace();
System.out.println("捕获输入有误");
}finally {
System.out.println("finally执行了");
}
}
在程序中,无论有没有捕获异常,finally都会执行
没有异常时:
有异常时:
finally 会有一个弊端,会覆盖前面不会出错的返回值,所以不建议在finally 中写return
public class Abnormal {
public static int func() {
int a = 12;
try {
return a;
}catch (ArithmeticException e) {
e.printStackTrace();
}finally {
return 20;
}
}
public static void main(String[] args) {
System.out.println(func());
}
按原理返回的是12,但由于finally 执行了,所以返回了20;
public class Abnormal {
public static void func1(int x) throws ArithmeticException {
if(x == 0) {
throw new ArithmeticException("/ by zero");
}
}
public static void main(String[] args) {
try {
func1(1);
}catch (ArithmeticException e) {
e.printStackTrace();
}
}
}
当 x 为0时,就会抛出异常
public class Abnormal {
public static void func1(int x) throws ArithmeticException {
if(x == 0) {
throw new ArithmeticException("/ by zero");
}
}
public static void main(String[] args) {
try {
func1(1);
}catch (ArithmeticException e) {
e.printStackTrace();
}
}
}
自定义异常类就是字面上的意思,用于我们实现一些功能的测试时候抛出的一些异常,且这些异常都是我们觉得有bug的地方。
自定义异常通常会继承自 Exception 或者 RuntimeException继承自 Exception 的异常默认是受查异常继承自 RuntimeException Exception 的异常默认是非受查异常
我们实现一个简单的登录功能,可以抛出两个异常,一个用户名错误,另一个是密码错误。
/**
* 自定义非受查异常类
*/
class NameException extends RuntimeException{
public NameException(String message) {
super(message);
}
}
class PasswordException extends RuntimeException{
public PasswordException(String message) {
super(message);
}
}
public class LogOn {
private static final String name = "fly";
private static final String password = "123456";
/**
* 定义抛出异常
* @param name
* @param password
* @throws NameException
* @throws PasswordException
*/
public static void logon(String name,String password) throws NameException,PasswordException{
if (!LogOn.name.equals(name)) {
throw new NameException("用户名错误");
}
if (!LogOn.password.equals(password)) {
throw new PasswordException("密码错误");
}
System.out.println("登录成功");
}
//异常的检查
public static void main(String[] args) {
try {
logon("fly","123456");
}catch (NameException e) {
e.printStackTrace();
System.out.println("用户名错误");
}catch (PasswordException e) {
e.printStackTrace();
System.out.println("密码错误");
}
}
}