JavaSE01_Day05(中)-异常(throws关键字、自定义异常)

一、异常

1.1 throws关键字

       在计算机编程中,会设计很多的业务方法,不同的方法一般情况下会代表着一个功能,如果这个方法在进行书写相关业务逻辑的时候,可能有需要进行处理的异常需要抛出,但是这个方法希望调用者在进行调用的过程中进行处理,而不是在定义的时候就进行处理,此时可以在方法的后方使用throws关键字抛出相关的异常类型,最终由调用者进行对该异常处理。

 package cn.tedu.execption;
 
 import java.io.FileOutputStream;
 import java.io.IOException;
 
 /**
  * throws关键字使用案例
  * @author cjn
  *
  */
 public class ThrowsDemo {
 
     public static void main(String[] args) {
         /*
          * 调用createIO方法
          * 当在main方法中调用了createIO方法时,
          * 1.由于方法后方抛出了IOException异常,
          * 那么最终哪里调用这个方法,哪里就需要对该方法
          * 所出现的异常进行处理。
          * 2.如果在main方法中进行调用时,不建议在main方法后方
          * 继续使用throws关键字,抛出相关异常。
          * 原因是:当抛出以后,如果程序出错,最终的错误是抛给了
          * Java虚拟机(JVM),虚拟机没有处理异常的能力,
          * 最终还会导致程序的瘫痪。
          *3.建议在调用处使用try-catch进行异常的捕获处理
          */
         try {
             createIO();
        } catch (IOException e) {
             e.printStackTrace();
        } catch (Exception e) {
             //查看简单的错误信息
             System.out.println(e.getMessage());
        }
         System.out.println("程序执行完毕");
         
    }
     /**
      * 该方法的作用是创建一个输出流对象,写出数据.
      * 方法内部没有对异常进行捕获处理,而是希望调用方处理
      * @throws IOException
      */
     public static void createIO() throws IOException {
         //创建文件输出流(低级流)对象
         FileOutputStream fos  = new  FileOutputStream("fos.txt");
         //写出整数数据
         fos.write(97);
         //关闭资源
         fos.close();
    }
 
 }

       在定义方法以后,方法中的逻辑如果可能会出现非受检异常(运行时异常时),当调用方调用这个方法时,其实并不会检测出有异常需要进行处理,那么可以凭借着经验,在自己知道可能会发生异常的情况进行使用try-catch捕获处理,如果说不知道还有哪些非受检异常时,可以不加try。这个案例在书写时,方法后方添加throws关键字抛出相关的非受检异常的原因是想带着大家查看,这种情况下,调用方调用该方法仍然不会有编译报错。

 package cn.tedu.execption;
 /**
  * throws关键字对运行时异常的案例演示
  * @author cjn
  *
  */
 public class ThrowsDemo02 {
 
     public static void main(String[] args) {
         String[] strs = {"123","456","789"};
         //运行时异常不属受检异常,所以在调用该方法时不会有编译报错
         
         try {
             getArrayElement(strs);
        } catch (ArrayIndexOutOfBoundsException e) {
             System.err.println(e.getMessage());
        } catch (NullPointerException e) {
             System.out.println(e.getMessage());
        } catch (Exception e) {
             System.out.println(e.getMessage());
        }
         System.out.println("程序结束");
         
    }
     
     /**
      * 获取字符串数组中所有的元素内容
      * strs.length可能出现空指针异常
      * 遍历的时候取了等号的情况可能会出数组下标越界异常
      */
     public static String getArrayElement(String[] strs)
             throws ArrayIndexOutOfBoundsException,NullPointerException{
         String string = "";
         for (int i = 0; i <= strs.length; i++) {
             string = strs[i];
        }
         return string;
    }
 
 }

1.2 被throws关键字抛出异常的方法被重写的情况说明:

       当前这种情况,需要有一个前提条件,这个条件就是存在两个类,类与类之间需要存在继承关系,当超类的某个方法后方使用throws关键字抛出了相关的异常,在派生类对于超类的该方法进行重写时需要满足如下规则:

  • 超类中方法后面抛出什么异常,派生类在重写该方法时原样书写

  • 超类中方法后面抛出的异常,在派生类重写该方法时不添加throws关键字抛出异常

  • 可以在重写超类中的方法时,抛出超类的方法的部分异常

  • 如果在超类的方法后方比如抛出了IOException异常,那么可以在派生类重写方法时,在方法的后方抛出IOException异常的派生类异常

