接口和异常

接口

接口,是Java语言中一种引用类型,是方法的集合。接口的内部主要就是封装了方法,包含抽象方法(JDK 7及之前),默认方法和静态方法(JDK 8),私有方法 (JDK 9)。前端

接口的定义

接口定义:java

它与定义类方式类似,可是使用 interface 关键字。它也会被编译成.class文件,但必定要明确它并非类,而是另一种引用数据类型。程序员

引用类型:数组、类、接口数据库

接口语法:编程

1  public interface 接口名称 {
2      // 常量
3      // 抽象方法
4      // 默认方法 
5      // 静态方法
6      // 私有方法 
7  }

常量

接口当中也能够定义“成员变量”,可是必须使用public static final三个关键字进行修饰。从效果上看,这其实就是接口的【常量】数组

语法编程语言

1 public static final 数据类型 常量名称 = 数据值;

备注:一旦使用final关键字进行修饰,说明不可改变ide

注意事项:ui

1. 接口当中的常量,能够省略public static final,注意:不写也照样是这样。spa

2. 接口当中的常量,必须进行赋值;不能不赋值。

3. 接口中常量的名称,使用彻底大写的字母,用下划线进行分隔。(推荐命名规则)

抽象方法

抽象方法:使用 abstract 关键字修饰,能够省略,没有方法体。该方法供子类实现使用。

语法:

1 public interface InterFaceName {     
2     public abstract void method(); 
3 }

默认方法

默认方法:使用 default 修饰,不可省略,供子类调用或者子类重写。

语法:

1 public interface InterFaceName {     
2     public default void method() {         
3         // 执行语句     
4     }
5 }

备注:接口当中的默认方法,能够解决接口升级的问题。及能够后期进行重写升级。

静态方法

静态方法:使用 static 修饰,供接口直接调用。

1  public interface InterFaceName {     
2     public static void method2() {         
3         // 执行语句         
4     }
5  }

私有方法

普通私有方法

普通私有方法:解决多个默认方法之间重复代码问题。

格式

1 private 返回值类型 方法名称(参数列表) {
2     方法体
3 }
 1 public interface MyInterfacePrivateA {
 2 
 3     public default void methodDefault1() {
 4         System.out.println("默认方法1");
 5         methodCommon();
 6     }
 7 
 8     public default void methodDefault2() {
 9         System.out.println("默认方法2");
10         methodCommon();
11     }
12 
13     // 普通私有方法
14     private void methodCommon() {
15         System.out.println("AAA");
16         System.out.println("BBB");
17         System.out.println("CCC");
18     }
19 
20 }
代码示例:解决默认方法代码重复问题

静态私有方法

静态私有方法:解决多个静态方法之间重复代码问题

格式

1 private static 返回值类型 方法名称(参数列表) {
2     方法体
3 }
 1 public interface MyInterfacePrivateB {
 2 
 3     public static void methodStatic1() {
 4         System.out.println("静态方法1");
 5         methodStaticCommon();
 6     }
 7 
 8     public static void methodStatic2() {
 9         System.out.println("静态方法2");
10         methodStaticCommon();
11     }
12 
13     private static void methodStaticCommon() {
14         System.out.println("AAA");
15         System.out.println("BBB");
16         System.out.println("CCC");
17     }
18 
19 }
代码示例:解决静态方法代码重复问题

接口的使用

接口使用步骤:

1. 接口不能直接使用,必须有一个“实现类”来“实现”该接口。
格式:

1 public class 实现类名称 implements 接口名称 {
2     // ...
3 }

2. 接口的实现类必须覆盖重写(实现)接口中全部的抽象方法。实现:去掉abstract关键字,加上方法体大括号。

3. 建立实现类的对象,进行使用。

常量的使用

接口中的常量使用只须要:接口名.常量名。不须要建立对象

 1 public interface MyInterfaceConst {
 2     // 这其实就是一个常量,一旦赋值,不能够修改
 3     public static final int NUM_OF_MY_CLASS = 12;
 4 
 5 }
 6 
 7 
 8 --------------------------------------------------------------------------------
 9 public static void main(String[] args) {
10     // 访问接口当中的常量
11     System.out.println(MyInterfaceConst.NUM_OF_MY_CLASS);
12 }
View Code

默认方法的使用

1. 接口的默认方法,能够经过接口实现类【对象】,直接调用。

2. 接口的默认方法,也能够被接口实现类进行覆盖重写。

 1 public interface MyInterfaceDefault {
 2     // 默认方法
 3     public default void methodDefault() {
 4         System.out.println("这是默认方法");
 5     }
 6 }
 7 
 8 
 9 
