【JAVA CORE_API】Day17 转换流、缓冲字符流、异常概念try、catch、finally、throw、throws、异常API、自定义异常

字符流

字符流

字符流

  • 字符流是以字符(char)为单位读写数据的,一次处理一个unicode
  • java.io.Reader是所有字符输入流的父类;
  • java.io.Writer是所有字符输出流的父类;
  • 字符流仅适合读写文本数据。

字符输入流

  • Reader的常用方法:
    • int read():读取一个字符,返回int值,“低16位”有效;
    • int read(char[] chs):从该流中读取一个字符数组的length个字符并存入该数组,返回值位实际读取到的字符量。
  • Writer的常用方法:
    • void write(int c):写出一个字符,写出给定int值,“低16位”表示的字符;
    • void write(char[] chs):将给定字符数组中所有字符写出;
    • void write(String str):将给定的字符串写出;
    • void write(char[] chs, int offset, int len):将给定的字符数组中从offset处开始连续的len个字符写出。
    • 写出字节数据

  • 文件输出流继承自java.io.OutputStream
  • 文件输出流提供了父类中要求的写出字节的相关方法;
    • void write(int d):写出一个字节。写出的是给定intd对应2进制的“低8位”;
    • void write(byte[] data):块写操作,一次性将给定字节数组data中所有字节写出;
    • void write(byte[] data, int offset, int len):块写操作,一次性将给定字节数组data中从下标offset处连续len个字节写出。

转换流

转换流的意义

  • 字符流只能连接在字符流上使用;
  • 节点流通常都是字节流,在流连接中无法直接将字符流连接在字节流上;
  • 转换流在其中起到“转换器”的作用;
    • 用于衔接字符流与字节流;
    • 对于输出而言:其它字符流泄出的数据经过转换流时会转换为字节再交给字节流写出;
    • 对于输入而言:会从字节流中读取字节并转换为字符后再交给其他字符流进行读取处理;
  • 应用中通常不直接操作转换流。就相当于生活中的:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 字符流不能直接连接在字节流上;

  • 而节点流通常都是字节流;

  • 本质原因是字符流读写字符,字节流读写字节,读写单位不同;

    在这里插入图片描述

  • 转换流本身是字符流,他可以连接在字节流上;

  • 转换流就像转换器一样,可以衔接其它字符流与字节流;

    在这里插入图片描述

  • 转换输出流可以将上层字符流写出的文本数据转换为字节在通过其连接的字节流写出;

    在这里插入图片描述

  • 转换输入流可以从字节流读取相应字节并转换位字符再交给上层字符流做进一步处理;
    在这里插入图片描述

转换流

  • InputStreamReader:转换输入流。
    • 使用该流可以设置字符集,并按照指定的字符集从流中按照该编码将字节数据转换为字符并读取;
  • OutputStreamWriter:转换输出流。
    • 使用该流可以设置字符集,并按照指定的字符集将字符转换为对应字节后通过该流写出;

转换输出流构造器

  • InputStreamReader的构造方法允许我们设置字符集:
    • InputStreamReader(InputStream in, Charset cs):基于给定的字节输入流以及字符编码创建转换输入流;
    • InputStreamReader(InputStream in):该构造方法会根据系统默认字符集创建转换输入流(不推荐使用);

写出文本文本数据

 package day17;
 
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.OutputStreamWriter;
 import java.nio.charset.StandardCharsets;
 /**
  * 字符流:java.io.Reader和java.io.Writer
  * 上述两个流是抽象类,是所有字符流的超类,定义了所有字符流都具备的读写字符的操作
  * 字符流都是高级流
  * 转换流:java.io.InputStreamReader和java.io.OutputStreamWriter
  * 转换流是一对常用的字符流的实现类,实际开发中我们不会直接操作转换流,但在流连接中他们非常重要
  *
  * 本案例演示转换流OutputStreamWriter的写出操作----介绍为主
  */
 public class OswDemo {
     public static void main(String[] args) throws IOException {
         FileOutputStream fileOutputStream = new FileOutputStream("osw.txt");
         // 转换流在创建时可以明确字符集,通过它写出的文字都会使用该字符集来转换为字节
         OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream, StandardCharsets.UTF_8);
         // 字符流支持直接写出字符串,转换流会将字符串转换为字节后再通过文件流写出
         outputStreamWriter.write("久未放晴的天空 依旧留着你的笑容");
         outputStreamWriter.write("哭过 却无法掩埋歉疚");
         System.out.println("写出成功");
         outputStreamWriter.close();
     }
 }
 

