异常:
程序在执行过程中出现不正常的现象
import java.util.Scanner;
class ExceptionDemon1
{
public static void main(String[] args)
{
Scanner sc=new Scanner(System.in);
System.out.println("请输入除数: ");
int b=sc.nextInt();
System.out.println("请输入被除数: ");
int a=sc.nextInt();
int num=devide(a,b);//
System.out.println("商为: "+num);
}
<pre name="code" class="java">
//除法计算public static int devide(int a,int b){ return a/b;// }}
/*请输入除数:
0
请输入被除数:
1
Exception in thread "main" java.lang.ArithmeticException: / by zero
at ExceptionDemon1.devide(ExceptionDemon1.java:20)
at ExceptionDemon1.main(ExceptionDemon1.java:13)
请按任意键继续. . .*/
主方法是怎么处理异常的?
主方法在处理异常时是没有对异常做相关的处理操作,
仅仅是将异常的信息,以及相关的错误代码打印到控制台上
仅仅是将异常的信息,以及相关的错误代码打印到控制台上
class ExceptionDemon2
{
public static void main(String[] args)
{
int []array={1,4,6,8};
for (int i=0;i<array.length ;i++ )
{
System.out.println(array[i]);
}
}
}
我们应该怎么去处理异常?
由于异常的信息特别多,我们需要将异常的信息进行封装,我们之前学过面向对象,在这里可以采用面向对象的思维去对异常进行封装
但是异常也分为严重与不严重的情况,通过面向对象的思维模式,可以将异常的这两种情况提取出来进行封装,在java中已经进行了一个体系
其顶层是Throwable
Throwable类 是java语言中所有错误和异常的超类
Throwable
Error:不在我们处理范围内的异常,属于严重的错误
Exception:在我们处理范围内的异常,能够通过我们进行处理
实例1:
1.我们骑自行车出去玩,自行车的链条坏了----可处理范围内
2.我们骑自行车出去玩,路断了====不在处理范围内
实例2:
1.得了感冒----可以买要吃解决
2.得了癌症----吃药是无法解决的,属于严重错误
class ExceptionDemon3
{
public static void main(String[] args)
{
byte [] by=new byte[1000*1024*1024];
System.out.println(by);
/*Exception in thread "main" java.lang.OutOfMemoryError: Java heap space---内存溢出
at ExceptionDemon3.main(ExceptionDemon3.java:27)*/
}
}
*Throwable(可抛出;异常;对象)有哪些方法?
getMessage()--返回此Throwable的详细消息字符串(获取异常信息返回字符串)
printStackTrace()--将此 throwable 及其追踪输出至标准错误流。(获取异常类名和异常信息,以及异常出现在程序中的位置,返回值void)
printStackTrace(PrintStream s)--将此 throwable 及其追踪输出到指定的输出流。 (通常用该方法将异常内容保存在日志文件中,以便查阅)
字节流
printStackTrace(PrintWriter s)--将此 throwable 及其追踪输出到指定的 PrintWriter "自己去试"
字符流
toString()--返回此 throwable 的简短描述(获取异常类名和异常信息,返回字符串)
**自己怎么处理异常?
1.try(发现异常)--catch(处理异常) finally(处理) catch是必带的,仅仅try是不可以的
a.try...catch 一发现一处理
b.try...catch...catch... 一发现多处理(无限多)
**原则:先处理小的,再处理大的
import java.util.Scanner;
import java.lang.ArithmeticException;
import java.lang.ArrayIndexOutOfBoundsException;//导入异常
class ExceptionDemon4
{
public static void main(String[] args)
{
//扫描控制台输入
/*Scanner sc=new Scanner(System.in);
System.out.println("请输入除数: ");
int b=sc.nextInt();
System.out.println("请输入被除数: ");
int a=sc.nextInt();*/
/* try//发现异常
//---
{
int num=devide(a,b);//
System.out.println("商为: "+num);
int[]array={1,3};
System.out.println(array[2]);//取不到
}
*/
/* catch(ArithmeticException e)
//-----
{
System.out.println("报错了");
}
catch(ArrayIndexOutOfBoundsException e)
//-----
{
System.out.println("数组脚标越界");
}*/
/*
Exception in thread "main" java.lang.ArithmeticException: / by zero
at ExceptionDemon1.devide(ExceptionDemon1.java:20)
at ExceptionDemon1.main(ExceptionDemon1.java:13)
*/
try
{
int[]array={1,3};
System.out.println(array[2]);
// -
}
catch (Exception e)//catch它的父类,下面任何子类报出来的时候,我们都能捕捉到//超级父类Throwable也可以,但一般会这么做,因为会包含Error的错误,Error也捕捉不到
{
System.out.println("报错了");
// String message=e.getMessage();//获取异常信息返回字符串
// System.out.println(message);//2
// e.printStackTrace();//不返回什么,直接打印到控制台(获取异常类名和异常信息,以及异常出现在程序中的位置,返回值void)
//报错了
//java.lang.ArrayIndexOutOfBoundsException: 2--①
//at ExceptionDemon4.main(ExceptionDemon4.java:71)
System.out.println(e.toString());//(获取异常类名和异常信息,返回字符串)
//java.lang.ArrayIndexOutOfBoundsException: 2--①
}
System.out.println("******结束******");//正常打印
/*
Exception in thread "main" java.lang.ArithmeticException: / by zero
at ExceptionDemon1.devide(ExceptionDemon1.java:20)
at ExceptionDemon1.main(ExceptionDemon1.java:13)
*/
}
//除法计算
public static int devide(int a,int b)
{
return a/b;//
}
}
**①原则:先处理小的,再处理大的
②try处理的优先级问题
③try 和 finally 配合问题
a.
b.
c.try...catch...finally(里面的内容为-无论是否异常-必须执行!)
放在finally里执行的内容一般为:资源必须关闭等操作
d.try..catch...catch... finally
e.try...finally
④为什么不报错的代码我们不一起放到try中?
(try中要报错的系统会预分配内存)
放在try中的内容,在执行过程中java虚拟机会进行分配相应的空间
如果把没有报异常的代码一并放入try中,会降低程序的执行效率,所以通常不报错的代码不放在try中
*/
import java.util.Scanner;
import java.lang.ArithmeticException;
import java.lang.ArrayIndexOutOfBoundsException;//导入异常
class ExceptionDemon5
{
public static void main(String[] args)
{
//扫描控制台输入
Scanner sc=new Scanner(System.in);
System.out.println("请输入除数: ");
int b=sc.nextInt();
System.out.println("请输入被除数: ");
int a=sc.nextInt();
/* try//发现异常
//---
{
int num=devide(a,b);//
System.out.println("商为: "+num);
//int[]array={1,3};
//System.out.println(array[2]);//取不到
} */
/* catch(ArithmeticException e)
//-----
{
System.out.println("报错了");
}
catch(ArrayIndexOutOfBoundsException e)
//-----
{
System.out.println("数组脚标越界");
}
catch(Exception e)
//-----
{
System.out.println("展现的是父类异常");
}*/
System.out.println("------------------分隔符----------------------");
/* try//发现异常
//---
{
int num=devide(a,b);//
System.out.println("商为: "+num);
int[]array={1,3};
System.out.println(array[2]);//取不到
}
catch(ArrayIndexOutOfBoundsException e)
//-----
{
System.out.println("数组脚标越界");
}
catch(Exception e)
//-----
{
System.out.println("展现的是父类异常");
}
finally
{
System.out.println("最终执行,必须执行我");
}*/
System.out.println("------------------分隔符1----------------------");
/* try//发现异常
//---
{
int[]array={1,3};
System.out.println(array[2]);//取不到
}
catch(ArrayIndexOutOfBoundsException e)
//-----
{
System.out.println("数组脚标越界");
}
finally
{
System.out.println("最终执行,必须执行我1");
}
try//发现异常
//---
{
int num=devide(a,b);//
System.out.println("商为: "+num);
}
catch(Exception e)
//-----
{
System.out.println("展现的是父类异常");
}
finally
{
System.out.println("最终执行,必须执行我2");
}*/
System.out.println("------------------分隔符2----------------------");
//System.exit(0);//相当于是程序式的直接中断,之下的内容就不会被执行
try//发现异常
//---
{
int num=devide(a,b);//
System.out.println("商为: "+num);
System.exit(0);//放在这里也可以,无异常时,num输出,finally也不会被执行,没有"结束"
//但是异常时,直接跳到finally执行,输出printStackTrace(),没有"结束"
}
finally
{
System.out.println("最终执行,必须执行我2");
}//异常的话,执行依然报错,所以没有"结束"
System.out.println("******结束******");//正常打印
}
//除法计算
public static int devide(int a,int b)
{
return a/b;//
}
}
异常的第二种处理方式:
自己不处理该异常,将该异常[抛出,谁调用谁处理抛异常的关键字是throws
*主函数调用了这个异常,主函数两种处理方式
①try..catch 处理掉
②直接抛掉不再处理(不处理,谁调用谁处理)
*处理异常的两种方式到底哪一种好?
原则:能处理则处理,处理不好则抛出
class ExceptionDemon6
{
public static void main(String[] args) throws Exception//下边也不想处理了,直接交给java虚拟机处理---②
{
//int num=devide(10,2);---零
//System.out.println(num);//5
//int num=devide(10,0);---零
//System.out.println(num);//不能除以0
//0
//int num=devide(10,1);---②
//System.out.println(num);//10
int num=devide(10,0);//---②
System.out.println(num);//报异常,printStackTrace()类型
/* try //---①
{
int num=devide(10,0);
System.out.println(num);
}
catch (Exception e)
{
System.out.println("不能除以0");//输出"不能除以0"
}*/
/* try //---①
{
int num=devide(10,1);
System.out.println(num);
}
catch (Exception e)
{
System.out.println("不能除以0");//输出="10"
}*/
}
/*public static int devide(int a,int b)--零
{
int result=0;
try
{
result=a/b;
}
catch (ArithmeticException e)
{
System.out.println("不能除以0");
}
return result;
}*/
//System.out.println("----------分隔符-------------");
public static int devide(int a,int b)throws Exception//---①,②
//ExceptionDemon6.java:13: 错误: 未报告的异常错误Exception; 必须对其进行捕获或声明以便抛出
{
/*int result=0;
try
{
result=a/b;
}
catch (ArithmeticException e)
{
System.out.println("不能除以0");
}
return result;*/
return a/b;
}
}
throws 和throw
throws用于标识函数暴露出的异常
throw用于抛出异常对象
*区别:
1. throws用在函数上,后面跟"异常类名"
throw用在函数内,后面跟"异常对象"
2.throws可以单独使用
throw必须与throws组合使用(RuntimeException)
处理异常:①抛给java虚拟机②try...catch
还有一种:直接抛掉,不想交给谁去处理
**RuntimeException 是那些可能在 Java 虚拟机正常运行期间抛出的异常的超类,
可能在执行方法期间抛出但未被捕获的 RuntimeException 的任何子类都无需在 throws 子句中进行声明。//--在大数据运用中缩短排查错的时间
今后会教怎么用这种方式去排查错误,缩短查找时间
RuntimeException与Exception的区别:
1.Exception是编译时会检测的异常,是需要编写代码进行处理的
2.RuntimeException是运行时的异常,在编译过程中不检测
*/
class ExceptionDemon7
{
/* public static void main(String[] args) throws Exception //--调用的是throws
{
int num=devide(10,0);
System.out.println(num);
}
public static int devide(int a,int b)throws Exception
{
return a/b;
}*/
//----------------------------------------------------------------------------------------
/*
public static void main(String[] args) throws Exception
{
int num=devide(10,0);
System.out.println(num);//10(非异常)
}
public static int devide(int a,int b) throws Exception
{
int result=0;
try
{
result=a/b;
}
catch (ArithmeticException e)
{
throw new Exception("不能除以0");//带有了构造函数--异常的话,printStackTrace(),异常名称为"不能除以0"
}
return result;
}*/
//------------------------------------------------------------------------------------
/*
public static void main(String[] args)
{
try
{
int num=devide(10,0);
System.out.println(num);//10(非异常)
}
catch (Exception e)
{
System.out.println("不能除以0");//输出"不能除以0"(异常)
}
//int num=devide(10,1);
//System.out.println(num);
}
public static int devide(int a,int b) throws Exception
{
int result=0;
try
{
result=a/b;
}
catch (ArithmeticException e)
{
throw new Exception("不能除以0");//带有了构造函数
}
return result;
}*/
//---------------------------------------------------------------------
/*
public static void main(String[] args) throws Exception
{
// try
// {
// int num=devide(10,0);
// System.out.println(num);//10(非异常)
// }
// catch (Exception e)
// {
// System.out.println("不能除以0");//输出"不能除以0"(异常)
// }
int num=devide(10,0);
System.out.println(num);
}
public static int devide(int a,int b) throws Exception
// ---------
// 到时候抛的不是这个异常,而是其他异常,从114行抛出时,可以有效的帮助我们在前面的代码中查找错误
{
int result=0;
try
{
result=a/b;
}
catch (ArithmeticException e)
{
throw new Exception("不能除以0");//带有了构造函数--异常的话,printStackTrace(),异常名称为"不能除以0"
//可以帮我们达到异常的转换目的
}
return result;
}*/
//---------------------------------------------------------------------------------------------------------------
public static void main(String[] args) //不抛--------------抛出的是RuntimeException的时候,主函数中谁调用都不需再处理,
// 也不需要再进行一个声明
{
/* try
{
int num=devide(10,0);
System.out.println(num);//10(非异常)
}
catch (Exception e)
{
System.out.println("不能除以0");//输出"不能除以0"(异常)
}*/
int num=devide(10,0);
System.out.println(num);
}
public static int devide(int a,int b) //不抛
{
int result=0;
try
{
result=a/b;
}
catch (ArithmeticException e)
{
throw new RuntimeException("不能除以0");//带有了构造函数--异常的话,printStackTrace(),异常名称为"不能除以0"
//可以帮我们达到异常的转换目的
}
return result;
} //输出为:Exception in thread "main" java.lang.RuntimeException: 不能除以0
//at ExceptionDemon7.devide(ExceptionDemon7.java:154)
//at ExceptionDemon7.main(ExceptionDemon7.java:140)
}
finalize 当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法。
子类重写 finalize 方法,以配置系统资源或执行其他清除。
final finally finalize三者之间的区别?
final:可以有来修饰类,成员变量,成员方法;如果用来修饰类,则此类不能被继承
如果用来修饰成员变量,则此变量不能被改变,如果用来修饰成员方法,
则此方法不能被重写
finally:属于是异常体系中的一个关键词,一般用于释放资源,永远被执行
但特殊情况System.exit(0)除外
finalize:是Object类中的一个方法,当垃圾回收器确定不存在对该对象的更多引用时,由对象
的垃圾回收器调用此方法
class FinallyDemon8
{
public static void main(String[] args)
{
int final String line="测试";
// -----
try
{
int value=devide(a,b);
System.out.println("商为:"+value);
}
finally ()
{
System.out.println("必须执行我");
}
}
//除法计算
public static int devide(int a,int b)
{
return a/b;
}
}
/*
总结:
Exception异常体系在继承中的表现情况?a.在继承过程中,子类继承方法不能抛比父类中更多更大的异常
b.但可以抛父类中异常的子类异常或是相同的异常,一般是直接抛和父类中相同的异常
*/
/*class Demon
{
public static void printTest()throws ClassNotFoundException
{
System.out.println("调用我会抛异常");//方法抛出了一个异常-----①
//ExtendDemon9.java:12: 错误: 未报告的异常错误ClassNotFoundException; 必须对其进行捕获或声明以便抛出
}
}
class ExtendDemon9 extends Demon
{
public static void main(String[] args) throws Exception//加上(抛出最大的异常)此句后,输出①
// ----------------
{
printTest();
}
}*/
//-----------------------------------------------------------
/*
第二项中
a.throws NotBoundException--ExtendDemon9.java:36: 错误: 找不到符号
b.throws Exception---ExtendDemon9.java:44: 错误: ExtendDemon9中的printTest()无法覆盖Demon中的printTest()
** 在子类中不能抛比①中异常还大的异常,可以抛比它小的异常吗?
*/
/*class Demon
{
public static void printTest()throws ClassNotFoundException//--①
{
System.out.println("调用我会抛异常");
}
}
class ExtendDemon9 extends Demon
{
public static void main(String[] args) throws Exception
{
printTest();
}
public static void printTest() //throws NotBoundException与throws Exception//都拋不过去
// ------------------------
{
System.out.println("我是子类");//重写之后,输出"我是子类"
}
}*/
//*************************************************************************************
//** 在子类中(②)不能抛比①中异常还大的异常,可以抛比它小的异常吗?(①与②的抛出交换)
// A: 只能是相同或是父类中异常的子类 (绝对不能抛上面"没有"的异常)
class Demon
{
public static void printTest()throws Exception//--①
{
System.out.println("调用我会抛异常");
}
}
class ExtendDemon9 extends Demon
{
public static void main(String[] args) throws Exception
{
printTest();
}
public static void printTest()throws ClassNotFoundException//--②
//
{
System.out.println("我是子类");//输出:我是子类
}
}
/*
Q1:为什么要采用自定义异常?(有了java体系定义的那一套异常,为什么还要自定义)
A1:因为java定义的异常是常用的异常,根据我们的业务需求,是无法全部满足的
所以需要自定义异常
Q2;怎么定义自定义异常?
A2:继承Exception或RuntimeException(抛了后者这个异常,不需要在编写代码中做任何处理,但一般很少用这个异常,一般处理一些特殊跟踪异常才会用到)
根据自己的需求,报什么异常,为了跟踪什么错误,然后我们就自己直接自定义异常
*/
/*
class MyException extends Exception
{
private int number;
public MyException(String message,int number)
{
super(message);
this.number=number;
}
public int getNumber()
{
return number;
}
}
class Demon
{
public void devide(int a,int b) throws MyException//如果没这个抛出,则ExceptionDemon10.java:30: 错误: 未报告的异常错误MyException; 必须对其进行捕获或声明以便抛出
{
if (b<0)
{
throw new MyException("除数不能为0",b);
}
else
{
System.out.println("商为:"+a/b);
}
}
}
class ExceptionDemon10
{
public static void main(String[] args)
{
Demon demon=new Demon();
demon.devide(2,3);//ExceptionDemon10.java:44: 错误: 无法将类 Demon中的方法 devide应用到给定类型;
//加上"2,3"后,ExceptionDemon10.java:44: 错误: 未报告的异常错误MyException; 必须对其进行捕获或声明以便抛出
}
}
*/
//------------------------------------------------------------------------------------------------
/*class MyException extends Exception//------------------这里是自定义的异常
{
private int number;
public MyException(String message,int number)
{
super(message);
this.number=number;
}
public int getNumber()
{
return number;
}
}*/
class MyRuntimeException extends RuntimeException
{
public MyRuntimeException(String message)
{
super(message);
}
}
/*class Demon
{
public void devide(int a,int b) throws MyException
{
if (b==0)
{
throw new MyException("除数不能为0",b);//抛出了"除数不能为零"+0
}
else
{
System.out.println("商为:"+a/b);
}
}
}*/
class Demon1
{
public void devide(int a,int b)throws MyRuntimeException
{
if (b==0)
{
throw new MyRuntimeException("除数不能为零");//多了",b",//ExceptionDemon10.java:98: 错误: 无法将类 MyRuntimeException中的构造器 MyRuntimeException应用到给定类型;
}
else
{
System.out.println("商为:"+a/b);
}
}
}
class ExceptionDemon10
{
public static void main(String[] args) //throws MyException//此处相对于上为新增加--不抛,因为要打印异常信息
{
/*try
{
Demon demon=new Demon();
//demon.devide(4,2);//商为:2
demon.devide(4,-0);//0----除数不能为0
//demon.devide(4,-2);//商为:-2
}
catch (MyException e)
{
System.out.println(e.getNumber()+"----"+e.getMessage());
}*/
Demon1 demon1=new Demon1();//上面的已经抛了,这里不需要再做声明了
//demon1.devide(6,1);//6
demon1.devide(6,0);//Exception in thread "main" MyRuntimeException: 除数不能为零
//at Demon1.devide(ExceptionDemon10.java:98)
//at ExceptionDemon10.main(ExceptionDemon10.java:126)
//以上为直接交给java虚拟机进行的处理
}
}