1. 异常机制
1.1 概述
异常是Java中提供的一种识别及响应错误情况的一致性机制。有效地异常处理能使程序更加健壮、易于调试。
异常发生的原因有很多,比如:
- 用户输入了非法数据
- 要打开的文件不存在
- 网络通信时连接中断
- JVM内存溢出
- 这些异常有的是因为用户错误引起,有的是程序错误引起的,还有其它一些是因为物理错误引起的。
1.2 之前常见的异常
1. 空指针
2. 下标越界
3. 栈内存溢出
4. 类型转换异常
1.3 异常继承体系
其中RuntimeException大都是因为程序猿粗心导致的,在编译时不会报错
而IOException在编译时就会报错
1.4 ERROR
1. 概念
系统内部错误,这类错误由系统进行处理,程序本身无需捕获处理。
比如:OOM(内存溢出错误)、VirtualMachineError(虚拟机错误)、StackOverflowError(堆栈溢出错误)等,一般发生这种情况,JVM会选择终止程序。
2. 示例
//堆栈溢出错误
public class TestError {
public static void recursionMethod() {
recursionMethod();// 无限递归下去
}
public static void main(String[] args) {
recursionMethod();
}
}
报错信息:
Exception in thread "main" java.lang.StackOverflowError
at com.TestError.recursionMethod(TestError.java:5)
at com.TestError.recursionMethod(TestError.java:5)
at com.TestError.recursionMethod(TestError.java:5)
at com.TestError.recursionMethod(TestError.java:5)
at com.TestError.recursionMethod(TestError.java:5)
at com.TestError.recursionMethod(TestError.java:5)
1.5 Exception
1.5.1 是什么
Exception是所有异常类的父类。分为非RuntimeException和RuntimeException 。
- 非RuntimeException
指程序编译时需要捕获或处理的异常,如IOException、自定义异常等。属于checked异常。 - RuntimeException
指程序编译时不需要捕获或处理的异常,如:NullPointerException等。属于unchecked异常。一般是由程序员粗心导致的。如空指针异常、数组越界、类型转换异常等。
1.5.2 常用方法
public String get Message():返回关于发生的异常的详细信息,这个消息在Throwable类的构造函数中初始化了
public void printStackTrace():打印toString()结果和栈层次到System.err,即错误输出流
package com;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
/**
* 处理异常的两种方式:
* 1.throws: 抛出异常,告诉调用出这里可能有什么问题
* 如果你把异常抛给了调用出,那么调用出要么也抛出去,要么解决
* 2.try...catch...:解决异常
*
* try{
* 高风险代码;
* }catch(异常类型 变量){
* 解决方案;
* }
* @author 势不可挡的内鬼
*
*/
public class Exception_02 {
public static void main(String[] args) {
//打开资源文件
try {
FileInputStream fis = new FileInputStream("D:/xxx");
System.out.println(123);
// }catch(Exception e) {
}catch(FileNotFoundException e ) {
//打印错误的追踪栈帧,比较常用,适合程序员排错
//e.printStackTrace();
// 获取错误信息,适合响应给用户
String msg = e.getMessage();
System.out.println(msg);
}
System.out.println(456);
}
}
1.5.3 Try...catch...
1.5.3.1 第一种
public static void main(String[] args) {
//打开资源文件
try {
FileInputStream fis = new FileInputStream("D:/xxx");
//如果有一行出错,则try下面的所有代码不执行,开始执行catch
System.out.println(123);
}catch(FileNotFoundException e ) {
//catch是出错之后,做出的解决方案,如果try中代码没有出错,则catch不执行
//打印错误的追踪栈帧,比较常用,适合程序员排错
//e.printStackTrace();
// 获取错误信息,适合响应给用户
String msg = e.getMessage();
System.out.println(msg);
}
//使用try...catch...解决了问题,所以不再终止程序生命周期执行,456可以顺利执行
System.out.println(456);
}
try{
高风险代码;
}catch(异常类型 变量){
解决方案;
}
package com;
import java.io.FileNotFoundException;
import java.io.IOException;
public class Exception_03 {
}
class A{
public void m1() throws IOException{
}
}
class B extends A{
/*
* 方法覆写不能比原方法有更宽泛的异常
* 抛出的异常类,可以是父类方法中抛出的类,也可以是对应的子类,但不能是他的父类
* 父类抛出一个异常A,那么子类要么还要抛出A,要么抛出A的子类,要么不抛出异常,但是不能是A的父类
*
*/
public void m1() throws FileNotFoundException{
}
}
1.5.3.2 第二种
package com;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
/**
* try{
* 高风险代码;
* }catch(异常类型 变量){
* 处理方案;
* }catch(异常类型 变量){
* 处理方案;
* }...
*
* catch中异常类型不能有继承关系,如果有继承关系,需要从子类到父类
* @author 势不可挡的内鬼
*
*/
public class Exception_05 {
public static void main(String[] args) {
try {
FileInputStream fis = new FileInputStream("");
}catch(FileNotFoundException e ) {
System.out.println("找不到文件");
}catch(NullPointerException e) {
System.out.println("不能为null");
}catch(Exception e) {
System.out.println("其他异常");
}
}
}
1.5.3.3 第三种
package com;
import java.io.FileInputStream;
/**
* java1.7新特性 自动关闭资源
* try{
* 开启资源;
* }catch(异常类型 变量){
* 处理措施;
* }finally{
* 关闭资源;
* }
* --------------------------------
* try(开启资源){
* 高风险代码;
* }catch(异常类型 变量){
* 处理措施;
* }
* @author 势不可挡的内鬼
*
*/
public class Exception_10 {
public static void main(String[] args) {
// 自动关闭资源
try (FileInputStream fis = new FileInputStream("222");) {
// 操作
} catch (Exception e) {
e.printStackTrace();
}
}
}
1.5.4 覆写
package com;
import java.io.FileNotFoundException;
import java.io.IOException;
public class Exception_03 {
}
class A{
public void m1() throws IOException{
}
}
class B extends A{
/*
* 方法覆写不能比原方法有更宽泛的异常
* 抛出的异常类,可以是父类方法中抛出的类,也可以是对应的子类,但不能是他的父类
* 父类抛出一个异常A,那么子类要么还要抛出A,要么抛出A的子类,要么不抛出异常,但是不能是A的父类
*
*/
public void m1() throws FileNotFoundException{
}
}
1.5.5 Throws
package com;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
/**
* throws抛出异常,不会处理异常,是一种提醒机制 如果调用的方法抛出一个编译时异常,要么用try...catch解决,要么也抛出给调用出处
* throws是抛出异常,而不会解决,一般用于类库端(被调用的这个类)
* try...catch是解决异常,一般用于客户端调用其他类的这个类,一般客户端都有main方法
*
* @author 势不可挡的内鬼
*
*/
public class Exception_04 {
public static void main(String[] args) throws FileNotFoundException {
m1();
}
public static void m1() throws FileNotFoundException {
m2();
}
public static void m2() throws FileNotFoundException {
m3();
}
public static void m3() throws FileNotFoundException {
FileInputStream fis = new FileInputStream("1111");
}
}
1.5.6 Finally
1.5.6.1 使用
package com;
public class Exception_07 {
public static void main(String[] args) {
try {
int a = 0;
int b = 3;
int c = b/a;
//因为除数不能为0,会报错
System.out.println(c);
}catch (Exception e ) {
e.printStackTrace();
//终止方法执行
return;
}finally {
//不管有没有return,只要不是关闭虚拟机,finally一定执行
System.out.println("111111");
}
//执行不到,因为上面有return
System.out.println("2222222222");
}
}
1.5.6.2 注意
package com;
public class Exception_08 {
public static void main(String[] args) {
int result = m1();
//11
System.out.println(result);
}
public static int m1() {
int i = 10;
try {
//因为finally中有return,并且优先级比较高
//所以在编译的时候,就把这里的return去掉了,只有i++
return i++;
// i++;(在clsaa文件中 是没有return语句的)
}catch(Exception e) {
e.printStackTrace();
}finally {
System.out.println(i+"-------------------");
}
return i;
}
}
1.5.6.3 应用场景
package com;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class Exception_09 {
public static void main(String[] args) {
FileInputStream fis = null;
try {
// 打开资源
fis = new FileInputStream("1111");
// xx操作
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
// 关闭资源
try {
// 判断是否打开资源,如果打开就关闭
if (fis != null) {
fis.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
1.5.7 Throw
异常源点
Throw new 异常类(错误信息);
参考自定义异常
1.5.8 自定义异常类
1.5.8.1 自定义
package ThrowExample;
/**
* 1 继承一个已有的异常类 判断你应该是运行是异常还是编译时异常,如果是运行时异常需要继承 RuntimeException
* 否则就继承Exception即可 一般情况下 我们写的 一定是 编译时异常 2 公共的无参构造 3
* 公共的有参构造,传入字符串,并在构造方法中把该字符串传递给父类
*
* @author 势不可挡的内鬼
*
*/
public class UserException extends Exception{
public UserException() {
}
public UserException(String msg) {
super(msg);
}
}
1.5.8.2 应用场景
package ThrowExample;
public class UserService {
public static void login(String username, String password) throws UserException {
if (username.equals("admin")) {
if (password.equals("root")) {
// TODO 登陆成功
// return "登陆成功";
throw new UserException("密码不正确");
}
} else {
// TODO 用户名不正确
// return "用户名不正确";
throw new UserException("用户名不正确");
}
}
}