10 ----------------------------------------------------------------
11 // 在实现类中能够对默认方法进行覆盖重写,也能够什么操做都不作
12 // 可是若是想使用默认方法必需要有实现类
13 public class MyInterfaceDefaultA implements MyInterfaceDefault {
14     // 能够对默认方法覆盖重写
15 }
16 
17 
18 --------------------------------------------------------------------------
19 public class Demo02Interface {
20 
21     public static void main(String[] args) {
22         // 建立了实现类对象
23         MyInterfaceDefaultA a = new MyInterfaceDefaultA();
24 
25         // 调用默认方法,若是实现类当中没有,会向上找接口
26         a.methodDefault(); // 这是默认方法
27 
28     }
29 }
View Code

静态方法的使用

静态方法的使用:接口名.静态方法名(参数);

注意:不能经过接口实现类的对象来调用接口当中的静态方法。

 1 public interface MyInterfaceStatic {
 2 
 3     public static void methodStatic() {
 4         System.out.println("这是接口的静态方法!");
 5     }
 6 }
 7 
 8 
 9 
10 ------------------------------------------------------------------
11 // 实现类
12 public class MyInterfaceStaticImpl implements MyInterfaceStatic {
13 
14 }
15 
16 
17 ---------------------------------------------------------------------------
18 /*
19 注意事项:不能经过接口实现类的对象来调用接口当中的静态方法。
20 正确用法:经过接口名称,直接调用其中的静态方法。
21 格式:
22 接口名称.静态方法名(参数);
23  */
24 public class Demo03Interface {
25 
26     public static void main(String[] args) {
27         // 建立了实现类对象
28         MyInterfaceStaticImpl impl = new MyInterfaceStaticImpl();
29 
30         // 错误写法!
31         // impl.methodStatic();
32 
33         // 直接经过接口名称调用静态方法
34         MyInterfaceStatic.methodStatic();
35     }
36 }
View Code

抽象方法的使用

在实现类中覆盖重写抽象方法。而后建立实现类【对象】调用实现的方法。

 1 /*
 2 注意事项:
 3 1. 接口当中的抽象方法,修饰符必须是两个固定的关键字:public abstract
 4 2. 这两个关键字修饰符,能够选择性地省略。(今天刚学,因此不推荐。)
 5 3. 方法的三要素,能够随意定义。
 6  */
 7 public interface MyInterfaceAbstract {
 8 
 9     // 这是一个抽象方法
10     public abstract void methodAbs1();
11 
12     // 这也是抽象方法
13     abstract void methodAbs2();
14 
15     // 这也是抽象方法
16     public void methodAbs3();
17 
18     // 这也是抽象方法
19     void methodAbs4();
20 }
21 
22 
23 -------------------------------------------------------------------------
24 public class MyInterfaceAbstractImpl implements MyInterfaceAbstract {
25     @Override
26     public void methodAbs1() {
27         System.out.println("这是第一个方法!");
28     }
29 
30     @Override
31     public void methodAbs2() {
32         System.out.println("这是第二个方法!");
33     }
34 
35     @Override
36     public void methodAbs3() {
37         System.out.println("这是第三个方法!");
38     }
39 
40     @Override
41     public void methodAbs4() {
42         System.out.println("这是第四个方法!");
43     }
44 }
45 
46 
47 
48 -----------------------------------------------------------------
49 /*
50 注意事项:
51 若是实现类并无覆盖重写接口中全部的抽象方法,那么这个实现类本身就必须是抽象类。
52  */
53 public class Demo01Interface {
54 
55     public static void main(String[] args) {
56         // 错误写法!不能直接new接口对象使用。
57         // MyInterfaceAbstract inter = new MyInterfaceAbstract();
58 
59         // 建立实现类的对象使用
60         MyInterfaceAbstractImpl impl = new MyInterfaceAbstractImpl();
61         impl.methodAbs1();
62         impl.methodAbs2();
63     }
64 }
View Code

注意事项:若是实现类并无覆盖重写接口中全部的抽象方法,那么这个实现类本身就必须是抽象类。

私有方法的使用

普通私有方法:只有在其接口中的默认方法能够调用。

私有静态方法:只有在其接口中的默认方法和静态方法能够调用。

若是一个接口中有多个默认方法,而且方法中有重复的内容,那么能够抽取出来封装到私有方法中,供默认方法调用。从设计的角度讲,私有的方法是对默认方法和静态方法的辅助

接口的多实现