重写时不能操作的:

  • 重写超类中方法时,派生类方法后方使用throws关键字抛出了和超类方法不相干的其他异常

  • 重写超类中方法时,派生类方法后方使用throws关键字抛出的异常时派生类重写方法的超类异常

 package cn.tedu.execption;
 
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.sql.SQLException;
 
 /**
  * 重写派生类中方法带有throws关键字的方法时注意事项案例
  * @author cjn
  *
  */
 public class ThrowsDemo03 {
 
     public static void main(String[] args) {        
    }  
 }
 
 /**
  * 外部派生类
  * @author cjn
  *
  */
 class Son extends Father{
     //public void doSome() throws IOException,ClassCastException{
         //和超类中被重写的方法,所抛出的异常一摸一样,允许
     //}
     
     //public void doSome() throws FileNotFoundException,ClassCastException {
         //和超类中被重写的方法,所抛出的异常是派生类异常,允许
     //}
     //public void doSome() {
         //重写超类方法时,后面抛出的异常取消,允许
     //}
     //public void doSome() throws ClassCastException{
         //重写超类方法时,抛出超类方法的部分异常
     //}
     //public void doSome() throws SQLException,ClassCastException{
         //重写超类方法时,throws后面跟的异常,和超类方法的异常没有任何的关系,不允许
     //}
     
     //public void doSome() throws Exception{
         //重写超类方法时,throws后面跟的异常,是超类方法抛出异常的超类,不允许
     //}
 }
 
 /**
  * 外部类超类
  * @author cjn
  */
 class Father {
     
     public void doSome() throws IOException,ClassCastException{
         //方法体逻辑略
    }
 }
 

1.3 自定义异常

       其实在JDK中提供了很多的异常类,可以满足项目中的使用,但是如果从业务的严谨性来说,假设有一个Person类,类中有age年龄属性,如果创建Person实例时,在对一个人的对象的年龄属性进行赋值时,如果赋值-1岁,或者300岁,这是与实际的业务场景不吻合的,也就会导致程序的健壮性不好。所以需要使用自定义异常满足项目的实际业务要求。

语法结构:

 public  class [自定义异常类型] extends Exception{
    //1.自定义异常类需要继承异常超类
    //2.生成自定义异常类的构造器,需要去选择调用超类中的构造器内容
 }

案例演示:

 package cn.tedu.execption_two;
 /**
  * 自定义一个年龄不合乎实际业务的异常类
  * @author cjn
  *
  */
 //要继承Exception异常超类
 public class AgeCustomExecption extends Exception{
  //要添加序列版本号
     private static final long serialVersionUID = 1L;
 
  //下面的利用工具自动生成:Generate Constructors from SuperClass
     public AgeCustomExecption() {
         super();
    }
 
     public AgeCustomExecption(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
         super(message, cause, enableSuppression, writableStackTrace);
    }
 
     public AgeCustomExecption(String message, Throwable cause) {
         super(message, cause);
    }
 
     public AgeCustomExecption(String message) {
         super(message);
    }
 
     public AgeCustomExecption(Throwable cause) {
         super(cause);
    }
 
     
 }

 package cn.tedu.execption_two;
 /**
  * 自定义Person类
  * @author cjn
  *
  */
 public class Person {
     private String name;
     private int age;
     private String gender;
     
     //定义无参构造,减少报错
     public Person() {}
     
     public Person(String name, int age, String gender) {
         super();
         this.name = name;
         this.age = age;
         this.gender = gender;
    }
 
     public String getName() {
         return name;
    }
 
     public void setName(String name) {
         this.name = name;
    }
 
     public int getAge() {
         return age;
    }
 
  //对年龄出现不合理的情况进行抛出异常处理
     public void setAge(int age) throws AgeCustomExecption{
         //不合理的年龄赋值情况
         if (age<0 || age>200) {
             //抛出自定义异常,关键字throw 创建自定义异常对象
             throw new AgeCustomExecption("年龄赋值不合法!!!");
        }
         this.age = age;
    }
 
     public String getGender() {
         return gender;
    }
 
     public void setGender(String gender) {
         this.gender = gender;
    }
 
     @Override
     public int hashCode() {
         final int prime = 31;
         int result = 1;
         result = prime * result + age;
         result = prime * result + ((gender == null) ? 0 : gender.hashCode());
         result = prime * result + ((name == null) ? 0 : name.hashCode());
         return result;
    }
 
     @Override
     public boolean equals(Object obj) {
         if (this == obj)
             return true;
         if (obj == null)
             return false;
         if (getClass() != obj.getClass())
             return false;
         Person other = (Person) obj;
         if (age != other.age)
             return false;
         if (gender == null) {
             if (other.gender != null)
                 return false;
        } else if (!gender.equals(other.gender))
             return false;
         if (name == null) {
             if (other.name != null)
                 return false;
        } else if (!name.equals(other.name))
             return false;
         return true;
    }
 
     @Override
     public String toString() {
         return "Person [name=" + name + ", age=" + age + ", gender=" + gender + "]";
    }
 
     
     
 }

 package cn.tedu.execption_two;
 /**
  * 自定义异常类的测试案例
  * @author cjn
  *
  */
 public class Test {
 
     public static void main(String[] args) {
         Person p1 = new Person();
         p1.setName("张三");
         try {
             p1.setAge(-1);
        } catch (AgeCustomExecption e) {
             e.printStackTrace();
        } catch (Exception e) {
             e.printStackTrace();
        }
         p1.setGender("男");
         System.out.println(p1);
         
         Person p2 = new Person("李四", 18, "男");
         System.out.println(p2);
 
    }
 
 }

 

 

posted @ 2021-06-24 23:48  Coder_Cui  阅读(262)  评论(0编辑  收藏  举报