异常及处理异常
递归:
* 方法调用方法本身的现象而不是方法嵌套方法!
*
* 举例
* Math.max(10,Math.max(20,40)) ; 方法嵌套
*
*
* show方法调用自己本身:递归
* public void show(int n){//5
* if(n<0){
* System.exit(0) ;
* }
* System.out.println(n) ; //5
* show(n--) ;
* }
*
*
* 使用递归的前提条件:
* 1)必须有一个方法
* 2)必须存在出口条件(结束条件):否则就是死递归
* 3)有一定的规律
/构造方法不存在递归
* 需求:求出5的阶乘
public class DiguiDemo2 {
public static void main(String[] args) {
//普通方式
//for循环:求阶乘思想
int jc = 1 ;
for(int x = 2 ; x <=5 ; x ++){
jc *=x ;
}
System.out.println(jc);
System.out.println("---------------------------");
//使用递归思想
//定义一个方法
System.out.println(getNum(5));
}
//定义了一个求阶乘的方法
private static int getNum(int i) {
//出口条件:如果i=1,永远是1
if(i==1){
return 1 ;
}else{
//i不等于1
return i*getNum(i-1) ; //5 * getNum(4)
}
}
}
什么是异常:
* 就是程序出问题了!
*
* 体系结构
* Throwable
* 子类
* Error Exception
*
* Error:严重问题: 无法直接使用代码方式解决(内存溢出...(加载大量图片的时候))
* Exception:程序出现的这种问题,是可以通过代码方式解决
* RuntimeException:运行时期异常
* 举例:
* NullPointerException:都属于代码逻辑不严谨导致的!
* 只要不是运行时期的出现的都是属于编译时期异常
编译时期异常和运行时期异常的区别
*
*
* 编译时期异常:必须要进行处理,否则代码通过不了,运行不了!
*
* 如果编译时期异常的代码使用的捕获异常,调用者不需要在处理了!
* try...catch... (开发中:使用捕获)
*
*
* 如果使用throws:抛出异常 在方法声明上使用
* 调用者必须要抛出,否则报错!
*
*
* 运行时期异常:
* 调用者不需要显示处理,可以通过逻辑代码来优化
* 也可以显示处理
*
* 注意事项:
* 不管什么编译和运行时期,尽量在代码中使用try...catch处理...
public class ExceptionDemo3 {
public static void main(String[] args) throws ParseException {
System.out.println("今天天气不错");
// method() ; //调用者
method2() ;
System.out.println("可以踢球...");
}
//运行时期
private static void method2() {
try{
int a = 10 ;
int b = 0 ;
System.out.println(a/b);
}catch (ArithmeticException e){
System.out.println("除数不能为0");
}
/* int a = 10 ;
int b = 0 ;
if(b!=0){
System.out.println(a/b);
}else{
System.out.println("除数为0");
}*/
}
//编译时期
private static void method() throws ParseException {
//日期文本的字符串格式:
/* try {
//可能出现问题的代码
String s = "2021-5-28" ;
//s--->Date日期格式
//解析
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd ") ;
Date date = sdf.parse(s) ; // public Date parse(String source) throws ParseException
} catch (ParseException e) {
System.out.println("解析出问题了...");
}*/
String s = "2021-5-28" ;
//s--->Date日期格式
//解析
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd ") ;
Date date = sdf.parse(s) ; // public Date parse(String source) throws ParseException
}
}
解决异常的方案:
* try...catch...finally:标准格式
* 变形格式
* try...catch
* try...catch...catch...
* try...finally
*
* 捕获异常的执行流程
* 1)首先执行try中的代码
* 2)如果程序在try中出问题了,执行catch语句----jvm创建当前异常类对象:异常类名 e = new 异常类名() ;
* 自动查看是否匹配catch语句中的异常对象,如果匹配,就执行处理的语句!
*
*
* throws:抛出异常
private static void method4() {
try{
int a = 10;
int b = 0;
int[] arr = {1, 2, 3, 4};
System.out.println(arr[4]);
System.out.println(a / b);
System.out.println(arr[0]);
}catch (ArithmeticException | ArrayIndexOutOfBoundsException e){ // jdk7以后的写法: catch捕获多个异常类名
System.out.println("程序出问题了...");
}
}
//方式2:针对多个异常处理,一次性处理,不分别try...catch...
private static void method3() {
//try...catch...catch
try {
int a = 10;
int b = 0;
int[] arr = {1, 2, 3, 4};
System.out.println(arr[4]);
System.out.println(a / b);
System.out.println(arr[0]);
}catch (Exception e){
System.out.println("出问题了...");
/* }catch(ArrayIndexOutOfBoundsException e){
System.out.println("访问数组中不存在的角标");
}catch(ArithmeticException e){
System.out.println("除数不能为0");*/
}
}
实际开发中:catch语句:具体的异常类名 变量
throws和throw的区别?
*
* 这两个都是属于"抛出"
*
*
* throws:抛出
* 1)抛出在方法声明上,而且方法声明上的异常类名可以跟多个,中间使用逗号隔开
* 2)throws的异常处理交给:调用者进行处理
* 3)throws表示抛出异常的一种可能性
* 4)throws后面跟的异常类名
*
*
* throw:抛出
* 1)是在方法体中使用,并非在方法声明上使用(位置不一样)
* 2)throw的异常处理交给: 方法体中的逻辑语句判断
* 3)throw表单抛出的异常的肯定性(执行某段代码,一定会执行这个异常)
* 4)throw后面跟的异常对象: throw new XXXException() ;匿名对象
private static void method2() throws ArithmeticException{
int a = 20 ;
int b = 0 ;
//加入逻辑判断处理
if(b!=0){
System.out.println(a/b);
}else{
throw new ArithmeticException() ; //表示出现异常的肯定性
}
}
捕获异常的标准格式:
* try{
*
* 可能出现问题的代码
*
* }catch(异常类名 变量名){
*
* 处理语句;
* }finally{
*
* //一般情况
* 释放相关的底层系统资源
* //io流中的流对象 (底层系统资源)
* //Statment:sql语句的执行对象
* //PreparedStatement:预编译的对象
* //Connection:数据库的链接对象
* //ResultSet:结果集对象
* }
*
* finally特点:
* 就是释放相关的系统资源,而且finally语句一定会执行的!
* 除非一种特例,在执行finally语句,jvm退出了! (System.exit(0))
//自己使用try...catch...finally:
//catch语句:针对异常的处理,不会手动处理,都是通过Throwable的功能
//public String getMessage():获取到详细消息字符串
//public String toString():
//异常类的描述 : +getMessage():获取到详细消息字符串
public class FinallyDemo {
public static void main(String[] args) {
//自己使用try...catch...finally:
//catch语句:针对异常的处理,不会手动处理,都是通过Throwable的功能
//public String getMessage():获取到详细消息字符串
//public String toString():
//异常类的描述 : +getMessage():获取到详细消息字符串
try{
String s = "2021-5-28" ;
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd ") ;
Date date = sdf.parse(s) ;
System.out.println(date);
}catch (ParseException e){
//String str = e.getMessage();//Unparseable date: "2021-5-28"
// String str = e.toString() ;//java.text.ParseException: Unparseable date: "2021-5-28"
// System.out.println(str);
//public void printStackTrace():跟踪堆栈打印错误输出流
e.printStackTrace() ;
System.exit(0);
}finally {
System.out.println("这里的代码一定会执行...");
}
}
}
当前try...catch...finally:捕获异常的时候,如果catch语句里面有return语句,finally还会执行吗?
* 在前还是在后? finally一定会执行,在return 前 (将方法已经结束---catch语句中的return语句已经返回路径!)
*
* finally代码除非在执行前 jvm退出,----finally不会出现return,都是去释放资源...
*
*
* final,finally,finalize的区别?
*
* finally :
* 一般使用在异常处理中:捕获异常 格式 try...catch...finally
* 它里面的语句一定会执行(特例:在执行之前jvm退出)
* try...catch...finally---应用场景:
* 业务层(service)代码中 使用捕获异常
*
* 在数据库访问层(dao)代码, 建议使用抛出throws
public class FinallyDemo2 {
public static void main(String[] args) {
System.out.println(getNum(10));
}
private static int getNum(int i) {
try{
i = 20 ;
int b = 0 ;
System.out.println(i/b); //出现异常了
}catch(Exception e){
i = 30 ; //i =30
return i ; //当前位置 已经形成返回路径 i = 30
}finally {
i = 40 ;
//return i ;
}
return i; // return 30
}
}
异常的使用注意事项:
* 1)子类继承父类, 重写父类的方法的时候,如果父类的方法存在抛出异常,那么子类重写的方法的异常
* 要么跟父类方法异常保持一致
* 要么是父类方法异常的子类异常
*
* 2)子类继承父类的时候,子类重写父类方法,如果父类的该方法没有抛出异常,那么子类只能去try...catch,不能throws,
* 一旦子类抛出,那么父类的方法也必须抛出(不推荐更改父类的代码!)
public class ExceptionDemo2 {
public static void main(String[] args) {
}
}
class Father{
/* public void method() throws Exception {
System.out.println("father method");
}*/
public void show(){
System.out.println("show father");
}
}
//子类要重写method方法
class Son extends Father{
/* public void method() throws ArithmeticException{
System.out.println("son method...");
}*/
public void show() {
//将日期文本--->日期格式
//String--->Date
try {
String s = "2021-5-28" ;
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd") ;
Date date = sdf.parse(s) ; //throws----> 父类的方法也必须throws
} catch (ParseException e) {
e.printStackTrace();
}
}
}
如何自定义一个异常类
* 异常体现的结构:
* Throwable
* error exception
* RuntimeException
* 很多运行时期异常
* IOException,ParseException..编译时期异常
*
* 自定义一个类:继承自RuntimeException
* 继承自 Exception
*
* 提供有参构造方法(String message)/无参构造方法
public class ExceptionDemo {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in) ;
System.out.println("请输入学生成绩:");
int socre = sc.nextInt() ;
//创建Teacher类对象
Teacher t = new Teacher();
t.checkStudentSocre(socre);
}
}
自定义一个异常类 继承自RuntimeException
*/
public class MyException extends RuntimeException{
public MyException(){}
public MyException(String message){
super(message) ;
}
}
public class Teacher {
//打分的功能
public void checkStudentSocre(int socre){
//分值:1-100
if(socre<0 || socre>100){
//非法数据
throw new MyException("学生成绩非法...") ;
}else{
System.out.println("学生数据合法...");
}
}
}
下一篇: redis string操作