在继承体系中,一个类只能继承一个父类。而对于接口而言,一个类是能够实现多个接口的,这叫作接口的多实现。而且,一个类能继承一个父类,同时实现多个接口。

语法

1 class 类名 [extends 父类名] implements 接口名1,接口名2,接口名3... {     
2     // 重写接口中抽象方法【必须】    
3     // 重写接口中默认方法【不重名时可选】    
4 }

多实现中的抽象方法

接口中,有多个抽象方法时,实现类必须重写全部抽象方法若是抽象方法有重名的,只须要重写一次

 1 public interface MyInterfaceA {
 2 
 3     public abstract void methodA();
 4 
 5     public abstract void methodAbs();
 6 
 7 }
 8 
 9 
10 
11 -------------------------------------------------------
12 public interface MyInterfaceB {
13 
14     public abstract void methodB();
15 
16     public abstract void methodAbs();
17 
18 }
19 
20 
21 
22 ------------------------------------------------------------
23 public class MyInterfaceImpl implements MyInterfaceA, MyInterfaceB {
24     
25     @Override
26     public void methodA() {
27         System.out.println("覆盖重写了A方法");
28     }
29 
30 
31     @Override
32     public void methodB() {
33         System.out.println("覆盖重写了B方法");
34     }
35 
36     // 重名的只须要重写一次
37     @Override
38     public void methodAbs() {
39         System.out.println("覆盖重写了AB接口都有的抽象方法");
40     }
41 }
View Code

注意:若是实现类没有覆盖重写全部接口当中的全部抽象方法,那么实现类就必须是一个抽象类。

多实现中的默认方法

接口中,有多个默认方法时,实现类均可继承使用。不重名的能够不重写。若是默认方法有重名的,必须重写一次。

 1 public interface MyInterfaceA {
 2 
 3     public default void methodDefault() {
 4         System.out.println("默认方法AAA");
 5     }
 6 }
 7 
 8 
 9 
10 ---------------------------------------------------
11 public interface MyInterfaceB {
12 
13     public default void methodDefault() {
14         System.out.println("默认方法BBB");
15     }
16 
17 }
18 
19 
20 
21 -------------------------------------------------------
22 public class MyInterfaceImpl implements MyInterfaceA, MyInterfaceB {
23     // 两个接口中重名。必须重写
24     @Override
25     public void methodDefault() {
26         System.out.println("对多个接口当中冲突的默认方法进行了覆盖重写");
27     }
28 }
View Code

多实现中的静态方法

接口中,存在同名的静态方法并不会冲突,缘由是只能经过各自接口名访问静态方法。

优先级问题

一个类若是直接父类当中的方法,和接口当中的默认方法产生了冲突,优先用父类当中的方法。

接口的多继承

一个接口能继承另外一个或者多个接口,这和类之间的继承比较类似。接口的继承使用 extends 关键字,子接口继承父接口的方法。

 1 // 接口A
 2 public interface MyInterfaceA {
 3 
 4     public abstract void methodA();
 5 
 6     public abstract void methodCommon();
 7 
 8     public default void methodDefault() {
 9         System.out.println("AAA");
10     }
11 }
12 
13 
14 
15 ----------------------------------------------------------
16 // 接口B
17 public interface MyInterfaceB {
18 
19     public abstract void methodB();
20 
21     public abstract void methodCommon();
22 
23     public default void methodDefault() {
24         System.out.println("BBB");
25     }
26 }
27 
28 
29 
30 --------------------------------------------------------------
31 // 继承接口A和B的接口
32 /*
33 这个子接口当中有几个方法?答:4个。
34 methodA 来源于接口A
35 methodB 来源于接口B
36 methodCommon 同时来源于接口A和B
37 method 来源于我本身
38  */
39 public interface MyInterface extends MyInterfaceA, MyInterfaceB {
40 
41     public abstract void method();
42 
43     @Override
44     public default void methodDefault() {
45 
46     }
47 }
48 
49 
50 ----------------------------------------------------------------------
51 // 实现类
52 
53 public class MyInterfaceImpl implements MyInterface {
54     @Override
55     public void method() {
56 
57     }
58 
59     @Override
60     public void methodA() {
61 
62     }
63 
64     @Override
65     public void methodB() {
66 
67     }
68 
69     @Override
70     public void methodCommon() {
71 
72     }
73 }
View Code

注意事项:
1. 多个父接口当中的抽象方法若是重复不要紧

2. 多个父接口当中的默认方法若是重复,那么子接口必须进行默认方法的覆盖重写,【并且带着default关键字】。

异常

异常定义

异常 :指的是程序在执行过程当中,出现的非正常的状况,最终会致使JVM的非正常中止。

