Java学习 11.23(2)

Java第八天异常

1.1 数组工具类

封装:将重复代码写到函数中,需要使用的时候 通过函数调用形式让代码执行。
    
面向对象思想始于封装。
​
两种情况:1 类的封装[数据模型类封装  其他类封装  ]  2 工具类封装 [数据工具类封装   ArrayTool]
    
    
你能封装一个工具类 其他人也能,官方就封装了一个 Arrays 
 Arrays.equals()      判断俩数组是否完全一样
 Arrays.sort()        数组排序
 Arrays.toString()    将数组转换成格式化字符串
 Arrays.copyOf()      克隆数组
 Arrays.copyOfRange() 提取范围  前闭后开 
 Arrays.binarySearch()  查找出现的索引 没找到返回-1  

1.2 为什么需要异常

​
我们写过一个函数 getMax()  有问题
​
public class ArrayTool {
​
    public static int getMax(int[] arr){
        int max = arr[0];
        for(int i=1;i<arr.length;i++){
            if(arr[i]>max){
                max = arr[i];
            }
        }
        return max;
    }
​
}
当一个数组里面一个数据都没有的时候  就没有最大值一说了。
    @Test
    public void test(){
​
        int[] arr = {};
        int a = ArrayTool.getMax(arr);
        System.out.println(a);
    
    }
​
所以我们今后的代码 70%都是安全判断 30%代码是业务流程 所以我们获取最大值的函数也应该是 先判断是否能获取最大值 
 public static int getMax(int[] arr){
        
        if(arr.length == 0){
            return  -1;
        }
        
        int max = arr[0];
        for(int i=1;i<arr.length;i++){
            if(arr[i]>max){
                max = arr[i];
            }
        }
        return max;
    }
​
但是我们加了判断之后 发现了一个可怕的问题 条件成立该返回什么呢?
发现返回什么都不好使  返回0 -1 本身就有歧义  返回其他的类型又不匹配  所以说return什么都不行
    
所以java就造了一套新的返回形式  异常返回
​
我们以前说 有返回值的函数 一定要有一个可以执行的 return ,但是从今天开始 这句话就不要再说了  因为java对于返回值 有两种形式  
    
 return 返回
 throw  返回
    

1.3throw解决问题

public class ArrayTool {
    public static int getMax(int[] arr){
        if(arr.length == 0){
            throw new RuntimeException("?????? 数组为空");
        }
        int max = arr[0];
        for(int i=1;i<arr.length;i++){
            if(arr[i]>max){
                max = arr[i];
            }
        }
        return max;
    }
}
​
什么时候return  什么时候throw?
如果调用者传递的数据没有问题
    我们函数执行方能根据参数正常执行        那就正常return返回 
    如果传递过来的数据有问题 导致无法正常执行 则 异常throw返回
 public void test(){
    
        String  str = "hello world";
        char  a =  str.charAt(-50);
        System.out.println(a);
    
}    
public char charAt(int index) {
        if ((index < 0) || (index >= value.length)) {
            throw new StringIndexOutOfBoundsException(index);
        }
        return value[index];
}    

1.4 执行方抛出异常语法

throw 异常对象

1.5 异常的分类

 

Throwable 可抛出的
    Error    :错误,指的是程序内部出现问题,无法通过代码解决的 例如 OutOfMemoryError 内存超出错误,简单的说 就是内存不够了
              [说是代码无法解决 还是你代码的问题 例如 死循环]
    
    
    Exception:异常,程序传递数据的时候导致无法正常执行代码,通过异常表示。
          
              运行时异常  RuntimeException 和其子类 :程序运行起来之后才会出现的异常 例如:
    
              非运行时异常 RuntimeException分支以外的都称之为非运行时异常:代码写完就会出现 必须要解决 不解决无法执行
              例如 Class.forName("123123123");
​
我们需要记住分类的情况 还要记住常用的异常.
    
    
    
    
    