读取文本数据

 package day17;
 
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStreamReader;
 import java.nio.charset.StandardCharsets;
 /**
  * 演示转换流InputStreamReader的读取操作----介绍为主
  */
 public class IsrDemo {
     public static void main(String[] args) throws IOException {
         FileInputStream fileInputStream = new FileInputStream("osw.txt");
         InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream, StandardCharsets.UTF_8);
         // read() 夫区一个字符,返回值为int类型,这个int类型的“低16位”有效,-1表示读到了文件的末尾
         int d;
         while ((d = inputStreamReader.read()) != -1) {
             System.out.println((char) d);
         }
         inputStreamReader.close();
     }
 }
 

缓冲字符输出流

PrintWriter

  • PrintWriter是具有自动行刷新功能的缓冲字符输出流;
    • 内部总是连接BufferdWriter作为缓冲块写(默认8192长的char数组)文本数据
    • 可以按行写出字符串;
    • 具有自动行刷新功能;

构造器

  • 提供了比较丰富的构造方法:
    • PrintWriter(File file)
    • PrintWriter(String fileName)
    • PrintWriter(OutputStream out)
    • PrintWriter(OutputStream out, boolean autoFlush)
    • PrintWriter(Writer writer)
    • PrintWriter(Writer writer, boolean autoFlush)
  • 基于参数OutputStreamWriter的构造方法提供了一个可以传入boolean值参数,该参数用于表示PrintWriter是否具有自动行刷新。

PrintWriter

  • PrintWriter提供了丰富的重载printprintln方法。
  • 常用方法:
    • void print(int i):打印整数;
    • void print(char c):打印字符;
    • void print(boolean b):打印boolean值;
    • void print(char[] c):打印字符数组;
    • void print(double d):打印double值;
    • void print(float f):打印float值;
    • void print(long l):打印long值;
    • void print(String str):打印字符串;
  • 上述方法都有println方法。

简易记事本v2.0

  • 输入数据:

     package day17;
     
     import java.io.*;
     import java.nio.charset.StandardCharsets;
     import java.util.Scanner;
     
     /**
      * 完成简易记事本升级版:
      * 需求:程序启动后将用户输入的每一行字符串都按行写入到note.txt中,用户输入exit输出
      * 要求:完成四层流连接
      */
     public class NoteTestV2 {
         public static void main(String[] args) throws FileNotFoundException {
             // 创建一个扫描仪
             Scanner scanner = new Scanner(System.in);
             // 四层流连接 --- 创建一个文件输出流对象
             FileOutputStream fileOutputStream = new FileOutputStream("note.txt");
             // 四层流连接 --- 创建一个转换流对象
             OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream, StandardCharsets.UTF_8);
             // 四层流连接 --- 创建一个缓冲流对象
             BufferedWriter bufferedWriter = new BufferedWriter(outputStreamWriter);
             // 四层流连接 --- 创建一个打印流对象
             PrintWriter printWriter = new PrintWriter(bufferedWriter, true);
     
             System.out.println("请输入内容:");
             while (true) {
                 String string = scanner.nextLine();
                 if ("exit".equalsIgnoreCase(string)) {  // 判断用户输入的字符串是否为exit
                     break;
                 } else {
                     printWriter.println(string);
                 }
             }
             System.out.println("记录完成!再见!");
             printWriter.close();
     
         }
     }
     
    
  • 输出数据:

     package day17;
     
     import java.io.*;
     import java.nio.charset.StandardCharsets;
     
     /**
      * 使用缓冲字符输入流BufferedReader按行读取字符串:
      * 1) 内部维护一个8192字节长的char数组,可以块读文本数据保证读取效率;
      * 2) 提供了readLine()方法可以按行读取字符串;
      */
     public class BrDemo {
         public static void main(String[] args) throws IOException {
             FileInputStream fileInputStream = new FileInputStream("note02.txt");
             InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream, StandardCharsets.UTF_8);
             BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
     
             /**
              * readLine()方法读取一行字符串
              * 1) 读到\n换行符,返回一行字符串;
              * 2) 读到空行,则返回空字符串
              * 3) 读到了末尾,则返回null
              */
             String line;
             while ((line = bufferedReader.readLine()) != null) {
                 System.out.println(line);
             }
             bufferedReader.close();
         }
     }
     
    

