简介
什么是异常?Java代码在编译或者运行时出现了问题,这就是异常。
在Java中,把异常信息封装成了一个类。当出现了问题时,就会创建异常类对象并抛出异常相关的信息(如异常出现的位置、原因等)。
Throwable类
Throwable 类是 Java 语言中所有错误或异常的超类。只有当对象是此类(或其子类之一)的实例时,才能通过 Java 虚拟机或者 Java throw 语句抛出。类似地,只有此类或其子类之一才可以是 catch 子句中的参数类型。
查看API中Exception的描述,Exception 类及其子类是 Throwable 的一种形式,它用来表示java程序中可能会产生的异常,并要求对产生的异常进行合理的异常处理。
再来看一下与异常Exception平级的Error,它也是Throwable的子类,它用来表示java程序中可能会产生的严重错误。解决办法只有一个,修改代码避免Error错误的产生。
Java中的异常,我们可以靠try…catch(…finally)来进行捕捉
Note:在异常Exception类中,有一个子类要特殊说明一下,RuntimeException子类,RuntimeException及其它的子类只能在Java程序运行过程中出现。
再来具体看一下Throwable类的继承体系:
- Throwable
- Exception
- RuntimeException
- ClassCastException
- NullPointerException
- IndexOutOfBoundsException
- ArithmeticException
- …
- 非运行时异常(checked Exception)
- IOException
- SQLException
- …
- RuntimeException
- Error
- OutOfMemoryError
- AWTError
- …
- Exception
除开上述Java中已经预定义了的异常类,我们还可以自己按几所需自定义异常类。
举个例子
比如,我们在检测用户名密码时,可自定义异常类,来达到提醒用户的目的。
首先,自定义一个UsernameNotFoundException(继承自RuntimeException)
public class UsernameNotFoundException extends RuntimeException {
private String str;
public UsernameNotFoundException() {
super();
// TODO Auto-generated constructor stub
}
public UsernameNotFoundException(String message, Throwable cause, boolean enableSuppression,
boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
// TODO Auto-generated constructor stub
}
public UsernameNotFoundException(String message, Throwable cause) {
super(message, cause);
// TODO Auto-generated constructor stub
}
public UsernameNotFoundException(String message) {
super(message);
// TODO Auto-generated constructor stub
}
public UsernameNotFoundException(Throwable cause) {
super(cause);
// TODO Auto-generated constructor stub
}
public String getStr() {
return str;
}
public void setStr(String str) {
this.str = str;
}
}
然后,再定义一个LoginTest测试一下,如下:
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;
public class LoginTest {
private static Map<String, String> map = new HashMap<String, String>();
public static void main(String[] args) {
map.put("zhangsan", "123456");
map.put("lisi", "147852");
map.put("wangwu", "369147");
try {
login();
} catch (UsernameNotFoundException e) {
e.printStackTrace();
}
}
public static void login() {
Scanner input = new Scanner(System.in);
System.out.println("请输入用户名:");
String inputName = input.next();
System.out.println("请输入密码:");
String inputPasd = input.next();
if(!map.containsKey(inputName)) {
throw new UsernameNotFoundException("user is not exit!");
}else {
Set<String> keys = map.keySet();
for (String key : keys) {
String valuePasd = map.get(key);
if(valuePasd.equals(inputPasd)) {
System.out.println("该用户存在!");
break;
}else {
System.out.println("密码错误,请重新输入!");
break;
}
}
}
input.close();
}
}
运行结果:
请输入用户名:
zhangli
请输入密码:
123456
com.ding.zuoye.UsernameNotFoundException: user is not exit!
at com.ding.zuoye.LoginTest.login(LoginTest.java:30)
at com.ding.zuoye.LoginTest.main(LoginTest.java:16)
上面可以看出,当输入的用户名在Map中不存在时,这个时候,自定义的异常就起了作用,抛出异常,予以提示。
还要说一点就是,如果出现异常我们没有处理,jvm会帮我们进行处理,它会把异常的类型,原因还有位置显示在命令行并且还终止了程序,异常后面的代码将不在执行。
下面举个例子说明一下。
创建一个测试类:
public class TryCatchTest {
public static void main(String[] args) {
char[] arr = {};
System.out.println("0");
try {
System.out.println("A");
System.out.println("B");
} catch (Exception e) {
System.out.println("C");
}finally {
try {
System.out.println("G");
arr[0] = 10;
} catch (Exception e2) {
System.out.println("F");
}
System.out.println("D");
}
System.out.println("E");
System.out.println("==============================");
TryCatchTest tct = new TryCatchTest();
tct.test();
}
public void test() {
System.out.println("0");
Scanner sca = new Scanner(System.in);
try {
int a = sca.nextInt();
System.out.println("1");
if (a%2==0) {
int b = 100/0;
System.out.println(b);
}else {
int d = 100/10;
System.out.println(d);
}
System.out.println("2");
} catch (Exception e) {
System.out.println("3");
e.printStackTrace();
}finally {
System.out.println("4");
}
sca.close();
}
}
运行结果1:
0
A
B
G
F
D
E
==============================
0
3//此处从键盘键入3
10
2
4
运行结果2:
0
A
B
G
F
D
E
==============================
0
2//此处从键盘键入2
1
3
4
java.lang.ArithmeticException: / by zero
at com.ding.exception.TryCatchTest.test(TryCatchTest.java:39)
at com.ding.exception.TryCatchTest.main(TryCatchTest.java:28)
由上述代码:
- 第一点,当异常没有发生时,catch块中的代码不会被执行
- 第二点,当异常发生时,执行catch块中内容,同时,抛出异常的代码后的代码不会再执行。
- 第三点,finally块中的代码必执行
- 第四点,try…catch可进行嵌套
- 最后注意一点,try块必须有,另外二选一