在Java等面向对象的编程语言中,异常自己是一个类,产生异常就是建立异常对象并抛出了一个异常对象。Java处理异常的方式是中断处理。 

注意:异常指的并非语法错误,语法错了,编译不经过,不会产生字节码文件,根本不能运行.

异常分类

 异常的根类是java.lang.Throwable,其下有两个子类:java.lang.Errorjava.lang.Exception日常所说的异常指java.lang.Exception

Error:严重错误Error,没法经过处理的错误,只能事先避免,比如绝症。

Exception:表示异常,异常产生后程序员能够经过代码的方式纠正,使程序继续运行,是必需要处理的。比如感冒、阑尾炎

Throwable中的经常使用方法:

public void printStackTrace():打印异常的详细信息。
  包含了异常的类型,异常的缘由,还包括异常出现的位置,在开发和调试阶段,都得使用printStackTrace。*

public String getMessage():获取发生异常的缘由。
  提示给用户的时候,就提示错误缘由。

public String toString():获取异常的类型和异常描述信息(不用)。

异常处理

抛出异常throw

在java中,提供了一个throw关键字,它用来抛出一个指定的异常对象。

  1,建立一个异常对象。封装一些提示信息(信息能够本身编写)。

  2,须要将这个异常对象告知给调用者。怎么告知呢?怎么将这个异常对象传递到调用者处呢?经过关键字throw就能够完成。throw 异常对象。

语法:

1 throw new 异常类名(参数);
2 示例:
3 throw new NullPointerException("要访问的arr数组不存在");
4 
5 throw new ArrayIndexOutOfBoundsException("该索引在数组中不存在,已超出范围");

注意:
1.throw关键字必须写在方法的内部

2.throw关键字后边new的对象必须是Exception或者Exception的子类对象

3.throw关键字抛出指定的异常对象,咱们就必须处理这个异常对象
  throw关键字后边建立的是RuntimeException或者是 RuntimeException的子类对象,咱们能够不处理,默认交给JVM处理(打印异常对象并中断程序)
  throw关键字后边建立的是编译异常(写代码的时候报错),咱们就必须处理这个异常,要么throws,要么try...catch 

 1 public class Demo03Throw {
 2     public static void main(String[] args) {
 3         //int[] arr = null;
 4         int[] arr = new int[3];
 5         int e = getElement(arr,3);
 6         System.out.println(e);
 7     }
 8     /*
 9         定义一个方法,获取数组指定索引处的元素
10         参数:
11             int[] arr
12             int index
13         之后(工做中)咱们首先必须对方法传递过来的参数进行合法性校验
14         若是参数不合法,那么咱们就必须使用抛出异常的方式,告知方法的调用者,传递的参数有问题
15         注意:
16             NullPointerException是一个运行期异常,咱们不用处理,默认交给JVM处理
17             ArrayIndexOutOfBoundsException是一个运行期异常,咱们不用处理,默认交给JVM处理
18      */
19     public static int getElement(int[] arr,int index){
20         /*
21             咱们能够对传递过来的参数数组,进行合法性校验
22             若是数组arr的值是null
23             那么咱们就抛出空指针异常,告知方法的调用者"传递的数组的值是null"
24          */
25         if(arr == null){
26             throw new NullPointerException("传递的数组的值是null");
27         }
28 
29         /*
30             咱们能够对传递过来的参数index进行合法性校验
31             若是index的范围不在数组的索引范围内
32             那么咱们就抛出数组索引越界异常,告知方法的调用者"传递的索引超出了数组的使用范围"
33          */
34         if(index<0 || index>arr.length-1){
35             throw new ArrayIndexOutOfBoundsException("传递的索引超出了数组的使用范围");
36         }
37 
38         int ele = arr[index];
39         return ele;
40     }
41 }
throw代码示例

源码中对throw的使用示例:Object中的方法查看引用对象是否为null

1 //Obects类中的静态方法
2 //public static <T> T requireNonNull(T obj):查看指定引用对象不是null。
3 源码:
4 public static <T> T requireNonNull(T obj) {
5     if (obj == null){
6         throw new NullPointerException();
7     }
8     return obj;
9 }
 1 import java.util.Objects;
 2 
 3 public class Demo04Objects {
 4     public static void main(String[] args) {
 5         method(null);
 6     }
 7 
 8     public static void method(Object obj){
 9         //对传递过来的参数进行合法性判断,判断是否为null
10         // if(obj == null){
11         //     throw new NullPointerException("传递的对象的值是null");
12         // }
13 
14         //Objects.requireNonNull(obj);
15         Objects.requireNonNull(obj,"传递的对象的值是null");
16     }
17 }
View Code

