异常:不正常。在运行时期发生的一些不正常情况。就是异常。
异常的由来。程序运行是总会
class ExceptionDemo
{
public static void main(String[] args)
{
int[] arr=new int[2];
System.out.println(arr[2])
}
}
异常情况有多钟,都需要分别描述,意味着异常情况应该会有一个体系。
多一个异常具备共性不断地向上抽取,就形成了体系。
异常还有一个父类。通过查阅API,发现异常体系是这样的:
Throwable
|--Error严重的问题,一般是由jvm从底层抛出来的问题,通常不需要处理
直接修改程序就可以了。
|--Exception是可以定义针对性的处理方式对这种情况进行处理、
不正常情况分两种,一种是可以解决的Exception,一种是严重性的Error。
无论是error还是Exception ,他们的子类名字的后缀都是父类名。
int []arr=new int(1024*1024*700);//OutOfMemoryError;
虚拟机在内存中分配空间,(名称信息都具备)底层开辟空间失败,将异常抛给调用者。
发生问题之后不用再运算了。将发生的问题抛给调用者知道。抛给了虚拟机。
谁调用主函数交给谁。默认的处理方式:直接将问题(名称,信息,位置打包发给调用者。)
System.out.println(arr[2]);//new ArrayIndexOutOfException();
这个异常体系最大的特点在于该体系中的类和对象都具备可抛性。
可抛性的体现就是无论是类或者对象都可以被throws或者throw所操作
throws操作类。throw操作对象。
通常情况下:
class Demo
{
int div(int a,int b)throws Exception//多了一个标识
{
if(b<0){
throw new FuShuException("错误,不允许除数为负数");
throw new FuShuExceptin(b);
}
if(b==0)//要想手动抛出一个异常对象,必须的用throw关键字.
throw new ArithmeticException("完啦,被零除啦!")
return a/b;//new ArithmeticException("by zero")
}
}
class ExceptionDemo
{
public static void main(String[] args)throws Exception///这面包有可能坏了
//(一个标签。)
{
Demo d=new Demo();//创建对象。
try{
int x=d.div(4,0);
System.out.println("x="+x);
}
catch(Exception e)//引用型的变量。//该变量用于接收抛出的异常。
{
//Exception e=new ArithmeticException();
System.out.println("啊,异常了!");
//调用方法去。(他很张凯迪,但是他爹不张凯迪)
System.out.println("message"+e.getMessage());
System.out.println("toString"+e.toString());
e.printStackTrace();//打印名字,信息,位置。
}
//ArithmeticException:/by zero;调用div,他抛到了这里。
默认的处理方式:抛给jvm(就是名称,信息,位置打包发给调用者,都打印在控制台上;结束
程序)
System.out.println("over");
}
}
异常是可处理的:
处理方式:
1,声明抛出。告诉调用者功能会有问题,通过throws关键字将问题声明在功能上。
2,进行捕捉。可以使用针对性的捕捉代码块完成。
try{
//需要被检测的代码
}
catch(异常类 变量)
{
//异常处理代码
}
finally
{
//一定会被执行的代码
}
//程序会继续往下执行。
throws throw关键字有什么区别?
throws用在函数上,用于功能声明异常,后面跑出的是异常类,可以跑出多个,只要用逗号隔
开就可以。
throw 只能用在函数内,用于抛出异常对象,额外特点,一旦执行,就可以结束功能。
自定义异常:对于常见的不正常情况,java都有对应的描述。比如角标越界
或者空指针等。对于自定义的程序中出现的特有问题,java并没有给出相应的
描述。这是需要我们按照面向对象的思想对这个问题进行描述,像异常一样
将其封装成对象。
定义的方式;
1,定义的方式:定义一个类,对问题进行描述。
2,必须要让这个类继承异常类,具备可抛性。
class FuShuException extends Exception
{
private int num;
FuShuException()
{
super();
}
FuShuException(String message)
{
super(message);
}
FuShuException(int num)
{
this.num=num;
}
public int getNum()
{
return num;
}
}
异常的细节:
1,定义功能,功能内部因为传入参数问题,导致了功能会出现问题。
这时为了解决这个问题
通常我们都会将这个问题通过throws声明在函数上。
目的:为了调用者在使用这个功能的时候,能明确处理方式。也即是说throws跑出的目的是为
了
让调用者预先定义好的问题的处理方式。
2,如果一个功能抛出多个异常。
那么调用该功能时,需要有多个catch进行每个异常的针对性处理。
如果多个catch中有父类异常,一定要定义在最下面。否则编译失败。
3,特殊部分:
函数内throw抛出异常对象,函数上一定要用throws声明。否则编译失败。
调用到声明异常的函数,要进行声明throws声明抛出,或者trycatch捕捉,否则,编译失败。
注意:异常分两种。
1,编译时被编译器检测的异常。
通常都需要此案写针对性的代码进行处理。
2,编译时不被检测的异常。这种异常出现,编译时期是不在检查之列。这种异常称为运行时
异常。
也就是说函数内throw抛出运行时异常,不需要在函数上声明。即使声明了调用者也不用
一定给出预先处理方式,因为她不会导致编译失败。
为了对代码进行修正。
区分方式:Exception中一个特殊的子类:RuntimeException就是运行时异常。
RuntimeException,Exception和其子类都不需要编译时检测。
意味着:我们在自定义异常时,可以继承Exception,称为编译时被检测的异常。
也可以继承RunTimeException,称为运行时异常。
class Demo
{
int div(int a,int b)throws ArithmeticException(Exception1,Exception2,Exception3)
{
return a/b;
int div(int a,int b)throws Exception
{
if(b==0)
{
throw new Exception("异常");
}
int [] arr=new int[a];
if(b>=a)
throw new ArrayIndexOutOfBoundsException("角标越界了")
System.out.println(arr[b])
}
}
class Exception4
{
public static void main(String[] args)
{
Demo d=new Demo();
int num=d,div(4,1);
System.out.println("num="+num);
/*
try{
int x=d.div(4,0);
}
catch(Exception1 e)
{
}
catch(Exception2 e)
{
}
catch(Exception3 e)
{
}*/
}
}
}
//毕老用电脑上课。
//在上课过程中出现故障。比如电脑蓝屏,冒烟。
class LanPingException(string message)
{
LanPingException()
{
super();
}
MaoYanException(String)
}
class Computer
{
private int state=1;
public void run()
{
if(state==2)
throw new LanPingException("电脑蓝屏啦");
if(state==3)
throw new MaoYanException("电脑冒烟啦");
System.out.println("电脑运行");
}
public void reset{
state=1;
System.out.println("电脑重启");
}
}
class Teacher
{
private String name;
private Computer comp;
Teacher(String name)
{
this.name=name;
comp=new Computer();
}
public void prelect()
{
try{
comp.run();
System.out.println(name+"讲课");
}catch(LanPingException e)
{
//重启电脑
comp.reset();
prelect();
}catch(MaoYanException e)
{
test();
throw e;
throw new
}
}
public void test()
{
System.out.println("大家练习");
}
class Exception
{
public static void main(String[] args)
{
Teacher t=new Teacher("毕老师");
t.prelect();
}
}
//
try{}
catch(异常类)
{
异常处理;
}
finally{
一定会被处理的代码。
}
//catch里写return语句,finally还是会被执行。
void add(data)
{
//1连接数据库
//2存储数据。存储失败会发生异常。
//3关闭数据库连接。(不消耗数据库资源)
}
//把连接和处理放在try里,catch (数据库异常 e)
{
异常处理
}
finally{
// 数据库必须关闭。
//主要用于释放资源,无论是否发生异常,有些动作一定要被执行。
}
System.exit(0);//退出虚拟机,这时finally也不会执行。
在进行异常捕捉时,代码块的不同组合。
1,try catch finally
2,try catch//没有需要一定被执行的代码。通常是不需要关闭资源的动作。
3,try finally。处理异常只有catch能完成。//异常并没有被处理,但是却涉及到了资源的
调用,资源需要被关闭,所以就有了将异常进行对外声明,因为没有catch,但是资源是在功
能内部打开的,必须在功能内部关闭,就有了try和finally的组合。
//Exception 覆盖中的细节。
子类在覆盖父类时,如果父类中被覆盖的方法抛出了异常,那么子类覆盖的方法们只能抛出相
同的异常,或者该异常的子类。
如果父类的覆盖方法抛出了多个异常,子类在覆盖时,只能抛出这些异常的子集。
3,如果被覆盖的方法没有抛出异常,子类也不允许抛出异常,如果子类真的出现异常,只能
在子类方法内进行try处理,绝对不允许throws声明。万一处理不了呢?你可以选择抛出运行
时异常。
interface Inter
{
void show();
}
class InterImpl implements Inter
{
public void show()
{
try{
throw new Exception();
}
catch(Exception e)
{
throw new RuntimeException("xxx异常信息");
}
}
}