JAVA--异常

异常

java具有健壮性。
   1. GC  垃圾回收   无用对象(堆内存/元空间)
   2. 异常处理机制---> 一段流程出现异常  不影响其它程序的正常执行  

不正常的现象

1. 错误 Error

 public static void main(String[] args) {

       int[] array = new int[1024 * 1000 * 1000];
       System.out.println(array);

  }
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at com.javasm.exception.Demo.main(Demo.java:15)

 

public class Error  extends Throwable
   错误无法处理的。程序只能终止。都是与虚拟机内存/内核有关系的,

 

 

==2. 异常 Exception==

 System.out.println(1/0);
Exception in thread "main" java.lang.ArithmeticException: / by zero
at com.javasm.exception.Demo.main(Demo.java:19)

 

总结:
 相同点:  程序里面的不正常的现象   都继承了Throwable。
     
 不同点:
    Error: 所有的错误父类。无法处理  程序只能终止。
    Exception: 所有异常的父类 利用异常处理机制  可以处理  所有的异常。    

 

1. 常见异常

//数据(用户传来的数据是合法的)
//都是程序写代码不够严谨导致
//ArithmeticException   除数为0
//NullPointerException 变量值为null
//ArrayIndexOutOfBoundsException 数组索引越界
//ClassCastException 类型转换异常

//ParseException 解析异常 求租金

 

处理方式: 2种

1. 捕获  try...catch...finally  真正处理异常的方式
try{
    //有可能出现异常的代码块
}catch(异常类型 对象名称){//捕获一个具体的异常对象
    //处理异常对象功能
}
//多个catch块
[finally{
    //不管程序里面是否出现异常 finally代码块功能 肯定会被执行的
    //物理资源的释放 close
}]        
//锁释放
try{
   //上锁
}finally{
   //释放锁
}

 

2. 抛出  throws   把异常抛出给调用者(上级)---->表示没有能力处理  (消极处理)    
在方法的签名后面  使用throws抛出具体的异常类。    

 

2. 运行时异常

RuntimeException ==不允许在代码里面 对任意的一个运行时异常执行处理 提前预判==

 public static void main(String[] args) {
       demo1();
       //简单字符串的比较
       String str = "abc";
       System.out.println("abc".equals(str));
  }

   private static void demo1() {
       int[] array = {1, 2, 3};
       System.out.println(array[0]);
       System.out.println(array[1]);
       System.out.println(array[2]);
       System.out.println(array[3]);
       //代码里面出现异常 如果不处理 当前(main程序)线程终止
  }

 

常用的方法:
  Throwable(String message)
  Throwable(String message, Throwable cause) ---> 异常信息的传递
 
  1. void printStackTrace()  将异常信息输出到控制台
  2. String getMessage()    获得具体的异常信息字符串          

 

try{
   //有可能出现异常的代码
   
}catch(异常类  异常对象){
   //1. System.out.print()
   //2. 异常对象.printStackTrace();
   //3. System.out.print(异常对象.getMessage())
   //4. return 数据;
   //5. 异常+日志: 将异常信息存储到(不同级别)日志文件中 info warn error debug
   //log4j/log4j2 self4j logback...
   //6.异常信息的传递 throw --->将低级别异常对象传递到高级别的异常对象中 Casued by:
}finally{
   
}
 //代码里面出现异常 如果不处理  当前(main程序)线程终止
   private static int demo1() {
       int[] array = {1, 2, 3};
       System.out.println(array[0]);
       System.out.println(array[1]);
       System.out.println(array[2]);

       //try...catch...finally
       try {
           System.out.println(array[3]);
      } catch (ArrayIndexOutOfBoundsException a) {
           // System.out.println("数组 索引越界,索引的范围: 0-" + (array.length - 1));
           //在catch 一定要写代码 不能捕获异常 什么也不做
//           a.printStackTrace();
           //System.err.println(a.getMessage());
           //return -1;
      } finally {
           System.out.println("肯定会执行的代码。。。。");
      }
       return 1;
  }

 

多个catch块

public static void main(String[] args) {
       //用户录入一些数据
       Scanner input = new Scanner(System.in);
       System.out.println("录入一个字符串:");
       String s = input.nextLine();

       try {

           if (str.equals(s)) {
               System.out.println("true");
          } else {
               System.out.println("false");
          }

           System.out.println(3 / 1);
           
           //在try 虽然有多个catch块 但是 有且只执行一个catch
           //在try里面 异常之后的代码不会被执行的
           //一定要区分哪些代码是稳定代码 哪些非稳定代码
      } catch (NullPointerException e) {
           e.printStackTrace();
      } catch (ArithmeticException e) {
           e.printStackTrace();
      } finally {
           input.close();
      }

       System.out.println("其他代码。。。。");
  }

 

 try {

    if (str.equals(s)) {
        System.out.println("true");
    } else {
        System.out.println("false");
    }

    System.out.println(3 / 1);

    //在try 虽然有多个catch块 但是 有且只执行一个catch
    //在try里面 异常之后的代码不会被执行的
    //一定要区分哪些代码是稳定代码 哪些非稳定代码
} catch (NullPointerException | ArithmeticException | ArrayIndexOutOfBoundsException e) {
    e.printStackTrace();
    //       } catch (Exception e) {
    //           e.printStackTrace();
} finally {
    input.close();
}

 

 