声明异常throws

throws关键字:异常处理的第一种方式,交给别人处理

做用:
  当方法内部抛出异常对象的时候,那么咱们就必须处理这个异常对象
  可使用throws关键字处理异常对象,会把异常对象声明抛出给方法的调用者处理(本身不处理,给别人处理),最终交给JVM处理-->中断处理

使用格式:(方法声明的时候使用)

1 修饰符 返回值类型 方法名(参数列表) throws AAAExcepiton,BBBExcepiton...{
2     throw new AAAExcepiton("产生缘由");
3     throw new BBBExcepiton("产生缘由");
4     ...
5 }

注意:
1.throws关键字必须写在方法声明处

2.throws关键字后边声明的异常必须是Exception或者是Exception的子类

3.方法内部若是抛出了多个异常对象,那么throws后边必须也声明多个异常
  若是抛出的多个异常对象有子父类关系,那么直接声明父类异常便可

4.调用了一个声明抛出异常的方法,咱们就必须的处理声明的异常
  1)要么继续使用throws声明抛出,交给方法的调用者处理,最终交给JVM
  2)要么try...catch本身处理异常

 1 import java.io.FileNotFoundException;
 2 import java.io.IOException;
 3 
 4 public class Demo05Throws {
 5     /*
 6         FileNotFoundException extends IOException extends Excepiton
 7         若是抛出的多个异常对象有子父类关系,那么直接声明父类异常便可
 8      */
 9     //public static void main(String[] args) throws FileNotFoundException,IOException {
10     //public static void main(String[] args) throws IOException {
11     public static void main(String[] args) throws Exception {
12         readFile("c:\\a.tx");
13 
14         System.out.println("后续代码");
15     }
16 
17     /*
18         定义一个方法,对传递的文件路径进行合法性判断
19         若是路径不是"c:\\a.txt",那么咱们就抛出文件找不到异常对象,告知方法的调用者
20         注意:
21             FileNotFoundException是编译异常,抛出了编译异常,就必须处理这个异常
22             可使用throws继续声明抛出FileNotFoundException这个异常对象,让方法的调用者处理
23      */
24     public static void readFile(String fileName) throws FileNotFoundException,IOException{
25         if(!fileName.equals("c:\\a.txt")){
26             throw new FileNotFoundException("传递的文件路径不是c:\\a.txt");
27         }
28 
29         /*
30             若是传递的路径,不是.txt结尾
31             那么咱们就抛出IO异常对象,告知方法的调用者,文件的后缀名不对
32          */
33         if(!fileName.endsWith(".txt")){
34             throw new IOException("文件的后缀名不对");
35         }
36 
37         System.out.println("路径没有问题,读取文件");
38     }
39 }
throws声明异常代码示例

try---catch捕获异常

try...catch:异常处理的第二种方式,本身处理异常

格式:

 1 try{
 2     可能产生异常的代码
 3 }catch(定义一个异常的变量,用来接收try中抛出的异常对象){
 4     异常的处理逻辑,异常异常对象以后,怎么处理异常对象
 5     通常在工做中,会把异常的信息记录到一个日志中
 6 }
 7 ...
 8 catch(异常类名 变量名){
 9 
10 }

注意:

  1.try中可能会抛出多个异常对象,那么就可使用多个catch来处理这些异常对象

  2.若是try中产生了异常,那么就会执行catch中的异常处理逻辑,执行完毕catch中的处理逻辑,继续执行try...catch以后的代码
          若是try中没有产生异常,那么就不会执行catch中异常的处理逻辑,执行完try中的代码,继续执行try...catch以后的代码

打印错误信息的经常使用方法:

public void printStackTrace():打印异常的详细信息。
  包含了异常的类型,异常的缘由,还包括异常出现的位置,在开发和调试阶段,都得使用printStackTrace。*

public String getMessage():获取发生异常的缘由。
  提示给用户的时候,就提示错误缘由。

