Day15
课程内容
1、异常
2、异常体系结构
3、jvm默认处理异常机制
4、try..catch
5、编译时异常和运行时异常
6、声明异常抛异常throws和throw关键字
7、自定义异常
一、LinkedHashMap
1、HashMap的一个子类
2、特点:能够保证存入集合中的元素和取出集合中元素顺序的一致性
import java.util.HashMap;
public class Demo_1 {
public static void main(String[] args) {
HashMap<Integer,String> lhm = new HashMap<>();
lhm.put(485, "数字485");
lhm.put(553, "数字553");
lhm.put(5543, "数字5543");
lhm.put(1234, "数字1234");
lhm.put(977, "数字977");
System.out.println(lhm);
}
}
二、Collections
1、Collections是集合的一个工具类,里面提供了很多操作集合的方法。
2、常用方法
binarySearch(List<? extends Comparable<? super T>> list, T key)
在一个升序顺序的集合中,通过二分查找寻找key对应的索引
frequency(Collection<?> c, Object o) 返回集合c中元素o的个数
max,min获取集合的最大值和最小值
replaceAll(List<T> list, T oldVal, T newVal) 将list集合中的oldval元素都替换为newval
reverse(List<?> list) 将list集合中的元素进行反转
shuffle(List<?> list) 将list集合中的元素进行随机的置换
swap(List<?> list, int i, int j) 交换List中指定索引位置上的两个元素
synchronizedXXX:将一个线程不安全的集合传入方法,返回一个线程安全的集合
unmodifiableXXX:讲一个可以进行可修改的集合传入方法,返回一个不可修改的只读的集合
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class Demo_2 {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(5);
list.add(4);
list.add(2);
list.add(3);
list.add(6);
list.add(6);
list.add(6);
Collections.sort(list);
System.out.println(list);
int binarySearch = Collections.binarySearch(list, 5);
System.out.println(binarySearch);
int frequency = Collections.frequency(list, 4);
System.out.println(frequency);
Collections.replaceAll(list, 6, 10);
System.out.println(list);
Collections.reverse(list);
System.out.println(list);
Collections.swap(list, 0, list.size()-1);
System.out.println(list);
list.set(3, 888);
System.out.println(list);
List<Integer> newList = Collections.unmodifiableList(list);
System.out.println(newList);
newList.set(0, 9999);
System.out.println(newList);
}
}
三、异常
1、异常的概述
2、认识什么异常?
3、java程序中,如果出现了和现实生活中不符合的情况的时候,不想让程序继续执行了。就是将这个出现该异常情况的问题进行一个描述,并且将出现异常的位置,出现异常原因,不正常情况的描述等信息封装到一个对象中,这个对象就是异常对象。
4、在程序中出现了异常,但是还想让程序继续执行,就可以对异常进行处理和捕获,不影响程序的正常执行。
异常的体系
1、Throwable,Throwable 类是 Java 语言中所有错误或异常的超类,是异常体系的顶层父类,其他异常或者错误,都是Throwable的子类类型
2、Error,Error 是 Throwable 的子类,用于描述那些不能进行捕获或者处理的错误情况。属于非常严重的错误。StackOverflowError
3、Exception:异常,是 Throwable 的子类,用于描述那些能进行捕获或者处理的错误情况,属于不太严重的错误。
4、RuntimeException,运行时异常,是Exception的子类,在程序的运行过程中出现的异常。在编译阶段不做检查的一个异常。
5、体系图
Throwable
Error
Exception
RuntimeException
public class Demo_3 {
public static void main(String[] args) {
System.out.println(1 / 0);
test_1();
}
public static void test_1() {
test_2();
}
public static void test_2() {
test_1();
}
}
Jvm默认处理异常的机制
1、在java程序运行的过程中,如果出现了不正常的情况,就会将出现的不正常的情况进行封装,封装到一个异常对象中。如果不能对这个异常进行处理就会由jvm虚拟机进行抛出,将异常信息通过错误流打印到控制台上。
2、将异常对象抛给调用该方法的方法上
3、某个方法接受底层抛上来的异常,没有办法处理,就会继续向上抛,最终抛给主方法,主方法也处理不了,就抛给jvm虚拟机,jvm虚拟机也处理不了,就将错误信息打印到控制台上,结束程序
public class Demo_3 {
public static void main(String[] args) {
test_1();
}
public static void test_1() {
test_2();
}
public static void test_2() {
test_3();
}
public static void test_3() {
System.out.println(1 / 0);
}
}
手动处理异常的方式
1、两大类处理异常的方式
异常的声明:针对的是编译时异常,异常的声明只是能够解决编译时异常在编译阶段通不过的问题,并不能捕获或者处理异常
异常的捕获:出现了异常之后,还想让程序能够正常的执行,可以通过一种代码格式完成对异常的捕获和处理,让程序能够继续执行
2、异常的捕获的代码格式:
try...catch
try...catch...finally
try...finally(并不能捕获异常)
try…catch语句
1、格式:
try{
可能发生异常的代码
}catch(可能发生异常的类型 异常对象名){
发生了声明的异常类型后的处理方式;
}
2、说明
try:将可能出现异常的代码,放到try语句块中,完成对异常的检测
catch:捕获try中可能出现的异常,如果在try中出现了catch中声明的异常就执行catch块中的内容
3、运行机制
(1)执行try中的语句块
(2)如果在try中代码没有发生异常,那么就不执行catch中的内容
(3)如果在try中代码发生了异常,会和catch中声明的异常进行匹配,如果catch块上声明的异常和try中的匹配到了,就说明catch捕获到了异常就执行catch中的语句块(注意:在try中发生异常位置的代码后面的内容是都不能执行了,只要try中发生了异常,如果catch能够捕获的到,就直接跳转到catch块中)
(4)如果try中发生了异常,但是catch中没有捕获到该异常,就会按照jvm默认处理异常的方式进行处理
import java.util.Scanner;
public class Demo_4 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int[] arr = new int[3];
try {
System.out.println("请输入一个数字");
int num = scanner.nextInt();
System.out.println(1 / num);
System.out.println("请输入一个索引");
System.out.println(arr[scanner.nextInt()]);
System.out.println("try 中的语句");
} catch (ArithmeticException e) {
System.out.println("发生了算数异常");
}
System.out.println("我能不能执行呢");
}
}
try…catch…catch…
1、在一段代码中,可能出现多个异常,虽然每次只出现一个异常,但是每次出现的异常时不确定的,所以就要准备多种异常的处理机制
2、格式:
try{
可能出现异常的代码
}catch(可能出现的异常类型1 异常对象名1){
对出现异常类型1的处理方式
}catch(可能出现的异常类型2 异常对象名2){
对出现异常类型2的处理方式
}catch(可能出现的异常类型3 异常对象名3){
对出现异常类型3的处理方式
}
3、执行流程
(1)执行try中的语句块
(2)如果在try中代码没有发生异常,那么就不执行catch中的内容
(3)如果有异常那么就会在发生异常的位置直接跳转到catch块中,和catch中声明的异常类型从上到下进行一一匹配,如果匹配到了声明的异常就执行对应catch块中的内容,try...catch语句就结束了。
4、注意
(1)如果在catch的异常类型声明中,出现了子父类的异常类型,那么子类类型的catch块,必须放在父类类型的上面的
因为,catch块的匹配是从上到下的,如果父类的catch块在上面,子类类型的catch块就成了无法到达的代码
(2)想要对多个异常类型采取相同的处理方式,可以对异常类型进行或运算使用|表示
catch( 异常类型1|异常类型2|异常类型3|异常类型n){
对多种异常类型采用的同种处理方式。
}
import java.util.Scanner;
public class Demo_5 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int[] arr = new int[3];
try {
System.out.println("请输入一个数字");
int num = scanner.nextInt();
System.out.println(1 / num);
System.out.println("请输入一个索引");
System.out.println(arr[scanner.nextInt()]);
arr = null;
System.out.println(arr[0]);
System.out.println("try 中的语句");
}catch(ArithmeticException | ArrayIndexOutOfBoundsException | NullPointerException e) {
System.out.println("对算数异常,数组下标越界异常,空指针异常,采取相同的处理方式");
} catch (Exception e) {
System.out.println("发生了异常");
}
System.out.println("我能不能执行呢");
}
}
try…catch…finally
1、格式:
try{
可能发生异常的代码
} catch(可能发生异常的类型 异常对象名){
发生了声明的异常类型后的处理方式;
} finally{
一定要执行的代码;
}
2、finally:一定要执行的内容
(1)如果把代码代码放到try中,可能在要执行代码的前面发生了异常,一旦发生了异常,发生异常位置后的代码都执行不到了,如果把要执行的代码放到catch中,catch块的执行特点是,捕获到异常才执行,如果在try没有捕获到异常,catch块中的内容就不会执行。
如果这段代码放到try..catch后,如果try中有未捕获的异常,还是无法执行必须要执行的代码
(2)finally:也是一个代码块,在这个代码块中的内容,必须要执行的,无论是try中有没有异常还是try中有没有未捕获的异常,finally中的内容都要执行,即使在try中有return语句,finally仍然还有执行)
(3)作用:关闭资源
import com.sun.corba.se.impl.orb.ParserTable.TestAcceptor1;
public class Demo_6 {
public static void main(String[] args) {
int[] arr = new int[3];
int test = test();
System.out.println(test);
}
public static int test() {
int i = 10;
try {
System.out.println(1 / 1);
System.out.println("前面发生异常,我就不能执行了");
i = 30;
return i;
} catch (ArithmeticException e) {
System.out.println("try中发生了异常,执行catch中的内容");
} finally {
System.out.println("无论try中有没有异常,finally语句块中的代码都会执行");
i = i + 10;
return i;
}
}
}
try…finally
1、格式
try{
可能会发生异常的代码;
}finally{
一定要执行的代码;
}
2、作用:
(1)无法捕获和处理异常,一旦发生异常,就会采用默认的处理机制进行处理
(2)无论try时候发生了异常,finally中的语句都会执行
如果在try出现的异常知道怎么去处理,就可以使用try..catch..finally语句完成对异常的捕获和处理。
可能将来对于某段代码可能发生异常的,但是不知道怎么去处理这个异常,但是在方法中又不想导致必须要执行的代码不能够正常执行
public class Demo_7 {
public static void main(String[] args) throws ClassNotFoundException {
try {
Class.forName("com.offcn.demos.Demo_1");
} finally {
System.out.println("上面的代码是否发生错误都没有关系");
}
}
}
编译时异常和运行时异常
1、无论编译时异常还是运行时异常,最终都是在运行阶段可能会导致程序的终止。
2、区别:
(1)编译时异常:在编译阶段通不过编译,在编译阶段就会告知我们调用的方法可能会出现的异常。
(2)运行时异常:在编译阶段是可以通过的,只有在运行阶段才能出现的异常情况。
区别:体系的区别
编译时异常,体系是Exception和Exception的子类类型,除了RuntimeException以外全都是编译时异常的类型
运行时异常,体系是RuntimeException和RuntimException的子类类型
处理方式:
编译时异常:两种,一种异常的声明,只是为了解决编译时异常能够在编译阶段通过编译,并不能真正的捕获异常,一种是异常的捕获,能够将该异常进行处理,
运行时异常:异常的捕获。
import java.io.FileInputStream;
import java.io.FileNotFoundException;
public class Demo_8 {
public static void main(String[] args) {
try {
FileInputStream fis = new FileInputStream("aa.txt");
} catch (FileNotFoundException e) {
System.out.println("出现异常了");
}
}
public static void test() throws FileNotFoundException {
FileInputStream fis = new FileInputStream("aa.txt");
}
}
继承体系中的常用方法
1、在异常体系中,所有的方法都定义在了他的父类类型中,子类都是从父类继承的方法,异常的子类类型基本都没有自己特有的方法
2、构造方法
Throwable() :创建是一个没有任何参数的异常对象
Throwable(String message) 创建一个带有指定信息的异常对象
Throwable(Throwable cause) :创建一个带有异常对象的异常对象
Throwable(String message, Throwable cause) :创建一个带有指定信息和指定异常对象的异常对象
3、常用的成员方法
getCause():获取异常对象中的异常对象
getMessage():获取异常对象中封装的消息
toString():返回异常对象的信息
printStackTrace() :打印异常的栈轨迹
public class Demo_9 {
public static void main(String[] args) {
Throwable th1 = new Throwable();
System.out.println(th1);
Throwable th2 = new Throwable("不能除以0");
System.out.println(th2);
System.out.println(th2.getCause());
Throwable th3 = new Throwable(th2);
System.out.println(th3);
Throwable th4 = new Throwable("除0会发生错误的", th2);
System.out.println(th4.getMessage());
System.out.println(th4);
Throwable cause = th4.getCause();
System.out.println(cause);
System.out.println(th4.toString());
System.out.println("-------------------------------------");
try {
test_1();
} catch (ArithmeticException e) {
e.printStackTrace();
}
}
public static void test_1() {
test_2();
}
public static void test_2() {
test_3();
}
public static void test_3() {
System.out.println(1 / 0);
}
}
throw关键字
1、如果在程序运行的过程中,出现了不正常的情况,不想让程序继续执行了,就可以使用throw关键字将一个异常对象进行抛出。
一旦抛出异常,如果抛出的异常没有进行处理,程序就终止了。
2、作用:
如果程序中达到某种情况,可以使用throw完成对异常对象的抛出,实现程序的结束或者跳转
3、说明:
如果抛出的是一个运行时异常,在编译阶段相当于没有 异常,可以不处理
如果抛出的是一个编译时异常,在编译阶段要进行处理,才能编译成功
public class Person {
private String name;
private int age;
public Person() {
super();
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
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 <= 120) {
this.age = age;
}else {
throw new Exception("你输入的年龄不合法");
}
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
}
throws关键字
1、throws声明一个异常
2、主要的使用场景就是对编译时异常进行声明
3、在某个方法中,如果出现了编译时异常,没有给出处理异常的方式,没有捕获异常,就说明这个方法是一个有问题的方法,为了让调用者在调用的时候能能够意识到这个问题,并进行处理,所以就在方法的声明上,去声明这个异常。让编译时异常在编译阶段能够正常通过。
4、声明方式
在方法名字参数列表的后面加上throws关键字,跟上要声明的异常类型即可,要声明的异常类型可以是多个
5、注意
throws关键字主要就是能够让编译时异常通过编译,但是不会捕获或者处理这个异常,异常一旦发生,还是执行jvm默认处理机制
对于运行时异常而言,使用throws关键字进行声明,没有任何的意义。
throws在方法上进行异常声明的时候,调用者方法如果没有对该异常进行处理,调用者方法也必须进行异常的声明
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class Demo_11 {
public static void main(String[] args) throws FileNotFoundException {
System.out.println(1 / 0);
test();
}
public static void test() throws FileNotFoundException {
FileInputStream fis = new FileInputStream("a.txt");
}
}
throw和throws区别
1、throw对异常对象的抛出,throws是对异常对象的声明
2、throw是对异常的抛出,可以让程序进行结束或者跳转,throws就是对异常进行声明,解决编译时异常在编译阶段通不过的问题
throw既可以抛出运行时异常,也可以抛出编译时异常
throws只能声明的是编译时异常声明运行时异常没有意义
3、throw后面只能跟一个异常,也就是只能抛出一个异常对象
throws后面可以跟多个异常,可以声明多个异常类型
自定义异常
1、jdk中提供了很多的异常类型,其中大部分都没有自己特有的方法
2、定义很多的异常,没有特有方法,没有特有属性 原因:
(1)有了很多的异常类型,将来在程序出现异常情况的时候,可以根据异常类型的名称很容易就判断出发生异常的原因
(2)有了很多的异常类型,将来可以根据程序出现的不同的异常情况,可以根据不同的异常类型采取不同的措施
3、在自己的业务模块开发过程中,出现了不正常的情况,但是在jdk中没有描述该情况的这种异常类型
4、自定义异常的步骤
(1)定义一个类,以Execption结尾,起上一个描述异常对象名字(通俗易懂)
(2)定义的这个类,继承一个Exception或者RuntimeExecption类
如果这个自定义异常类继承的是RuntimeExecption,那么该自定义异常就是一个运行时异常
如果这个自定义异常类继承的是Execption,那么该自定义异常就是一个编译时异常
public class IllegalAgeException extends Exception {
public IllegalAgeException() {
super();
}
public IllegalAgeException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
public IllegalAgeException(String message, Throwable cause) {
super(message, cause);
}
public IllegalAgeException(String message) {
super(message);
}
public IllegalAgeException(Throwable cause) {
super(cause);
}
}
public class Person {
private String name;
private int age;
public Person() {
super();
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
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 <= 120) {
this.age = age;
}else {
throw new IllegalAgeException("你输入的年龄不合法");
}
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
}
public class Demo_12 {
public static void main(String[] args) throws IllegalAgeException {
Person person = new Person();
person.setAge(12313);
}
}
四、File类
1、文件和目录路径名的抽象表示形式。
2、路径:计算用于描述文件或者文件夹的一个字符串
3、路径分类:绝对路径和相对路径
4、绝对路径:从根目录开始的路径就是绝对路径
根目录:windows系统中,就是盘符C: D: E: F:
eg: E:\codedata\eclipse_workspace\Day12\src\com
Linux系统:/ /就是根目录
5、相对路径:相对于某个路径而言的。
中国,湖南省,长沙市,芙蓉区
芙蓉区,相对于长沙市而言
Eclipse中:在Ecipse中工程创建文件的时候,如果要使用相对路径,相对的是Eclipse的工程目录
File类型的构造方法
1、File(String pathname) :把一个字符串路径,封装为一个file类型的对象
2、File(String parent, String child) 将父级路径parent和子级路径封装为一个File对象,最终封装就是父级路径parent和子级路径的拼接后的路径
3、File(File parent, String child) 将父级的File类型对象的路径和子级路径封装成一个file类型的对象,最终封装就是父级File对象封装的路径和和子级路径的拼接后的路径
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
public class Demo_1 {
public static void main(String[] args) {
File f = new File("E:/codedata/eclipse_workspace\\Day12\\src\\com\\offcn\\demos\\Demo_1.java");
File f2 = new File("E:/codedata/eclipse_workspace\\Day12\\src\\com\\offcn\\demos");
System.out.println(f);
File f3 = new File("a");
System.out.println(f3);
System.out.println(f3.getAbsolutePath());
File f4 = new File("E:/codedata/eclipse_workspace\\Day12\\src\\com\\offcn\\demos","Demo_1.java");
System.out.println(f4);
File f5 = new File(f2,"Demo_1.java");
System.out.println(f5);
}
}
File类型的创建方法
1、createNewFile() 将File类型描述的文件抽象路径,创建出一个具体的文件
2、mkdir() 创建此抽象路径名指定的目录
3、mkdirs() 创建此抽象路径名指定的目录,包括所有必需但不存在的父目录。
import java.io.File;
import java.io.IOException;
public class Demo_2 {
public static void main(String[] args) throws IOException {
File f1 = new File("E:/a/a.txt");
boolean createNewFile = f1.createNewFile();
System.out.println(createNewFile);
File f2 = new File("E:/a/b");
boolean mkdir = f2.mkdir();
System.out.println(mkdir);
File f3 = new File("E:/c/b/e/f/a/s/fdsa/df/asdf/s");
boolean mkdirs = f3.mkdirs();
System.out.println(mkdirs);
}
}