字符流
字符流
字符流
- 字符流是以字符(
char
)为单位读写数据的,一次处理一个unicode
; java.io.Reader
是所有字符输入流的父类;java.io.Writer
是所有字符输出流的父类;- 字符流仅适合读写文本数据。
字符输入流
Reader
的常用方法:int read()
:读取一个字符,返回int
值,“低16位”有效;int read(char[] chs)
:从该流中读取一个字符数组的length
个字符并存入该数组,返回值位实际读取到的字符量。
Writer
的常用方法:- 文件输出流继承自
java.io.OutputStream
; - 文件输出流提供了父类中要求的写出字节的相关方法;
void write(int d)
:写出一个字节。写出的是给定int
值d
对应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)
- 基于参数
OutputStream
与Writer
的构造方法提供了一个可以传入boolean
值参数,该参数用于表示PrintWriter
是否具有自动行刷新。
PrintWriter
PrintWriter
提供了丰富的重载print
与println
方法。- 常用方法:
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
块代码被执行和当前线程的所属的ThreadGroup
的uncaughtException
方法被调用后,遇到异常的当前线程被终止。
异常的分类
Throwable, Error和Exception
- Java异常结构中定义有
Throwable
类,Exception
和Error
是其派生的两个子类。其中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()); } }