public String toString():获取异常的类型和异常描述信息(不用)。

 1 import java.io.IOException;
 2 
 3 public class Demo01TryCatch {
 4     public static void main(String[] args) {
 5         try{
 6             //可能产生异常的代码
 7             readFile("d:\\a.tx");
 8             System.out.println("资源释放");
 9         }catch (IOException e){//try中抛出什么异常对象,catch就定义什么异常变量,用来接收这个异常对象
10             //异常的处理逻辑,异常异常对象以后,怎么处理异常对象
11             //System.out.println("catch - 传递的文件后缀不是.txt");
12 
13             /*
14                 Throwable类中定义了3个异常处理的方法
15                  String getMessage() 返回此 throwable 的简短描述。
16                  String toString() 返回此 throwable 的详细消息字符串。
17                  void printStackTrace()  JVM打印异常对象,默认此方法,打印的异常信息是最全面的
18              */
19             //System.out.println(e.getMessage());//文件的后缀名不对
20             //System.out.println(e.toString());//重写Object类的toString java.io.IOException: 文件的后缀名不对
21             //System.out.println(e);//java.io.IOException: 文件的后缀名不对
22 
23 
24             // e.printStackTrace();
25             /*
26                 java.io.IOException: 文件的后缀名不对
27                     at com.itheima.demo02.Exception.Demo01TryCatch.readFile(Demo01TryCatch.java:55)
28                     at com.itheima.demo02.Exception.Demo01TryCatch.main(Demo01TryCatch.java:27)
29              */
30             
31         }
32         System.out.println("后续代码");
33     }
34 
35     /*
36        若是传递的路径,不是.txt结尾
37        那么咱们就抛出IO异常对象,告知方法的调用者,文件的后缀名不对
38     */
39     public static void readFile(String fileName) throws IOException {
40 
41         if(!fileName.endsWith(".txt")){
42             throw new IOException("文件的后缀名不对");
43         }
44 
45         System.out.println("路径没有问题,读取文件");
46     }
47 }
48 
49     
View Code

finally代码块

finally:有一些特定的代码不管异常是否发生,都须要执行。另外,由于异常会引起程序跳转,致使有些语句执行不到。而finally就是解决这个问题的,在finally代码块中存放的代码都是必定会被执行的。

格式:

 1 try{
 2     可能产生异常的代码
 3 }catch(定义一个异常的变量,用来接收try中抛出的异常对象){
 4     异常的处理逻辑,异常异常对象以后,怎么处理异常对象
 5     通常在工做中,会把异常的信息记录到一个日志中
 6 }
 7 ...
 8 catch(异常类名 变量名){
 9 
10 }finally{
11     不管是否出现异常都会执行
12 }

注意:

  1,finally不能单独使用,必须和try一块儿使用

  2,finally通常用于资源释放(资源回收),不管程序是否出现异常,最后都要资源释放(IO)

  3,当只有在try或者catch中调用退出JVM的相关方法,此时finally才不会执行,不然finally永远会执行

 1 import java.io.IOException;
 2 
 3 public class Demo02TryCatchFinally {
 4     public static void main(String[] args) {
 5         try {
 6             //可能会产生异常的代码
 7             readFile("c:\\a.tx");
 8         } catch (IOException e) {
 9             //异常的处理逻辑
10             e.printStackTrace();
11         } finally {
12             //不管是否出现异常,都会执行
13             System.out.println("资源释放");
14         }
15     }
16 
17     /*
18        若是传递的路径,不是.txt结尾
19        那么咱们就抛出IO异常对象,告知方法的调用者,文件的后缀名不对
20 
21     */
22     public static void readFile(String fileName) throws IOException {
23 
24         if(!fileName.endsWith(".txt")){
25             throw new IOException("文件的后缀名不对");
26         }
27 
28         System.out.println("路径没有问题,读取文件");
29     }
30 }
finally代码块示例