缓冲字符输入流

BufferedReader

  • BufferedReader是缓冲字符输入流;
    • 内部维护一个char数组作为缓冲区(默认8192字节长)缓存文本数据,以块读形式保证读取效率;
    • 可以按行读取字符串;

构造器

  • BufferedReader(Reader reader):创建默认8192字节长缓冲区的缓冲字符输入流并连接在参数指定的流上;
  • BufferedReader(Reader reader, int sz):创建sz指定长度缓冲区的缓冲字符输入流并连接在参数指定的流上。

按行读取字符串

  • BufferedReader提供了一个可以便于读取一行字符串的方法:
    • String readLine():该方法返回缓冲区中一行字符串,返回的字符串中不包含该换行符。当返回值为null时,表示流读取到了末尾。

异常处理机制

异常处理概述

使用返回值状态标识异常

  • 在Java语言出现以前,传统的异常处理方式多采用返回值来标识处现的异常情况,这种方式虽然为程序员所熟悉,但却有很多坏处;
  • 首先,一个API可以返回任意的返回值,而这些返回值本身并不能解释该返回值是否代表一个异常情况发生了和该异常的具体情况,需要调用API的程序自己判断并解释返回值的含义;
  • 其次,并没有一种机制来保证异常情况一定会得到处理,调用程序可以简单地忽略该返回值,需要调用API的程序员记住去检测返回值并处理异常情况。这种方式还让程序代码变得冗长,尤其是当进行IO操作等容易出现异常情况的处理时,代码的很大部分用于处理异常情况的switch分支,程序代码的可读性变得很差。

异常处理机制

  • 当程序中抛出一个异常后,程序从程序中导致异常的代码处跳出,Java虚拟机检测寻找和try关键字匹配处理该异常的catch块,如果找到,将控制权交到catch块中的代码,然后继续往下执行该程序,try块中发生异常的代码不会被重新执行。如果没有找到处理该异常的catch块,在所有的finally块代码被执行和当前线程的所属的ThreadGroupuncaughtException方法被调用后,遇到异常的当前线程被终止。

异常的分类

Throwable, Error和Exception

  • Java异常结构中定义有Throwable类,ExceptionError是其派生的两个子类。其中Exception表示由于网络故障、文件损坏、设备错误、用户输入非法等情况导致的异常;而Error表示Java运行时环境出现的错误,例如:JVM内存资源耗尽等。
    在这里插入图片描述

try-catch

