Java将程序执行过程中发生的不正常情况成为异常。Java使用统一的异常机制来提供一致的错误报告模型,从而使程序更加健壮。
编程的错误分为语法错误、逻辑错误、异常三种,其中语法错误和逻辑错误不属于异常。因为如果发生语法错误,Java程序根本无法运行;而如果发生逻辑错误,Java程序也不可能得到正确的结果。我们说的异常是指程序既没有语法错误,也没有逻辑错误,而是在运行过程中遇到一些程序以外的错误,导致Java程序发生异常,从而导致Java程序崩溃。
Java将程序执行时可能发生的错误(Error
)或异常(Exception
),都封装成了类,作为java.long.Throwable
的子类,即Throwable
是所有错误或异常的超类。
异常的种类有很多,如空指针异常、类型转换异常、数组下标越界异常等,java将这些异常归为运行时异常(RuntimeException)。针对运行时异常,java编译器将不会给出任何提醒,因此运行时异常又称为非受检异常.
ArrayIndexOutOfBoundsException
:数组小标越界异常。NullPointerException
:空指针异常。ClassCastException
:类型转换异常。ArithmeticException
:算术异常.InputMismatchException
:输入不匹配异常。NumberFormatException
:数字格式化异常。StackOverflowError
:栈内存溢出错误。OutOfMemoryError
:内存溢出错误。通常情况下,异常处理方式有以下三种:
package Exception;
import java.util.InputMismatchException;
import java.util.Scanner;
public class TestTryCatch {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
while(true){
try{
System.out.println("请输入整数被除数:");
int a = input.nextInt();
System.out.println("请输入整数除数:");
int b = input.nextInt();
int result=a/b;
System.out.println("商是:"+result);
break;
}catch (ArithmeticException e){
e.printStackTrace();
System.out.println("除数不能为0");
}catch (InputMismatchException e){
e.printStackTrace();
System.out.println("被除数和除数都必须是整数!");
input.nextLine();//读取流中的非整数数据,否则死循环
}finally {
System.out.println("计算结束");
}
System.out.println("请重新输入!");
}
System.out.println("程序结束");
}
}
情况一:没有异常发生
情况二:发生异常,但是被catch分支捕获
有时候在当前方法中,无法确定如何处理该异常,那么可以将throws(异常信息)抛给上一级处理。
在声明某个方法时,可以通过throws在方法签名中明确需要调用方警惕和处理的异常类型。throws关键字后面可以接一个或多个异常类型。如果有多个异常类型,则使用逗号分割,多个异常类型之间的顺序可以随意。throws后面跟的异常类型,可以是方法中可能产生的异常类型本身或其父类异常类型。
package Exception;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class TestThrows {
public static void readFile(String filePathName) throws FileNotFoundException{
FileInputStream fis = new FileInputStream(filePathName);
//此处省略具体读文件代码
}
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
while(true){
try {
System.out.println("请指定要读取的文件:");
String filePathName=input.next();
readFile(filePathName);
break;
} catch (FileNotFoundException e) {
e.printStackTrace();
System.out.println("文件不存在");
System.out.println("请重新指定");
}
}
}
}
创建异常对象使用关键字new
,抛出异常对象使用关键字throw
。
throws
:可看作try-catch-finally之外的另一种处理异常的方式。在方法声明处,指明可能抛出的一个或多个异常类型,并由方法的调用方进行进一步处理。throw
:可看作自动生成并抛出异常对象之外的另一种生成异常对象的方式,属于手动抛出。在方法体内使用,后面跟异常对象。如果程序执行时运行了throw结构,则需要进一步考虑使用try-catch或throws进行处理。 异常类型虽然也是一个Java
类,但不是所有的Java
类都可以作为异常类型。Java规定异常或错误的类型必须继承现有的Throwable或其子类。因为只有当对象是Throwable
(或其子类之一)的实例时,才能通过Java
虚拟机或throw
语句抛出。类似地,只有此类或其子类之一才可以是catch
子句中的参数类型。
通常我们会继承Exception
或RuntimeException
,而继承RuntimeException
的异常是非受检异常,继承Exception
的异常是受检异常。此外,为了方便地创建异常对象,我们还可以提供多个构造器。
年龄非法异常代码:
import java.util.Scanner;
public class ExceptionTest {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
while(true){
try{
System.out.println("请输入年龄:");
int age=input.nextInt();
if(age>120||age<0){
throw new AgeIllegalException("年龄必须在[0,120]之间!");
}
System.out.println("年龄:"+age);
// break;
}catch (AgeIllegalException e){
System.out.println("请重新输入,原因是:"+e.getMessage());
}
}
}
}
class AgeIllegalException extends Exception{
public AgeIllegalException() {
super();
}
public AgeIllegalException(String message) {
super(message);
}
}
登录异常:
import java.util.Scanner;
public class LoginTest {
public static void login(String username, String password) {
if (!("codeleader".equals(username))) {
throw new LoginException("用户名不存在!");
}
if (!("123".equals(password))) {
throw new LoginException("密码不正确!");
}
}
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("请输入用户名:");
String username = input.next();
System.out.println("请输入密码:");
String password = input.next();
try {
login(username,password);
System.out.println("登录成功");
} catch (Exception e) {
System.out.println("登录失败,原因是:"+e.getMessage());
}
}
}
class LoginException extends RuntimeException {
public LoginException() {
super();
}
public LoginException(String message) {
super(message);
}
}