异常注意事项

 注意1:多个异常使用捕获又该如何处理呢?
  1. 多个异常分别处理。
  2. 多个异常一次捕获,屡次处理。【推荐】
  3. 多个异常一次捕获一次处理。

 1 import java.util.List;
 2 
 3 public class Demo01Exception {
 4     public static void main(String[] args) {
 5         /*
 6             多个异常使用捕获又该如何处理呢?
 7             1. 多个异常分别处理。
 8             2. 多个异常一次捕获,屡次处理。
 9             3. 多个异常一次捕获一次处理。
10          */
11 
12         //1. 多个异常分别处理。
13        try {
14             int[] arr = {1,2,3};
15             System.out.println(arr[3]);//ArrayIndexOutOfBoundsException: 3
16         }catch (ArrayIndexOutOfBoundsException e){
17             System.out.println(e);
18         }
19 
20         try{
21             List<Integer> list = List.of(1, 2, 3);
22             System.out.println(list.get(3));//IndexOutOfBoundsException: Index 3 out-of-bounds for length 3
23         }catch (IndexOutOfBoundsException e){
24             System.out.println(e);
25         }
26 
27 
28         //2. 多个异常一次捕获,屡次处理。
29         try {
30             int[] arr = {1,2,3};
31             //System.out.println(arr[3]);//ArrayIndexOutOfBoundsException: 3
32             List<Integer> list = List.of(1, 2, 3);
33             System.out.println(list.get(3));//IndexOutOfBoundsException: Index 3 out-of-bounds for length 3
34         }catch (ArrayIndexOutOfBoundsException e){
35             System.out.println(e);
36         }catch (IndexOutOfBoundsException e){
37             System.out.println(e);
38         }
39 
40         /*
41             一个try多个catch注意事项:
42                 catch里边定义的异常变量,若是有子父类关系,那么子类的异常变量必须写在上边,不然就会报错
43                 ArrayIndexOutOfBoundsException extends IndexOutOfBoundsException
44          */
45         try {
46             int[] arr = {1,2,3};
47             //System.out.println(arr[3]);//ArrayIndexOutOfBoundsException: 3
48             List<Integer> list = List.of(1, 2, 3);
49             System.out.println(list.get(3));//IndexOutOfBoundsException: Index 3 out-of-bounds for length 3
50         }catch (IndexOutOfBoundsException e){
51             System.out.println(e);
52         }catch (ArrayIndexOutOfBoundsException e){
53             System.out.println(e);
54         }
55 
56         //3. 多个异常一次捕获一次处理。
57         try {
58             int[] arr = {1,2,3};
59             //System.out.println(arr[3]);//ArrayIndexOutOfBoundsException: 3
60             List<Integer> list = List.of(1, 2, 3);
61             System.out.println(list.get(3));//IndexOutOfBoundsException: Index 3 out-of-bounds for length 3
62         }catch (Exception e){
63             System.out.println(e);
64         }
65     }
66 }
代码示例

注意2:运行时异常被抛出能够不处理。即不捕获也不声明抛出。

默认给虚拟机处理,终止程序,何时不抛出运行时异常了,在来继续执行程序

 1 import java.util.List;
 2 
 3 public class Demo01Exception {
 4     public static void main(String[] args) {
 5 
 6         //运行时异常被抛出能够不处理。即不捕获也不声明抛出。
 7         //默认给虚拟机处理,终止程序,何时不抛出运行时异常了,在来继续执行程序
 8         int[] arr = {1,2,3};
 9         System.out.println(arr[3]);//ArrayIndexOutOfBoundsException: 3
10         List<Integer> list = List.of(1, 2, 3);
11         System.out.println(list.get(3));//IndexOutOfBoundsException: Index 3 out-of-bounds for length 3
12 
13         System.out.println("后续代码!");
14     }
15 }
View Code

注意3:若是finally有return语句,永远返回finally中的结果,避免该状况.

 1 public class Demo02Exception {
 2     public static void main(String[] args) {
 3         int a = getA();
 4         System.out.println(a);// 100
 5     }
 6 
 7     //定义一个方法,返回变量a的值
 8     public static int getA(){
 9         int a = 10;
10         try{
11             return a;
12         }catch (Exception e){
13             System.out.println(e);
14         }finally {
15             //必定会执行的代码
16             a = 100;
17             return a;
18         }
19     }
20 }
View Code

注意4:子父类的异常:

  若是父类抛出了多个异常,子类重写父类方法时,抛出和父类相同的异常或者是父类异常的子类或者不抛出异常。

  父类方法没有抛出异常,子类重写父类该方法时也不可抛出异常。此时子类产生该异常,只能捕获处理,不能声明抛出

 1 public class Fu {
 2     public void show01() throws NullPointerException,ClassCastException{}
 3     public void show02() throws IndexOutOfBoundsException{}
 4     public void show03() throws IndexOutOfBoundsException{}
 5     public void show04() throws Exception {}
 6 }
 7 
 8 class Zi extends Fu{
 9     //子类重写父类方法时,抛出和父类相同的异常
10     public void show01() throws NullPointerException,ClassCastException{}
11 
12     //子类重写父类方法时,抛出父类异常的子类
13     public void show02() throws ArrayIndexOutOfBoundsException{}
14 
15     //子类重写父类方法时,不抛出异常
16     public void show03() {}
17 
18     /*
19         父类方法没有抛出异常,子类重写父类该方法时也不可抛出异常。
20      */
21     //public void show04() throws Exception{}
22 
23     //此时子类产生该异常,只能捕获处理,不能声明抛出
24     public void show04()  {
25         try {
26             throw  new Exception("编译期异常");
27         } catch (Exception e) {
28             e.printStackTrace();
29         }
30     }
31 }
View Code

自定义异常

