什么是异常?
程序运行时,发生的不被期望的事件,它阻止了程序按照程序员的预期正常执行,这就是异常。就是在java编译或运行或者运行过程中出现的错误。
所有的错误都会指向一个最终的父类就是Throwable,Throwable就是可抛出的意思,抛出分为两种情况:
1,由JVM直接抛出
JVM会自动检测程序,如果出现异常,会自动创建该异常的对象,然后去抛出,自动去执行throw new XxxxxException()
2,我们手动进行抛出
在代码中我们手写throw new XxxxxException()
三种类型的异常:
1,检查性异常
由于用户错误或问题引起的异常,这是程序员无法预见的。这些异常在编译时不能被简单的忽略,是在程序运行的时候才发生,一旦该异常发生。我们可以采取一些预备的措施
2,运行时异常
由于程序设计逻辑问题引起的错误,这种异常发生是不能恢复的,与检查异常相反,运行异常可以在编译时被忽略,主要体现在内存上,也可以进行捕获操作
3,错误
错误不是异常,而是脱离程序员控制的问题。错误在代码中通常被忽略。例如,当栈溢出时,一个错误就发生了,它在编译时也是检查不到的。
java中的异常处理机制
对于编译异常都有哪些预备解决的方案呢?
1,声明
在当前异常发生的函数后面throws异常类名,就是预先告诉调用者,自身可能要出错,声明仅仅是告诉调用者,自己可能要有问题,所以对于调用者而言,它有两种解决的方式,throws声明或者捕获
比如:void show() throws XxxxxException(){
throw XxxxxException();//编译时异常,对于这show而言,通过声明throws XxxxxException()告诉调用者,自己有问题,比如调用者是main函数,对于main函数而言有两种解决的方式:1,声明 void main(String [] args) throws XxxxxException(){}2,try{} catch{},如果一直声明下去,最终的调用者就是虚拟机,最后由虚拟机抛出
2,捕获
在当前异常发生的地点,直接将异常处理掉,直接内部消化掉了
void main(){
show();
}
void show(){
try{ //尝试着去执行某些代码
throw new XxxException();// 编译时异常||运行时异常
} catch(XxxException e) { //一旦try中出现异常 则catch将其捕获
//e = new XxxException();
//在catch里面可以做一些修正的工作
}
}
声明和捕获的代码举例:
package test1;
public class ExceptionDemo01 {
/**
* 异常举例:
* teach(){
1.电脑开机
2.老师讲课
}
电脑
start(){
//可能会蓝屏
//可能被水浇了 主板烧了 冒烟
}
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Teacher t=new Teacher("王兴");
try {
t.teach();
} catch (TeacherInteruptException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("公司放假");
}
}
}
class Teacher{
String name;
Computer computer;
public Teacher(String name) {
this.name=name;
computer=new Computer();
}
public void teach() throws TeacherInteruptException {
try {
computer.start();
}
catch(BlueScreenException e) {
e.printStackTrace();
computer.restart();
}
catch(MaoYanException e) {
e.printStackTrace();
/**
* 异常的转换
* 每一个层级都要去考虑不同的结果
* 第一层出现异常A 导致第二层出现异常B ......
* A -> B
*/
throw new TeacherInteruptException("课程无法继续");
}
}
}
class Computer{
int statue=1;//状态 0,正常,1,蓝屏 2,冒烟
public void start() throws BlueScreenException,MaoYanException{
if(statue==2) {
throw new BlueScreenException("电脑蓝屏");
}
else if(statue==1) {
throw new MaoYanException("电脑冒烟");
}
}
public void restart() {
System.out.println("电脑重启了");
}
}
class BlueScreenException extends Exception{
public BlueScreenException(String message) {
super(message);
}
}
class MaoYanException extends Exception{
public MaoYanException(String message) {
super(message);
}
}
class TeacherInteruptException extends Exception{
public TeacherInteruptException(String message) {
super(message);
}
}
现在来看try{}
catch{}
finally{} 此种结构的用法
package part01.异常;
/*
try{
//尝试去执行一些代码
} catch() {
//如果try中出现异常 则catch中将其捕获并修正
} finally {
//无论是否异常发生 都要去执行的代码
}
try catch 如果发生异常 则会进行程序的跳转动作 从try中第一次出现异常的地方跳转至catch
注意:如果手动的将异常throw 之后的代码就成为了不可达(不会执行)
我们可以将必须要执行的代码放入到finally里即可
什么时候要使用finally,什么情况下用finally
IO,数据库连接,网络编程
上述三者都会占用内存资源,如果用完之后不去释放资源,则会导致内存的浪费
所以我们最无论是否在操作的过程中产生异常,上述资源都需要被关闭掉
*/
public class ExceptionDemo02 {
public static void main(String[] args) {
try{
System.out.println("连接一个数据库...");
System.out.println("对数据库进行读写操作...");
// System.out.println(10/0); //此处我捕获的是运行时异常
//throw new NullPointerException();//Unreachable Code
} catch(Exception e) {
e.printStackTrace();
} finally {
System.out.println("关闭数据连接...");
}
}
}
异常在子父类的应用
public class ExceptionDemo03 {
public static void main(String[] args) {
}
}
/*
* 在继承当中使用异常的一些情况(不去管运行时异常)
* 1.父类的函数如果没有声明任何编译时异常,那么子类重写的函数也不能声明
* 就算子类当中出现了编译时异常 也只能进行捕获 不能声明
* 2.父类的函数如果声明了编译时异常,那么子类重写的函数只能声明该异常或该异常的子类的子集
* 3.父类的函数如果声明了多个编译时异常,那么子类重写的函数只能声明这些异常或其子类的子集
* */
class Fu {
void show() throws IOException,SQLException{
}
}
class Zi extends Fu {
void show() throws FileNotFoundException,SocketException,SQLNonTransientException,SQLClientInfoException{
}
}
interface A {
void show();
}
class B implements A {
public void show() {
}
/*
public void show() throws IOException { //Error不可以声明编译时异常
}
*/
}