​
​
​
序号  异常名称    异常描述
​
1   java.lang.ArrayIndexOutOfBoundsException    数组索引越界异常。当对数组的索引值为负数或大于等于数组大小时抛出。
​
2   java.lang.ArithmeticException   算术条件异常。譬如:整数除零等。
​
3   java.lang.SecurityException     安全性异常
​
4   java.lang.IllegalArgumentException  非法参数异常
​
5   java.lang.ArrayStoreException   数组中包含不兼容的值抛出的异常 
​
6   java.lang.NegativeArraySizeException    数组长度为负异常 
​
7   java.lang.NullPointerException  空指针异常。当应用试图在要求使用对象的地方使用了null时,抛出该异常。譬如:调用null对象的实例方法、访问null对象的属性、计算null对象的长度、使用throw语句抛出null等等。
​
​
​
序号  异常名称    异常描述
​
1   IOException 操作输入流和输出流时可能出现的异常
​
2   EOFException    文件已结束异常
​
3   FileNotFoundException   文件未找到异常
​
 
​
序号  异常名称    异常描述
​
1   ClassCastException  类型转换异常类
​
2   ArrayStoreException 数组中包含不兼容的值抛出的异常
​
3   SQLException    操作数据库异常类
​
4   NoSuchFieldException    字段未找到异常
​
5   NoSuchMethodException   方法未找到抛出的异常
​
6   NumberFormatException   字符串转换为数字抛出的异常
​
7   StringIndexOutOfBoundsException 字符串索引超出范围抛出的异常
​
8   IllegalAccessException  不允许访问某类异常
​
9   InstantiationException  
​
 当应用程序试图使用Class类中的newInstance()方法创建
​
一个类的实例,而指定的类对象无法被实例化时,抛出该异常
​
10  java.lang.ClassNotFoundException    找不到类异常。当应用试图根据字符串形式的类名构造类,而在遍历CLASSPAH之后找不到对应名称的class文件时,抛出该异常。
​

1.6 调用方处理异常

A 异常转移(默认方案)
​
    当执行方抛出异常给调用方的时候 ,此时调用方可以使用异常转移的形式来处理异常。
    异常转移的语法:
    @Test
    public void test() throws ClassNotFoundException {   
        Class.forName("123123123");
    }
    在函数的参数后面添加一个 throws 关键字,后面写要转移的异常类。
    此时当前异常会转移给当前函数的调用者。  上层调用者需要去处理本次异常,如果上层一直选择转移,最后就会转移到JVM。JVM就会帮我们去处理异常。
    JVM处理异常的方式非常简单:终止当前程序 打印异常信息到控制台
 
异常转移可以转移多种异常
     @Test
    public void test() throws ClassNotFoundException, FileNotFoundException {
​
        Class.forName("asdf");
​
        new FileOutputStream("123");
​
    }
也可以转移一个总异常
    @Test
    public void test() throws Exception {
​
        Class.forName("asdf");
​
        new FileOutputStream("123");
​
    }

 

B 异常捕获
​
 通过 try{}catch(Exception e){} 代码块进行异常捕获
     
 @Test