3. 编译时异常

检测到异常。 checked Exception 必须要处理

private static long getMoney(String borrowTime, String backTime) {
       if (borrowTime == null || backTime == null) {
           //应该结束
           System.out.println("参数不能为null");
           System.exit(-1);
      }

       //字符串的数据不能直接进行算术运算 (数值型)
       //将字符串时间转换成数值类型的数据----> 时间间隔
       //1. 将string转java.util.Date   ---> 格式化字符串时间   java.text.SimpleDateFormat
       SimpleDateFormat dateFormat = new SimpleDateFormat(PATTEN);

       //编译时异常(检测到异常)---> 必须要处理
       Date borrowDate = null;
       Date backDate = null;
       try {
           borrowDate = dateFormat.parse(borrowTime);
           backDate = dateFormat.parse(backTime);
      } catch (ParseException e) {
           //System.out.println("字符串时间数据肯定是少于pattern格式规定的内容");
           e.printStackTrace();
//           try {
//               throw new Exception("字符串时间数据肯定是少于pattern格式规定的内容", e);
//           } catch (Exception e1) {
//               e1.printStackTrace();
//           }
      }

       //2. 将Date对象转换成数值类型的数据
       long borrowDateTime = borrowDate.getTime();//获得当前日期毫秒数
       long backDateTime = backDate.getTime();

       //将2个时间的间隔 转换成小时
       return Math.abs((borrowDateTime - backDateTime) / 1000 / 3600);
  }

 

4. throw

在方法体里面: throw new 异常类();

1. 控制流程   遇见throw  程序结束   return;
   
public static void main(String[] args) {
       //求任意2个整数 相除结果
       int num1 = 10;
       int num2 = 1;
       System.out.println(divide(num1, num2));

       userLogin(null, null);

  }

   private static boolean userLogin(String name, String pass) {

//       if (name == null || pass == null) {
//           return false;
//       }

//       if (name == null || pass == null) {
//           throw new NullPointerException("用户名或者密码不能为null");
//       }

       Objects.requireNonNull(name, "用户名不能为null");
       Objects.requireNonNull(pass, "密码不能为null");
       
       return true;
  }

   //除数不能为0
   private static double divide(int num1, int num2) {
       //提前预判数据
       if (num2 == 0) {
           //System.out.println("除数不能为0");
           //System.exit(-1); //java项目中有意义
           throw new ArithmeticException("除数不能为0");
      }

       return num1 / num2;
  }    

 

  1. 异常信息的传递: try/==catch==

 try {
           borrowDate = dateFormat.parse(borrowTime);
           backDate = dateFormat.parse(backTime);
      } catch (ParseException e) {
           //实现异常信息的传递: throw
           //Exception: 也是一个编译时异常
           try {
               throw new Exception("字符串时间数据肯定是少于pattern格式规定的内容", e);
          } catch (Exception e1) {
               e1.printStackTrace();
          }
      }

 

java.lang.Exception: 字符串时间数据肯定是少于pattern格式规定的内容
at com.javasm.exception.ExceptionDemo3.getMoney(ExceptionDemo3.java:49)
at com.javasm.exception.ExceptionDemo3.main(ExceptionDemo3.java:25)
Caused by: java.text.ParseException: Unparseable date: "2021-05-17 12:00"
at java.text.DateFormat.parse(DateFormat.java:366)
at com.javasm.exception.ExceptionDemo3.getMoney(ExceptionDemo3.java:43)
... 1 more
Exception in thread "main" java.lang.NullPointerException
at com.javasm.exception.ExceptionDemo3.getMoney(ExceptionDemo3.java:56)
at com.javasm.exception.ExceptionDemo3.main(ExceptionDemo3.java:25)

 

throw  vs  throws
throws: 处理异常的一种方式
   在方法的签名后面 throws 抛出多个异常类。自己可能没有能力处理  抛出给上级(调用者)  

 

 

5. 自定义异常类

一般都是与throw结合使用。

模拟用户支付:
public class UserPayDemo {

   //用户余额
   private static double balance = 1000;

   public static void main(String[] args) {

       double totalMoney = 2000;
       System.out.println("需要支付:" + totalMoney);

       try {
           pay(totalMoney);
      } catch (BalanceException e) {
           e.printStackTrace();
      }
       System.out.println("账户余额:" + balance);

  }

   private static void pay(double totalMoney) throws BalanceException {
//       if (totalMoney > balance) {
//           System.out.println("账户余额不足的");
//           return;
//       }
       if (totalMoney > balance) {
           throw new BalanceException("账户余额不足,无法扣除");
      }
       balance -= totalMoney;
  }

}  
 

 

 

 

posted @ 2022-10-13 19:10  学JAVA的旅行者  阅读(103)  评论(0)    收藏  举报