try-catch

  • try{ ... } 语句指定了一段代码,这段代码就是一次捕获并处理例外的范围;
  • 在执行过程中,该段代码可能会产生并抛出一种或几种类型的异常对象,它后面的catch语句分别对这些异常做相应的处理;
  • 如果没有异常产生,所有的catch代码段都被略过不执行;
  • catch语句块中是对异常进行处理的代码;
  • catch中生命的异常对象(catch(SomeException e))封装了异常事件发生的信息,在catch语句块中可以使用这个对象的一些方法获取这些信息。
  • 语法格式:
     try {
         正常的代码片段(Plan A} catch (XXXException) {try中的代码出现了XXXException异常之后的处理代码(Plan B}
    
  • try-catch示例:
     package day17;
     
     public class TryCatchDemo {
         public static void main(String[] args) {
             try {
                 String string = null;
                 System.out.println(string.length());
             } catch (NullPointerException e) {
                 System.out.println("空指针异常");
             }
         }
     }
     
    
  • 多catch示例:
     package day17;
     
     public class TryCatchDemo {
         public static void main(String[] args) {
             try {
             //  String string = null;
             //  System.out.println(string.length());  // 会走空指针异常
                 String string1 = "abc";
                 System.out.println(string1.charAt(5));  // 会走字符串索引越界异常
             } catch (NullPointerException e) {
                 System.out.println("空指针异常");
             } catch (StringIndexOutOfBoundsException e) {
                 System.out.println("字符串索引越界异常");
             }
         }
     }
     
    
  • 合并catch示例:
     package day17;
     
     public class TryCatchDemo {
         public static void main(String[] args) {
             try {
             //  String string = null;
             //  System.out.println(string.length());  // 会走空指针异常
                 String string1 = "abc";
                 System.out.println(string1.charAt(5));  // 会走字符串索引越界异常
             } catch (NullPointerException | StringIndexOutOfBoundsException e) {
                 System.out.println("空指针异常或字符串索引越界异常");
             }
         }
     }
     
    
  • 全报示例:
     package day17;
     
     public class TryCatchDemo {
         public static void main(String[] args) {
             try{
                 String string = "abc";
                 System.out.println(Integer.parseInt(string));
             } catch(Exception e) {  // 这是所有异常的父类,也叫超类型异常
                 System.out.println("不知道,反正出了个错!");
             }
         }
     }
     
    
  • 注意:
    • try中的代码不出现异常时,catch语句是不执行的;
    • try语句块中某语句发生异常后,剩余代码不会被执行;
    • catch可以定义多个,针对不同的一场有不同的处理方式以分别捕获处理;
    • 当多个异常具有相同的处理方式时,可以合并到一个catch中处理;
    • 捕获超类型(Exception e)异常,那么它的所有子类型异常都可以被处理;
    • 如果catch的一场存在继承关系,那么子类异常在上,父异常在下。

finally

finally块

  • finally语句为异常处理提供一个统一的出口,使得在控制流程转到其他程序部分以前,能够对程序的状态同统一地管理;
  • 无论try所制定的程序块中是否抛出异常,finally所制定的代码都要被执行;
  • 通常在finally语句中可以进行资源的释放工具,如果关闭打开文件、删除临时文件等;
     package day17;
     
     public class FinallyDemo {
         public static void main(String[] args) {
             System.out.println("程序01开始了...");
     
             // 没有异常也会走finally
             try{
                 String string = "abc";
                 System.out.println(string.length());
             } catch (Exception exception) {
                 System.out.println("不知道,反正出了个错!");
             } finally {
                 System.out.println("程序01里面的finally执行了!");
             }
             System.out.println("程序01结束了...");
     
             System.out.println("----------------------------");
     
             // 有异常也会走finally
             try{
                 String string = null;
                 System.out.println(string.length());
             } catch (Exception exception) {
                 System.out.println("不知道,反正出了个错!");
             } finally {
                 System.out.println("程序02里面的finally执行了!");
             }
             System.out.println("程序02结束了...");
     
             System.out.println("---------------------------------");
     
             // 哪怕return也走
             try{
                 String string = null;
                 System.out.println(string.length());
                 return;
             } catch (Exception exception) {
                 System.out.println("不知道,反正出了个错!");
             } finally {
                 System.out.println("程序03里面的finally执行了!");
             }
             System.out.println("程序03结束了...");
         }
     }
     
    

异常处理在IO中的应用

 package day17;
 
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
 
 /**
  * 异常处理机制在IO中的应用
  */
 public class FinallyIODemo {
     public static void main(String[] args) {
         FileOutputStream fileOutputStream = null;
         // ctrl+alt+t 快速生成 try catch
         try {
             fileOutputStream = new FileOutputStream("fos.dat");
             fileOutputStream.write(1);
         } catch (IOException e) {
             System.out.println("出现异常了!");;
         } finally {
             try {
                 if (fileOutputStream != null) {
                     fileOutputStream.close();
                     System.out.println("完成!");
                 }
             } catch (IOException e) {
                 System.out.println("关闭资源出现异常了!");;
             }
         }
 
     }
 }
 

异常处理机制

自动关闭特性

自动关闭特性

  • JDK7之后,Java推出了自动关闭特性;
  • 旨在更优雅的在异常处理机制中关闭,如:流这样的操作。
     package day17;
     
     import java.io.FileNotFoundException;
     import java.io.FileOutputStream;
     import java.io.IOException;
     
     /**
      * JDK7之后,Java推出了一个新特性,自动关闭特性.
      * 可以使我们在异常处理机制中更优雅的关闭如“流”这样的资源
      */
     public class AutoCloseableDemo {
         public static void main(String[] args) {
             /**
              * 只要实现了AutoCloseable接口的类,才可以在try()中定义
              * 所有流都实现了该接口,意味着可以将流定义并初始化在try()中,会自动进行流的关闭。
              */
             try (FileOutputStream fileOutputStream = new FileOutputStream("fos.dat")) {
                 fileOutputStream.write(1);
             } catch (IOException e) {
                 System.out.println("出现异常了!");;
             }  // 无需写finally了
         }
     }
     
    

异常的抛出

throw关键字

  • 当程序发生错误而无法处理的时候后,会抛出对应的异常对象,除此之外,在某些时刻,我们可能会想要自行抛出异常,例如在异常处理结束后,再将异常抛出,让下一层异常处理块来捕捉,若想要自行抛出异常,我们可以使用throw关键字,并声称指定的异常对象后抛出。
  • 例如:
    throw new ArithmeticException();
  • 示例代码:
    • Person类:
     package day17;
     
     import java.util.Objects;
     
     public class Person {
         private String name;
         private int age;
         private String gender;
         private String address;
     
         public Person() {
         }
     
         public Person(String name, int age, String gender, String address) {
             this.name = name;
             this.age = age;
             this.gender = gender;
             this.address = address;
         }
     
         public String getName() {
             return name;
         }
     
         public void setName(String name) {
             this.name = name;
         }
     
         public int getAge() {
             return age;
         }
     
         public void setAge(int age) {
             if (age < 0 || age > 200) {
                 throw new RuntimeException("年龄不合法,正确的年龄应在0到200之间!");
             }
             this.age = age;
         }
     
         public String getGender() {
             return gender;
         }
     
         public void setGender(String gender) {
             this.gender = gender;
         }
     
         public String getAddress() {
             return address;
         }
     
         public void setAddress(String address) {
             this.address = address;
         }
     
         @Override
         public boolean equals(Object o) {
             if (this == o) return true;
             if (o == null || getClass() != o.getClass()) return false;
             Person person = (Person) o;
             return age == person.age && Objects.equals(name, person.name) && Objects.equals(gender, person.gender) && Objects.equals(address, person.address);
         }
     
         @Override
         public int hashCode() {
             return Objects.hash(name, age, gender, address);
         }
     
         @Override
         public String toString() {
             return "Person{" +
                     "name='" + name + '\'' +
                     ", age=" + age +
                     ", gender='" + gender + '\'' +
                     ", address='" + address + '\'' +
                     '}';
         }
     
     }
     
    
    • 测试类:
     package day17;
     
     /**
      * throw关键字,用于将一个异常抛出。
      * 通常下列情况下会将一个异常抛出方法外:
      * 1)当前代码片段出现了异常,但是该异常不应该在此处被处理(不是我们的责任);
      * 2)程序可以运行,但运行结果不符合实际业务需求(本案例演示)
      */
     public class ThrowDemo {
         public static void main(String[] args) {
             Person person = new Person("张禹垚", 18, "男", "南京");
             person.setAge(2000);
             System.out.println("此人年龄:" + person.getAge());
         }
     }
     
    
    如果这时我们输入非法的数据,会出现:
    在这里插入图片描述

throws关键字

  • 程序中会生命许多方法(Method),这些方法中可能会因某些错误而引发异常,但如果我们不希望直接在这个方法中处理这些异常,而希望调用这个它的方法来统一处理,这时候我们可以使用“throws”关键字来声明这个方法将会抛出异常。
  • 除了RunTimeException以外,当主动使用throw抛出异常时,编译器要求必须在方法中使用throws来声明异常的抛出,以便通知调用者处理。
     package day17;
     
     import java.util.Objects;
     
     public class Person {
         private String name;
         private int age;
         private String gender;
         private String address;
     
         public Person() {
         }
     
         public Person(String name, int age, String gender, String address) {
             this.name = name;
             this.age = age;
             this.gender = gender;
             this.address = address;
         }
     
         public String getName() {
             return name;
         }
     
         public void setName(String name) {
             this.name = name;
         }
     
         public int getAge() {
             return age;
         }
     
         public void setAge(int age) throws Exception{
             if (age < 0 || age > 200) {
                 throw new Exception("年龄不合法,正确的年龄应在0到200之间!");
             }
             this.age = age;
         }
     
         public String getGender() {
             return gender;
         }
     
         public void setGender(String gender) {
             this.gender = gender;
         }
     
         public String getAddress() {
             return address;
         }
     
         public void setAddress(String address) {
             this.address = address;
         }
     
         @Override
         public boolean equals(Object o) {
             if (this == o) return true;
             if (o == null || getClass() != o.getClass()) return false;
             Person person = (Person) o;
             return age == person.age && Objects.equals(name, person.name) && Objects.equals(gender, person.gender) && Objects.equals(address, person.address);
         }
     
         @Override
         public int hashCode() {
             return Objects.hash(name, age, gender, address);
         }
     
         @Override
         public String toString() {
             return "Person{" +
                     "name='" + name + '\'' +
                     ", age=" + age +
                     ", gender='" + gender + '\'' +
                     ", address='" + address + '\'' +
                     '}';
         }
     
     }
     
    
  • 当我们调用一个含有throws声明异常抛出的方法时,编译器要求我们必须处理该异常,方法如下:
    • 使用try...catch...处理该异常;
    • 在当前方法上继续使用throws对该异常抛出;
    • 注意:具体选择哪种方式,取决于责任问题;
    • 记住:永远不要再main方法上写throws,否则直接杀死主方法。

重写方法时的throws

  • 如果使用继承时,在父类的某个方法上宣告了throws某些异常,而在子类里重新定义该方法时,我们可以:
    • 不处理异常(重新定义时不设定throws);
    • 可仅throws父类中声明的部分异常;
    • throws父类方法中抛出异常的子类异常;
      但不可以:
    • throws出额外的异常;
    • throws父类方法中抛出异常的父类异常。
     package day17;
     
     import java.awt.*;
     import java.io.FileNotFoundException;
     import java.io.IOException;
     import java.sql.SQLException;
     
     /**
      * 子类重写父类含有throws声明异常抛出的方法时,对throws的重写规则
      */
     public class ThrowsDemo {
         public void doSome() throws IOException, AWTException {
             
         }
     }
     
     class SubClass extends ThrowsDemo {
      // public void doSome() throws IOException {}  // 允许仅抛出部分异常
      // public void doSome() throws IOException, AWTException {}  // 允许全部抛出
      // public void doSome() {}  // 允许不抛出异常
      // public void doSome() throws FileNotFoundException {} // 允许抛出异常类型小于父类的方法
         
      // public void doSome() throws SQLException {}  // 不允许抛出额外异常(父类中没有继承关系的异常)
      // public void doSome() throws Exception{}  // 不允许抛出大于父类方法的异常   
         
     }
    

Java异常常见API

检查异常与非检查异常

  • Java异常可以分为可检测异常与非检测异常:
    • 可检测异常:可检测异常经编译器验证,对于声明抛出异常的任何方法,编译器将强制执行处理或声明规则,不捕捉这个异常,编译器就通不过,不允许编译;
    • 非检测异常:非检测异常不遵循处理或声明规则。在产生此类异常时,不一定非要采取任何适当操作,编译器不会检查是否已经解决了这个异常;
  • RuntimeException类属于非检测异常,因为普通JVM操作引起的运行时异常随时可能发生,此类异常一般是由特定操作引发。但这些操作在Java应用程序中会频繁出现。因此他们不受编译器检查预处理或声明规则的限制;

常见RuntimeException

  • IllegalArgumentException:抛出的异常表明像方法传递了一个不合法或不正确的参数;
  • NullPointerException:当应用程序试图在需要对象的地方使用null时,抛出该异常;
  • ArrayIndexOutOfBoundsException:当时用的数组下标超出数组允许范围时,抛出该异常;
  • ClassCastException:当试图将对象强制转换为不是实例的子类时,抛出该异常;
  • NumberFormatException:当应用程序试图将字符串转换成一种数值类型,但该字符串不能转换为适当格式时,抛出该异常。

printStackTrace

  • Throwable中定义了一个方法可以输出错误信息,用来跟踪异常事件发生时执行堆栈的内容。该方法定义为:
    • void printStackTrace()
       try {
         ...
       } catch (Exception e) {
         e.printStackTrace();  // 输出执行堆栈信息
       } 
      

getMessage

  • Throwable中定义了一个方法可以得到有关异常事件的信息。该方法定义为:
    • String getMessage()
      try {
        ...
      } catch (Exception e) {
        System.out.println(e.getMessage);
      } 
      
     package day17;
     
     /**
      * throw关键字,用于将一个异常抛出。
      * 通常下列情况下会将一个异常抛出方法外:
      * 1)当前代码片段出现了异常,但是该异常不应该在此处被处理(不是我们的责任);
      * 2)程序可以运行,但运行结果不符合实际业务需求(本案例演示)
      */
     public class ThrowDemo {
         public static void main(String[] args) {
             Person person = new Person("张禹垚", 21, "男", "黑龙江");
             try {
                 person.setAge(2000);
             } catch (Exception e) {
                 System.out.println(e.getMessage());
             }
             System.out.println("此人年龄:" + person.getAge());
         }
     }
     
    

自定义Exception

自定义异常的意义

  • Java异常机制可以保证程序更安全和更健壮。虽然Java类库已经提供很多可以直接处理异常的类,但是有时候为了更加精准地捕获和处理异常以呈现更好的用户体验,需要开发者自定义异常。
  • 自定义变量要完成下列操作:
    • 类名要做到见名知意;
    • 必须继承自Exception(直接或间接);
    • 提供从父类异常定义的所有构造器。
     package day17;
     
     /**
      * 非法年龄异常
      * 通常在项目中需要描述一个语法正确,但是不符合业务需求的需求时,可以自定义异常
      * 自定义异常应当满足如下要求:
      * 1)类名应当见名知意;
      * 2)自定义异常的类一定要继承自Exception类或Runtime类;
      * 3)要添加异常的所有构造器
      */
     public class IllegalAgeException extends Exception {
         public IllegalAgeException() {
         }
     
         public IllegalAgeException(String message) {
             super(message);
         }
     
         public IllegalAgeException(String message, Throwable cause) {
             super(message, cause);
         }
     
         public IllegalAgeException(Throwable cause) {
             super(cause);
         }
     
         public IllegalAgeException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
             super(message, cause, enableSuppression, writableStackTrace);
         }
     }
     
    
     package day17;
     
     import java.util.Objects;
     
     public class Person {
         private String name;
         private int age;
         private String gender;
         private String address;
     
         public Person() {
         }
     
         public Person(String name, int age, String gender, String address) {
             this.name = name;
             this.age = age;
             this.gender = gender;
             this.address = address;
         }
     
         public String getName() {
             return name;
         }
     
         public void setName(String name) {
             this.name = name;
         }
     
         public int getAge() {
             return age;
         }
     
         public void setAge(int age) throws IllegalAgeException{
             if (age < 0 || age > 200) {
                 throw new IllegalAgeException("年龄不合法,正确的年龄应在0到200之间!");
             }
             this.age = age;
         }
     
         public String getGender() {
             return gender;
         }
     
         public void setGender(String gender) {
             this.gender = gender;
         }
     
         public String getAddress() {
             return address;
         }
     
         public void setAddress(String address) {
             this.address = address;
         }
     
         @Override
         public boolean equals(Object o) {
             if (this == o) return true;
             if (o == null || getClass() != o.getClass()) return false;
             Person person = (Person) o;
             return age == person.age && Objects.equals(name, person.name) && Objects.equals(gender, person.gender) && Objects.equals(address, person.address);
         }
     
         @Override
         public int hashCode() {
             return Objects.hash(name, age, gender, address);
         }
     
         @Override
         public String toString() {
             return "Person{" +
                     "name='" + name + '\'' +
                     ", age=" + age +
                     ", gender='" + gender + '\'' +
                     ", address='" + address + '\'' +
                     '}';
         }
     
     }
     
    
     package day17;
     
     /**
      * throw关键字,用于将一个异常抛出。
      * 通常下列情况下会将一个异常抛出方法外:
      * 1)当前代码片段出现了异常,但是该异常不应该在此处被处理(不是我们的责任);
      * 2)程序可以运行,但运行结果不符合实际业务需求(本案例演示)
      */
     public class ThrowDemo {
         public static void main(String[] args) {
             Person person = new Person("张禹垚", 21, "男", "黑龙江");
             try {
                 person.setAge(2000);
             } catch (IllegalAgeException e) {
                 System.out.println(e.getMessage());
             }
             System.out.println("此人年龄:" + person.getAge());
         }
     }
     
    
  • 17
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值