public void test()  {
        try {
            Class.forName("asdf");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
​
try{
    // 可能出现异常的代码
    
}catch(异常类型   名字){
    //出现异常之后的解决方案
}

1.7 catch中异常处理方案

  @Test
    public void test() {
​
        try {
            int  a = 0;
            int  b = 0;
            int  i = a/b;
            System.out.println(i);
        }catch (Exception e){
             /*1 打印异常跟踪栈信息*/
             e.printStackTrace();
             /*2 记录日志*/
             /*3 事务回滚*/
        }
​
        System.out.println("123123123");
    }
​
并且catch可以捕获多个异常:分类捕获
@Test
    public void test() {
​
        try {
​
            Class.forName("123");
            new FileOutputStream("123");
​
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
​
    }
​
但是不能把总异常写到前面
@Test
    public void test() {
​
        try {
​
            Class.forName("123");
            new FileOutputStream("123");
​
        } catch (Exception e){
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
​
    }
因为异常的catch是从上往下依次查找执行的  所以我们捕获总异常一般写到最后用来兜底
 @Test
    public void test() {
​
        try {
​
            Class.forName("123");
            new FileOutputStream("123");
​
            System.out.println("12313123123123");
            System.out.println("12313123123123");
            System.out.println("12313123123123");
​
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (Exception e){
            e.printStackTrace();
        }
​
    }
此时 我们的catch 是分类捕获 还是 只捕获总的呢?
分情况: 如果我们不一样的异常处理方案不一样 就需要分类捕获  如果所有的异常处理方案都一样 则直接捕获总的

 

1  封装函数
2  调用者传递参数可能非法
3  执行方 安全判断 有问题的异常返回  throw  异常对象
4  异常的分类   
    Throwable  Error  Exception : 运行时 和 非运行时
​
5  调用方处理异常 
   A 异常转移 不处理默认走转移 转移方式 函数后面添加 throws 异常类名 可以写多个 如果一直转就到了JVM 就终止了 打印了
   B 异常捕获 通过try{}catch(){} try中写可能出现异常的代码  catch用来在try中代码出现异常之后 处理异常
        
 6 catch 特点: 1 try中出现问题 则直接去catch中执行 接下来try的代码不执行了
               2 catch也不是精准制导 而是从上往下依次询问 所以总异常不能写到最上面 应在在最后兜底
               3 有的时候我们只写一个总的 因为我们不需要分类处理 统一处理的时候只捕获 Exception
​

1.8 finally代码块

我们之前讲过final关键字,代表最终的。今天是finally代码块 代表最终执行的代码。也就是说写到finally中的代码 铁定最后要执行
​
    @Test
    public void test() {
​
        try {
            int i = 1/0;
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            // 以后我们关闭的代码写到这里面
            System.out.println("123");
        }
    }
​
面试题:
 1 final 和 finally 和  finalize 的区别?   
 2 try catch  finally 哪些可以组合使用
    try-catch   try-catch-finally  try-finally 
 3 在try中有个return 请问finally中的代码还执行吗? return前执行还是return后执行?     
public class ArrayTool {
    public static  int  haha(){
        try {
            return  666;
        }finally {
            System.out.println("你好世界");
        }
    }
}
​
如果finally中也有个return 请求到底是哪个生效
public class ArrayTool {
​
    public static  int  haha(){
        try {
            return  666;
        }finally {
            return  777;
        }
    }
}

1.9 自定义异常

​
首先我们看一下 Throwable 源码
    public void printStackTrace() {
        printStackTrace(System.err);
    }
看一下Exception 源码
public class Exception extends Throwable {
    static final long serialVersionUID = -3387516993124229948L;
    public Exception() {
        super();
    }
    public Exception(String message) {
        super(message);
    }
​
    public Exception(String message, Throwable cause) {
        super(message, cause);
    }
​
    public Exception(Throwable cause) {
        super(cause);
    }
    protected Exception(String message, Throwable cause,
                        boolean enableSuppression,
                        boolean writableStackTrace) {
        super(message, cause, enableSuppression, writableStackTrace);
    }
}
​
public
class ArrayIndexOutOfBoundsException extends IndexOutOfBoundsException {
    private static final long serialVersionUID = -5116101128118950844L;
​
    /**
     * Constructs an <code>ArrayIndexOutOfBoundsException</code> with no
     * detail message.
     */
    public ArrayIndexOutOfBoundsException() {
        super();
    }
​
    /**
     * Constructs a new <code>ArrayIndexOutOfBoundsException</code>
     * class with an argument indicating the illegal index.
     *
     * @param   index   the illegal index.
     */
    public ArrayIndexOutOfBoundsException(int index) {
        super("Array index out of range: " + index);
    }
​
    /**
     * Constructs an <code>ArrayIndexOutOfBoundsException</code> class
     * with the specified detail message.
     *
     * @param   s   the detail message.
     */
    public ArrayIndexOutOfBoundsException(String s) {
        super(s);
    }
}
​
​
我们发现 整个集成体系中 子类基本上什么都没有写 全都是调用父类Throwable的函数  子类就写了个构造函数 构造函数还是调用父类的构造函数
发现Throwable的子类一点新东西都没有,那为什么还要建立这一套继承体系呢?
    
 这样做的目的 为了有语义化
    
 假如没有这些子类  此时所有的以异常只能Throwable表示,代码实现的角度将没有毛病,但是从语义的角度将 我们就很难区分此时的异常到底是 越界了?还是类找不到了?还是文件找不到了?

 

java的设想非常好 ,但是无法将全部的异常情景给罗列出来,例如 我现在遇到一个问题 账号不存在 ,没有一个异常能语义化表达这层
所以我们可以自定义异常
​
public class UsernameNotFoundException extends RuntimeException {
    private static final long serialVersionUID = -5116101128118950844L;
​
    /**
     * Constructs an <code>ArrayIndexOutOfBoundsException</code> with no
     * detail message.
     */
    public UsernameNotFoundException() {
        super();
    }
    /**
     * Constructs an <code>ArrayIndexOutOfBoundsException</code> class
     * with the specified detail message.
     *
     * @param   s   the detail message.
     */
    public UsernameNotFoundException(String s) {
        super(s);
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值