/*异常:是对问题的处理,将问题进行对象的封装。
异常体系: Throwable
|--Error
|--Exception
|--RuntimeException
只有异常体系中的所有类以及建立的对象才具备可抛性
throws和throw的用法:throw定义在函数内,用于抛出异常对象
throws定义在函数上,用于抛出异常类,可以抛出多个用逗号隔开。
当函数内容有throw抛出异常对象,并未进行try处理,必须要在函数上声明,否则编译失败。
注意:RuntimeException除外,也就是说,函数内如果抛出的是RuntimeException异常,函数上可以不用声明
如果函数声明了异常,调用者需要进行处理,处理方式可以throws 可以try.
------------------------------
异常有两种:
编译时被检测异常:该异常在编译时,如果没有处理(没有抛也没有try),编译失败。该异常被标识,代表这可以被处理。
运行时异常(编译时不检测):在编译时,不需要处理,编译器不检查。该异常的发生,建议不处理,让程序停止。需要对代码进行修正。
---------------------------------
异常的处理方式:
java提供了特有的语句进行处理: 不可以单独使用
try{
需要被检测的代码;
}catch(异常类 变量){
处理异常的代码;(处理方式)
}finally{
一定会执行的语句;//通常用来关闭资源
}
在catch中写return的时候,处理完个异常时就执行return跳出这个函数,不会执行该函数下面的语句,但会执行finally里面的语句。但是当把catch
中的return改为 Ststem.exit(0);(jvm结束)时,下面的finally语句就不会执行。
---------------------------
自定义异常:
定义类继承Exception或RuntimeException
1.为了让该自定义类具备可抛性,2.让该类具备操作异常的共性方法。
当要定义自定义异常的信息时,可以使用父类已经定义好的功能,将异常信息传递给父类的构造函数。
class MyException extends Exception{
MyException(String message){
super(message);
}
}
自定义异常的好处:1.将问题进行封装。2.将正常流程代码和问题处理代码相分离,方便于阅读。
异常的处理原则:
1.处理方式有两种:try 或者 throws
2.调用到抛出异常的功能时,抛出几个,就处理几个。一个try对应多个catch
3.多个catch,父类的catch放到最下面
4.catch内,需要定义针对性的处理方式,不要简单的定义printStackTrace,输出语句,也不要不写
5.当捕捉到的异常,本功能吹了不了时,可以继续在catch中抛出
3.对捕捉到的异常对象进行常见的方法操作:String getMessage();
*/
public class Test1{
public static void main(String[] args){
Demo d=new Demo();
try{
int x=d.div(4,0);//new AritchmeticException();
System.out.println("x="+x);//出现异常就不会执行异常处下面你的程序 异常被捕捉就跳转了
}
catch(Exception e){//捕捉异常 = new AritchmeticException();
System.out.println("除零了!");
System.out.println(e.getMessage());// 异常信息(by zero)
System.out.println(e.toString());// 异常名称:异常信息
e.printStackTrace();//异常名称,异常信息,异常出现的位置。
//其实jvm默认的异常处理机制就是在调用printStackTrace方法,打印异常的堆栈的跟踪信息
}
System.out.println("程序结束");
}
}
class Demo{
int div(int a,int b){//会把异常交给调用它的对象处理
return a/b;
}
}
/*对于多异常的处理:
1.声明异常时,建议声明更具体的异常,这样处理的可以更具体.
2.用throws声明几个异常,(如果用catch处理)就对应有几个catch块进行处理,不要定义多余的catch块。
如果多个catch块中的异常出现异常的关系,父类异常catch块放在在下面。(catch块是按照顺序执行的)
对于异常 要么抛 要么try
*/
public class Test2 {
public static void main(String[] args) {
Demo2 d=new Demo2();
try{
int x=d.div(4, 0);
System.out.println("x="+x);
}catch(ArithmeticException e){
System.out.println(e.toString());
System.out.println("除零了");
}catch(ArrayIndexOutOfBoundsException e){
System.out.println(e.toString());
System.out.println("下标越界了");
}
System.out.println("程序结束");
}
}
class Demo2{
int div(int a,int b) throws ArithmeticException,ArrayIndexOutOfBoundsException{
int[] arr=new int[a];
System.out.println(arr[4]);
return a/b;
}
}
/*因为项目中会出现特有的问题,而这些问题并未被java描述并封装成对象,所以可以将这些特有的问题,进行自定义的异常封装
自定义异常:
1.当在函数中出现了throw抛出异常对象,那么就必须要给对应的处理动作。
2.要么再函数上声明让调用者处理,要么在内部try catch 处理。
一般情况下,在函数内出现异常,函数上需要声明
如何自定义异常信息呢?
因为父类中已经把异常信息的操作都完成了,所以子类只要在构造时,将异常信息通过super(信息)传递给父类
就可以直接通过getMessage()方法获取自定义的异常信息
自定义异常:
必须是自定义类继承Eclipse(原因:异常体系有一个特点:异常类和异常对象都被抛出,他们都具备可抛性,
但是这个可抛性是Throwable这个体系独有的特点,只有这个体系中的类和对象才可以被throws和throw操作)
throws和throw的区别:
throws用在函数上,throw用在函数内
throws后面跟的是异常类,可以跟多个,用逗号隔开; throw后跟的是异常对象。
*/
//在本程序中对除数的负数也认为是无法进行运算的 那么就需要对这个问题进行自定义的描述。
public class Test3 {
public static void main(String[] args) {
Demo3 d=new Demo3();
try{
int x=d.div(4, -1);
System.out.println("x="+x);
}catch(FuShuException e){
System.out.println(e.getMessage());
System.out.println("错误的负数是:"+e.getValue());
System.out.println("出现负数了");
}
System.out.println("程序结束");
}
}
class Demo3{
int div(int a,int b)throws FuShuException{
if(b<0)
throw new FuShuException("构造方法——自定义的负数异常",b);//手动通过throw关键字抛出一个自定义异常对象
return a/b;
}
}
class FuShuException extends Exception{//只有继承Exception才能抛出异常
private int value;
public FuShuException(){
super();
}
public FuShuException(String message, int value){
super(message);//将信息传递给父类中的构造函数
//System.out.println(message);
//b为自定义的函数的信息 父类没有的
this.value=value;
}
public int getValue(){
return value;
}
}
/*对于异常分两种:
1.编译时被检测的异常
2.编译时不能被检测的异常(运行时异常,RuntimeException) 运行时异常
运行时异常:当运行出现这个异常时,程序就不会继续往下执行
*/
public class Test4 {
public static void main(String[] args){
Demo4 d=new Demo4();
try{
int x=d.div(4,-1);
System.out.println("x="+x);
}catch(FuShuException4 e){//处理异常
System.out.println(e.getMessage());
}catch(ArithmeticException e){
System.out.println(e.getMessage());
}
System.out.println("程序结束");
}
}
class Demo4{
public int div(int a,int b)/*throws FuShuException4*/{
if(b<0)
throw new FuShuException4("负数啦");//创建一个异常
if(b==0)
throw new ArithmeticException("除数为零啦");
return a/b;
}
}
class FuShuException4 extends RuntimeException{
public FuShuException4(String message){
super(message);
}
}
/*try catch finally的三种格式用法:
*1.try{} catch(){} 2.try{} catch(){}finally{} 3.try{}finally{}
catch用来处理异常 没有解决就需要抛出问题(throws是抛出问题给别人处理,不需要自己处理),throw则是抛出问题(new 一个异常出来创建问题)
而 finally不是处理问题
异常在子父类覆盖中的体现:
1.子类在覆盖父类时,如果父类的方法抛出异常,那么子类的覆盖方法,只能抛出父类的异常或者该异常的子类(不能抛父类没有的异常)。
2.如果父类方法抛出多个异常,那么子类在覆盖方法时,只能抛出父类异常的子集。
3.如果父类或者接口的方法中没有异常抛出,那么子类在覆盖方法时,也不可以抛出异常。
如果子类方法发生了异常,就必须要进行try处理,绝对不能抛。
当有异常时我们进行处理,异常就回被解决,但程序会继续往下执行,这样当有时候这种异常没有解决的必要时,就可以继承运行时异常
继承RuntimeException时,就不需要catch去处理,因为编译时不会报错
*/
public class Test5 {
public static void main(String[] args) {
Rec r=new Rec(3,-1);//出现异常就跳转带到异常处执行,不会执行r.getArea();
r.getArea();
System.out.println("over");
}
}
class Rec implements Shape{
private int len,wid;
public Rec(int len,int wid){
if(len<=0||wid<=0){
throw new NoValueException("出现非法值");
}
this.len=len;
this.wid=wid;
}
public void getArea(){
System.out.println(len*wid);
}
}
class NoValueException extends RuntimeException{
public NoValueException(String message){
super(message);
}
}
interface Shape{
public void getArea();
}