为何要自定义异常:

  咱们说了Java中不一样的异常类,分别表示着某一种具体的异常状况,那么在开发中老是有些异常状况是SUN没有定义好的,此时咱们根据本身业务的异常状况来定义异常类。例如年龄负数问题,考试成绩负数问题等等。

什么是自定义异常类:

  在开发中根据本身业务的异常状况来定义异常类.

  自定义一个业务逻辑异常: RegisterException。一个注册异常类。

异常类如何定义:

  自定义一个编译期异常: 自定义类 并继承于java.lang.Exception

  自定义一个运行时期的异常类:自定义类 并继承于java.lang.RuntimeException

 语法:

1 public class XXXExcepiton extends Exception | RuntimeException{
2     添加一个空参数的构造方法
3     添加一个带异常信息的构造方法
4 }

注意:
  1.自定义异常类通常都是以Exception结尾,说明该类是一个异常类

  2.自定义异常类,必须的继承Exception或者RuntimeException
    继承Exception:那么自定义的异常类就是一个编译期异常,若是方法内部抛出了编译期异常,就必须处理这个异常,要么throws,要么try...catch
    继承RuntimeException:那么自定义的异常类就是一个运行期异常,无需处理,交给虚拟机处理(中断处理) 

 1 public class RegisterException extends /*Exception*/ RuntimeException{
 2     //添加一个空参数的构造方法
 3     public RegisterException(){
 4         super();
 5     }
 6 
 7     /*
 8         添加一个带异常信息的构造方法
 9         查看源码发现,全部的异常类都会有一个带异常信息的构造方法,方法内部会调用父类带异常信息的构造方法,让父类来处理这个异常信息
10      */
11     public RegisterException(String message){
12         super(message);
13     }
14 }
自定义异常类代码示例

自定义异常的使用语法和系统提供的使用语法相同:

 1 public class RegisterException extends /*Exception*/ RuntimeException{
 2     //添加一个空参数的构造方法
 3     public RegisterException(){
 4         super();
 5     }
 6 
 7     /*
 8         添加一个带异常信息的构造方法
 9         查看源码发现,全部的异常类都会有一个带异常信息的构造方法,方法内部会调用父类带异常信息的构造方法,让父类来处理这个异常信息
10      */
11     public RegisterException(String message){
12         super(message);
13     }
14 }
15 
16 
17 ========================================
18 import java.util.Scanner;
19 
20 /*
21     要求:咱们模拟注册操做,若是用户名已存在,则抛出异常并提示:亲,该用户名已经被注册。
22 
23     分析:
24         1.使用数组保存已经注册过的用户名(数据库)
25         2.使用Scanner获取用户输入的注册的用户名(前端,页面)
26         3.定义一个方法,对用户输入的中注册的用户名进行判断
27             遍历存储已经注册过用户名的数组,获取每个用户名
28             使用获取到的用户名和用户输入的用户名比较
29                 true:
30                     用户名已经存在,抛出RegisterException异常,告知用户"亲,该用户名已经被注册";
31                 false:
32                     继续遍历比较
33             若是循环结束了,尚未找到重复的用户名,提示用户"恭喜您,注册成功!";
34  */
35 public class Demo01RegisterException {
36     // 1.使用数组保存已经注册过的用户名(数据库)
37     static String[] usernames = {"张三","李四","王五"};
38 
39     public static void main(String[] args) /*throws RegisterException*/ {
40         //2.使用Scanner获取用户输入的注册的用户名(前端,页面)
41         Scanner sc = new Scanner(System.in);
42         System.out.println("请输入您要注册的用户名:");
43         String username = sc.next();
44         checkUsername(username);
45 
46     }
47 
48     //3.定义一个方法,对用户输入的中注册的用户名进行判断
49     public static void checkUsername(String username) /*throws RegisterException*/ {
50         //遍历存储已经注册过用户名的数组,获取每个用户名
51         for (String name : usernames) {
52             //使用获取到的用户名和用户输入的用户名比较
53             if(name.equals(username)){
54                 //true:用户名已经存在,抛出RegisterException异常,告知用户"亲,该用户名已经被注册";
55                 try {
56                     throw new RegisterException("亲,该用户名已经被注册");
57                 } catch (RegisterException e) {
58                     e.printStackTrace();
59                     return; //结束方法
60                 }
61             }
62         }
63         //若是循环结束了,尚未找到重复的用户名,提示用户"恭喜您,注册成功!";
64         System.out.println("恭喜您,注册成功!");
65     }
66 }
自定义异常使用

 

 

 

 

 

 

 

 

------------------------------

相关文章
相关标签/搜索