Java---第 7 章 (抽象クラス、インターフェイス、ポリモーフィズム、オブジェクト、例外処理)

ここに画像の説明を挿入

抽象クラス

抽象クラスの概要

コンセプト:

抽象クラスは、抽象として宣言されたクラスです。抽象メソッドが含まれる場合も含まれない場合もあり、抽象クラスはインスタンス化できませんが、サブクラス化することはできます (つまり、継承できます)。

抽象クラス定義の構文:

public abstract class 类名{
    
    //定义一个抽象类

}

抽象メソッド定義構文:
何かをする方法は知っているが、その方法がわからない

访问修饰符 abstract 返回值类型 方法名(参数列表);

抽象クラスの適用シナリオ

一般に、抽象クラスは抽象的なものを記述するために使用されます。
例: 動物、機器、幾何学模様など。

public abstract class Animal {
    
    
    public abstract void eat();
}

public class Panda extends Animal {
    
    

    @Override
    public void eat() {
    
    
        System.out.println("熊猫吃竹叶");
    }
}
public class PersonTest{
    
    
    public static void main(String[] args) {
    
    
        Panda a = new Panda();
        a.eat();
    }
}

クラスが抽象クラスから継承する場合、クラスは抽象クラス内のすべての抽象メソッドを実装する必要があります。それ以外の場合、クラスは抽象クラスを定義する必要があります。
抽象クラスは必ずしも抽象メソッドを持つ必要はありません。抽象メソッドは抽象クラスである必要があります。

2つのインターフェース

インターフェースの紹介

Java プログラミング言語では、インターフェイスはクラスの参照型に似ています。定数、メソッド シグネチャ、デフォルト メソッド、静的メソッド、およびネストされた型のみを含めることができます。
メソッド本体は、デフォルト メソッドと静的メソッドでのみ使用できます。
インターフェイスはインスタンス化できません。クラスによって実装するか、他のインターフェイスによって拡張することしかできません。

インターフェイス宣言には、メソッド シグネチャ、デフォルト メソッド、静的メソッド、および定数定義を含めることができます。
実装のあるメソッドはデフォルトメソッドと定数メソッドです

インターフェースにコンストラクターがありません

文法:

[public] interface 接口名{
    
    
	[public static final]数据类型 变量名 = 变量的值;
	//接口中定义变量,该变量是静态变量,在定义时必须赋值

	返回值类型 方法名([参数列表]);//定义接口方法
	
	default 返回值类型 方法名([参数列表]){
    
    
	//接口中定义的默认方法,必须在JDK8及以上版本使用
		[return 返回值;]
	}

	static 返回值类型 方法名([参数列表]){
    
    
	//接口中定义的静态方法,必须在JDK8及以上版本使用
		[return 返回值;]
	}

	private 返回值类型 方法名([参数列表]){
    
    
	//接口中定义的私有方法,必须在JDK9及以上版本使用
		[return 返回值;]
	}
}

例:

public interface Test {
    
    
    public static final int number = 10;
    public abstract void show();
    public default int plus(int a,int b){
    
    
        return a+b;
    }
    public default int multiply(int x,int y){
    
    
        return x*y;
    }
    private String getName(){
    
    
        return "admin";
    }
}

インターフェースの継承

文法:

[public] interface 接口名 extends 接口名1,接口名2,....接口名n{
    
    

}

注: インターフェースは複数の継承を持つことができます。これは、Java で複数の継承を使用できる唯一の場所です。インターフェイスに含まれる変数はすべて静的定数であり、インターフェイスに含まれるメソッド シグネチャはすべてパブリック抽象メソッドです。インターフェイスのデフォルト メソッドと静的メソッドは JDK8 以降のバージョンでのみ定義できます。インターフェースは JDK9 以降のバージョンで定義する必要があります。インターフェイスがコンパイルされると、必要なクラス ファイルも生成されます。

インターフェースの実装

文法:

访问修饰符 class 类名 implements 接口名1,接口名2,...接口名n{
    
    
}

インターフェイスを実装するクラスは、インターフェイスで宣言されたすべてのメソッドを実装する必要があります

クラスがインターフェイスを実装する場合、そのインターフェイスで定義されたすべての抽象メソッド (継承関係によってインターフェイスによって継承された抽象メソッドを含む) を実装する必要があります。このクラスは、インターフェイスの実装クラスまたはサブクラスと呼ばれ、継承関係同様に、実装クラスとインターフェース間の関係も is-a 関係です。

練習する:

プリンターはインクカートリッジ(カラー)と用紙(サイズ)のインターフェースが外部に露出しており、インクカートリッジインターフェースの取り決めに基づいてインクカートリッジメーカーが白黒インクカートリッジとカラーインクカートリッジを生産し、用紙メーカーがA2用紙とA4用紙を生産します。紙のインターフェースに関する合意に従って。

インターフェース:
カートリッジ:

public interface InkBox {
    
    
    String getcolor();
}

紙:

public interface Paper {
    
    
    String getsize();
}

クラス:
モノクロプリンター:

public class BlackInkBox implements InkBox{
    
    
    @Override
    public String getcolor() {
    
    
        return "黑白";
    }
}

カラープリンター:

public class ColorInkBox implements InkBox{
    
    
    @Override
    public String getcolor() {
    
    
        return "彩色";
    }
}

A2用紙:

public class A2Paper implements Paper{
    
    
    @Override
    public String getsize() {
    
    
        return "A2";
    }
}

A4用紙:

public class A4Paper implements Paper{
    
    
    @Override
    public String getsize() {
    
    
        return "A4";
    }
}

プリンター:

public class Printer {
    
    
    private InkBox inkBox;
    private Paper paper;
    public Printer(){
    
    
    }
    public Printer(InkBox inkBox, Paper paper) {
    
    
        this.inkBox = inkBox;
        this.paper = paper;
    }
    public void print(){
    
    
        System.out.printf("打印机使用%s墨盒打印%s纸张上打印\n",inkBox.getcolor(),paper.getsize());
    }
    public InkBox getInkBox() {
    
    
        return inkBox;
    }
    public void setInkBox(InkBox inkBox) {
    
    
        this.inkBox = inkBox;
    }
    public Paper getPaper() {
    
    
        return paper;
    }
    public void setPaper(Paper paper) {
    
    
        this.paper = paper;
    }
}

テスト:

public class PrinterTest {
    
    
    public static void main(String[] args) {
    
    
        Printer p1 = new Printer();
        p1.setInkBox(new ColorInkBox());
        p1.setPaper(new A4Paper());
        p1.print();

        Printer p2 = new Printer(new BlackInkBox(),new A2Paper());
        p2.print();
    }
}

3 つの抽象クラスとインターフェイスの違い

  • 抽象クラスにはコンストラクターがありますが、インターフェイスにはコンストラクターがありません。
  • 抽象クラスはメンバー変数、静的変数、および静的定数を定義できますが、インターフェイスはパブリック静的定数のみを定義できます。
  • 抽象クラスのメソッドは保護されたメソッドとデフォルトのメソッドを持つことができますが、インターフェイスのメソッドはパブリックです (JDK9 で定義できるプライベート メソッドを除く)。
  • 抽象クラスは主に抽象的なものを記述するために使用され、インターフェイスは主に規則や規則を記述するために使用されます。
  • 抽象クラスは単一の継承のみを継承できますが、インターフェイスは複数の継承を実装できます。

4つの多態性(Polymorphism)

ポリモーフィズムの概要:

コンセプト:

多態性の辞書の定義は、生物または物質が多くの異なる形態または相を取ることができる生物学の原理です。
この原則は、オブジェクト指向プログラミングや Java 言語などの言語にも適用できます。
サブクラスは独自の固有の動作を定義できますが、親クラスと同じ特性の一部を共有します。

上記の説明から次のことがわかります。

  • 継承、インターフェースはポリモーフィズムの具体的な具現化です
  • ポリモーフィズムは主にカテゴリと物事のやり方に反映されます
  • ポリモーフィズムはオブジェクト指向の 3 つの主要な特徴の 1 つです
  • ポリモーフィズムは、コンパイル時ポリモーフィズム(メソッドのオーバーロード) と実行時ポリモーフィズムの2 つのカテゴリに分類されます。

コンパイル時のポリモーフィズム:
例:
メソッドのオーバーロード

2 つの乱数の合計を計算します

public class Printer {
    
    
    public long calculate(long a,long b){
    
    
        return a + b;
    }
    public double calculate(double a,double b){
    
    
        return a + b;
    }
}
public class PrinterTest {
    
    
    public static void main(String[] args) {
    
    
        Printer p = new Printer();
        long result1 = p.calculate(1,2);
        double result2 = p.calculate(1.0,2.0);
    }
}

実行時のポリモーフィズム:

Java 仮想マシン (JVM) は、各変数で参照されるオブジェクトに適切なメソッドを呼び出します。変数の type によって定義されたメソッドは呼び出されませんこの動作は仮想メソッド呼び出しと呼ばれ、Java 言語の重要な多態性機能の一側面を示しています。

親クラスはメソッドを定義します

public class Printer {
    
    
    public void show(){
    
    
        System.out.println("Father");
    }
}

サブクラスはこのメソッドをオーバーライドします

public class Person extends Printer{
    
    
    @Override
    public void show() {
    
    
        System.out.println("Child");
    }
}
public class PrinterTest {
    
    
    public static void main(String[] args) {
    
    
        //变量f的类型是Printer
        Printer p = new Person();
        //p调用show()时,不会调用Printer定义的方法
        p.show();
    }
}

5 つの instanceof 演算子

instanceof 自体は、それが意味するインスタンスです。
主に型強制に使用されます。
型強制を使用する場合、それが正しく使用されないと、実行時にエラーが報告されます。
instanceof演算子は変換のターゲット型を検出し、そうである場合は必須の型変換を実行します。これにより、プログラムの通常の動作が保証されます。

文法:

对象名 instanceof 类名;//表示检测对象是否是指定类型的一个实例,返回值为boolean型

練習する:

ショッピングモールには、テレビ、扇風機、エアコンなどの電気機器が展示されています。これらの電気機器を検査するのが既存の品質検査員で、テレビであればビデオ検査をしたり、扇風機であれば扇風機を動かしたり、電気機器であれば検査を行ったりします。

電気機器の抽象クラス:

public abstract class Device {
    
    
    public abstract void show();
}

テレビ:

public class TV extends Device{
    
    
    @Override
    public void show() {
    
    
        System.out.println("这是电视机");
    }
    public void vedio(){
    
    
        System.out.println("播放电视剧");
    }
}

エアコン:

public class AirCod extends Device{
    
    

    @Override
    public void show() {
    
    
        System.out.println("这是空调");
    }
    public void ice(){
    
    
        System.out.println("制冷");
    }
}

扇風機:

public class ElectronicFan extends Device{
    
    
    @Override
    public void show() {
    
    
        System.out.println("这是电风扇");
    }
    public void start(){
    
    
        System.out.println("启动电风扇");
    }
}

品質検査:

public class Quality {
    
    
    public void test(Device device){
    
    
        device.show();
        if(device instanceof TV){
    
    
            ((TV)device).vedio();
        } else if (device instanceof  AirCod) {
    
    
            ((AirCod)device).ice();
        } else if (device instanceof  ElectronicFan) {
    
    
            ((ElectronicFan)device).start();
        }
    }
}

テスト:

public class DeviceTest {
    
    
    public static void main(String[] args) {
    
    
        Quality q = new Quality();
        q.test(new TV());
        q.test(new AirCod());
        q.test(new ElectronicFan());
    }
}

オブジェクトクラスの6つの一般的なメソッド

Object クラスで定義されているメソッドのほとんどは、**C++** で実装されたネイティブ メソッド(ローカル メソッド) です。

getClass()

public final Class getClass()

getClass() メソッドは、名前 (getSimpleName())、そのスーパークラス // (getSuperclass())、実装するインターフェイス (getInterfaces() など) のクラスに関する情報を取得するために使用できるメソッドを持つ Class オブジェクトを返します。 )

package org.device.Device;

public class DeviceTest {
    
    
    public static void main(String[] args) {
    
    
        Quality q = new Quality();
        q.test(new TV());
        q.test(new AirCod());
        q.test(new ElectronicFan());

        TV tv = new TV();
        Class clazz  = tv.getClass();
        String name = clazz.getSimpleName();//获取类名
        System.out.println(name);
        String className = clazz.getName();//获取类的全限定名
        System.out.println(className);

        Class superclass = clazz.getSuperclass();//获取父类的定义信息
        String superName = superclass.getSimpleName();//获取父类的名称
        System.out.println(superName);
        String superClassName = superclass.getName();//获取父类的全限定名
        System.out.println(superClassName);

        String s = "admin";
        Class stringClass  = s.getClass();
        Class[] interfaceClasses = stringClass.getInterfaces();
        for(int i=0;i<interfaceClasses.length;i++){
    
    
            Class interfaceClass  = interfaceClasses[i];
            String interfaceName = interfaceClass.getSimpleName();//获取接口的名称
            System.out.println(interfaceName);
            String interfaceClassName = interfaceClass.getName();//获取接口的全限定名
            System.out.println(interfaceClassName);
        }
    }
}

ハッシュコード()

public int hashCode()

戻り値はオブジェクトのハッシュ コードであり、オブジェクトのメモリ アドレス (16 進数の 0x...) です。

定義上、2 つのオブジェクトが等しい場合、それらのハッシュ コードも等しくなければなりません。
equals() メソッドをオーバーライドすると、2 つのオブジェクトが等しい方法が変更され、Object の hashCode() の実装は無効になります。
したがって、equals() メソッドをオーバーライドする場合は、hashCode() メソッドもオーバーライドする必要があります。

Object クラスの hashCode() メソッドは、オブジェクトのメモリ アドレスを返します。hashCode() メソッドが書き換えられると、Object の hashCode() メソッドは無効になり、hashCode() によって返される値はメモリ アドレスではなくなります。

定義によれば、2 つのオブジェクトが等しい場合、ハッシュ コードは等しくなければなりません。そうでない場合、
equals メソッドが書き換えられる場合は、上記の定義の結論を満たすように hashCode メソッドを書き換える必要があります。

hashCode()を書き換える

    @Override
    public int hashCode(){
    
    
        return name.hashCode() + age;
    }

等しい(オブジェクトオブジェクト)

public boolean equals(Object obj)

equals() メソッドは、2 つのオブジェクトが等しいかどうかを比較し、等しい場合は true を返します。
Object クラスによって提供されるequals() メソッドは、恒等演算子 (==) を使用して2 つのオブジェクトが等しいかどうかを判断します。
プリミティブ データ型の場合、これにより正しい結果が得られます
ただし、 object の場合、 Object が提供する equals() メソッドは、オブジェクト参照が等しいかどうか、つまり、比較されるオブジェクトが完全に等しいかどうかをテストします。

2 つのオブジェクトが等価性に関して完全に等しい (同じ情報を含む) かどうかをテストするには、equals() メソッドをオーバーライドする必要があります。

public class Student {
    
    
    private String name;
    private int age;

    public Student(String name, int age) {
    
    
        this.name = name;
        this.age = age;
    }
    @Override
    public int hashCode(){
    
    
        return name.hashCode() + age;
    }
}

たとえば、戻り値は false です

public class DeviceTest {
    
    
    public static void main(String[] args) {
    
    
        Student s1 = new Student("张三",1);
        Student s2 = new Student("张三",1);
        boolean result = s1.equals(s2);
        System.out.println(result);//false
    }
}

equals() メソッドをオーバーライドする

    @Override
    public boolean equals(Object obj) {
    
    
        if(this == obj) return true;
        //比较类的定义是否相等
        if(this.getClass() != obj.getClass()) return false;
        //类的定义一致,那么对象obj就可被强制转换为Student
        Student other = (Student) obj;
        return this.name.equals(other.name) && this.age == other.age;
    }
  • メモリアドレスを比較する
  • ユニフォームタイプかどうかを確認する
  • 属性が等しいかどうかを確認します

== メソッドと等しいメソッドの違いを説明します。

基本的なデータ型は == を使用して、2 つのデータのリテラルが等しいかどうかを比較します。参照データ型は、等号を使用してメモリ アドレスを比較します。
equals メソッドは Object クラスから来ており、その実装も == であり、現時点ではそれらの間に違いはありません。
ただし、equalsメソッドは書き換えられる可能性があり、その際は書き換えロジックを見て比較する必要があります。

hashCode()とequals()

equals メソッドが書き換えられた場合は、hashCode メソッドも書き換える必要があります, これは、hashCodeを書き換えずにObjectクラスのhashCodeメソッドを呼び出してメモリアドレスを取得することになり、オブジェクトごとにメモリアドレスが異なるためです。
しかしequals メソッドが書き換えられた後、比較されるのはメモリアドレスではなく、オブジェクトの内部情報です。そうでない場合、複数の異なるオブジェクトが等しくなりますが、異なるハッシュ コードを持つことになります。

toString()

public String toString()

クラス内の toString() メソッドをオーバーライドすることを常に考慮する必要があります。

Object の toString() メソッドは、デバッグに役立つオブジェクトの String 表現を返します。
オブジェクトの String 表現は完全に object に依存します。そのため、クラスで toString メソッドをオーバーライドします。

次に、上記の例:

public class DeviceTest {
    
    
    public static void main(String[] args) {
    
    
        Student s1 = new Student("张三",1);
        System.out.println(s1);
        Student s2 = new Student("张三",1);
        boolean result = s1.equals(s2);
        System.out.println(result);//false
    }
}

s1 を出力した結果は次のようになります。

org.device.Device.Student@bd2ea

張三ではない 1

toString メソッドをオーバーライドする

    @Override
    public String toString() {
    
    
        return name + "\t" + age;
    }

ファイナライズ()

protected void finalize() throws Throwable

Object クラスは、オブジェクトがガベージになったときに呼び出すことができるコールバック メソッド Finalize() を提供します。
Object クラスの Finalize() 実装は何も行いません。finalize() をオーバーライドして、リソースの解放などをクリーンアップすることができます。

ファイナライズリライト

    //当一个Student对象变成垃圾时可能会被调用
    @Override
    protected void finalize() throws Throwable {
    
    
        this.name = null;
        System.out.println("所有资源已释放完毕,可以进行清理了");
    }
public class DeviceTest {
    
    
    public static void main(String[] args) {
    
    
        show();
        //garbage collertor
        System.gc();
    }
    public static void show(){
    
    
        //s对象的作用范围只是在show()方法中
        //一旦方法执行完毕,那么s对象就应该消亡,释放内存
        Student s = new Student("李四",21);
        System.out.println(s);
    }
}

ヒープ上のメモリのみがガベージを生成できます (スタック上にはガベージを参照するものはありません)。

7つの例外

珍しい紹介

コンセプト:

例外とは、プログラムの実行中に発生し、プログラム命令の通常の流れを中断するイベントです。

メソッド内でエラーが発生すると、メソッドはオブジェクトを作成し、それをランタイム システムに渡します
このオブジェクトは例外オブジェクトと呼ばれますには、エラーの種類やエラー発生時のプログラムの状態など、エラーに関する情報が含まれています。例外オブジェクトの作成とそれをランタイム システムに渡すことを総称して例外のスローと呼びます。

メソッドによって例外がスローされる

例外システム:
ここに画像の説明を挿入
Throwable は
すべての例外の親クラスであり、その共通メソッドは次のとおりです。

public String getMessage();//获取异常发生的原因

public void printStackTrace();//打印异常在栈中的轨迹信息

エラー

エラーは非常に深刻なエラーであり、プログラマーが次のように記述することによって解決することはできません。

例外

これは異常を意味し、主にプログラマーがコードを作成する際の考慮不足によって引き起こされます。例外は、実行時例外と検査例外の 2 つのカテゴリに分類され、プログラム内でこれらの例外が発生した場合、プログラマはそれらに対処する必要があります。

ランタイム例外

これは、実行時例外を示します。プログラムの実行中にスローされるすべての例外タイプは、RuntimeException のサブクラスに属します。一般に、プログラムは、実行時例外に対処することなく、自動的に実行時例外から回復できます。

チェック例外

チェック例外とは、コードのコンパイル中に不正なエンコーディングが見つかった場合にコンパイラーによってスローされる例外を指します。

例外を処理する方法

Javaには例外の種類がたくさんあり、それぞれの例外の種類を覚えなければならないとなると、非常に大変であることは間違いありません。例外を処理する一連のメカニズムがあれば、プログラマーが開発に費やす時間が短縮されます。
Java は、例外を処理するための一連の例外処理メカニズムを提供します。Javaは、例外を処理
するために 5 つのキーワードを使用します:
throw throws try catchfinally



throw は例外をスローします。

throw キーワードは、メソッド内でのみ使用できます。 throw キーワードは、例外を処理しなかったことを示す例外をスローします。

文法:

throw 异常对象;//通常与if选择结构配合使用

例:

import java.util.Scanner;

public class DeviceTest {
    
    
    private static Scanner sc = new Scanner(System.in);
    public static void main(String[] args) {
    
    
        calculate();
    }
    public static void calculate(){
    
    
        System.out.println("请输入一个数字");
        int number1 = sc.nextInt();
        System.out.println("请再输入一个数字");
        int number2 = sc.nextInt();
        if(number2 == 0){
    
    
            throw new ArithmeticException("除数不能为0");
        }
        int result = number1 / number2;
        System.out.println(result);
    }
}

数値を入力してください
1
別の数値を入力してください
0スレッド「メイン」の例外 java.lang.ArithmeticException: org.device.Device.DeviceTest.calculate(DeviceTest.java:16)
除数を 0 にすることはできません。.DeviceTest.main(DeviceTest.java:8)

throw new ArithmeticException("除数不能为0");

どちらの方法でも機能します

ArithmeticException e = new ArithmeticException("除数不能为0");
throw e;

throws は、スローされる可能性のある例外のタイプを宣言します。

throws キーワードは、メソッドまたはコンストラクターの定義にのみ適用でき、スローされる例外のタイプを宣言します。例外自体は処理されず、メソッド呼び出し元によって処理されます
メソッドの呼び出し元が処理しない場合、main() メソッドが処理されるまで上位の呼び出し元に例外がスローされ続け、main() メソッドも処理されない場合、プログラムが終了する可能性があります。

文法:

访问修饰符 返回值类型 方法名(参数列表) throws 异常类型1,异常类型2,....异常类型n{
    
    
}

例:

import java.util.Scanner;

public class DeviceTest {
    
    
    private static Scanner sc = new Scanner(System.in);
    public static void main(String[] args) {
    
    
        deviced();
    }
    public  static int deviced() throws InterruptedException,ArithmeticException{
    
    
        int number1 = getNumber();
        int number2 = getNumber();
        return number1/number2;
    }
    public static int  getNumber()throws InterruptedException{
    
    
        System.out.println("请输入一个数字");
        int number = sc.nextInt();
        return number;
    }
}

throws はメソッドの実行中にスローされる例外のタイプを宣言できますが、メソッドの実行中にスローできる例外は 1 つだけであることに注意してください。

try-catch キャッチ例外:

throw キーワードと throws キーワードはいずれも例外を処理しないため、プログラムが終了する可能性があります。この場合、try-catch 構造体を使用してスローされた例外をキャッチし、プログラムを正常に実行できるようにすることができます。

文法:

try{
    
    
	//代码块
}catch(异常类型 异常对象名){
    
    
}

このうち、try は試すという意味で、try 構造内のコードブロックを実行しようとします。実行中に例外がスローされた場合は、キャプチャ操作のために catch ステートメントブロックに渡されます。

例:

import java.util.Scanner;

public class DeviceTest {
    
    
    private static Scanner sc = new Scanner(System.in);
    public static void main(String[] args) {
    
    
        try{
    
    
            int number = deviced();
            System.out.println(number);
        }catch (InterruptedException e){
    
    
            e.printStackTrace();//打印异常轨迹
            System.out.println("请不要瞎搞");
        }
        System.out.println("发生异常也会执行");
    }
    public  static int deviced() throws InterruptedException,ArithmeticException{
    
    
        int number1 = getNumber();
        int number2 = getNumber();
        return number1/number2;
    }
    public static int  getNumber()throws InterruptedException{
    
    
        System.out.println("请输入一个数字");
        int number = sc.nextInt();
        return number;
    }
}

複数の例外キャプチャの処理:

    public  static int deviced(){
    
    
        try{
    
    
            int number1 = getNumber();
            int number2 = getNumber();
            return number1/number2;
        }catch (InterruptedException e){
    
    
            System.out.println("请不要瞎搞");
        }catch (ArithmeticException e){
    
    
            System.out.println("除数不能为0");
        }
        return 0;
    }

複数の catch 句を使用して例外をキャッチする場合、キャッチされた複数の例外オブジェクトのデータ型に継承関係がある場合、次のように親クラスの例外を前に置くことはできません

    int a = 100;
    if(a>100){
    
    

    }else(a>10){
    
    
        
    }

finally ステートメント:
finally ステートメントは単独で使用することはできず、try ステートメントまたは try-catch 構造体と組み合わせて使用​​する必要があります。これは、例外が発生するかどうかに関係なくプログラムが実行されることを意味し、主にリソースを解放するために使用されます。
ただし、try 文または catch 文にシステム終了コードがある場合、finally 文は実行されません。

System.exit(0);//系统正常退出
0正常退出,非0异常退出
System.exit(-1);//系统异常退出

文法:

try{
    
    
} finally{
    
    
}

//或者

try{
    
    
} catch(异常类型 异常对象名){
    
    
}finally{
    
    
}

例:

package org.device.Device;

public class DeviceTest {
    
    
    private static int[] numbers = {
    
    1,2,3,4,5};
    public static void main(String[] args) {
    
    
        try{
    
    
            int number = getNumber(5);
            System.out.println(number);
        }catch (ArrayIndexOutOfBoundsException e){
    
    
            System.out.println("数组下标越界了");
            System.exit(0);
        }finally {
    
    
            System.out.println("需要执行的代码");
        }
    }
    public static int getNumber(int index){
    
    
        return numbers[index];
    }
}

考えるための質問:

public class DeviceTest {
    
    
    public static void main(String[] args) {
    
    
        int result = getNumber();
        System.out.println(result);
    }
    public static int getNumber(){
    
    
        int number = 10;
        try{
    
    
            return number;
        }catch (Exception e){
    
    
            return 1;
        }finally {
    
    
            number++;
        }
    }
}

結果は次のとおりです。

10

try は return を実行しようとすることです
—> 結果を返そうとしますが、後ろにfinallyモジュールがあることがわかり、finallyモジュールは確実に実行されるため、ここでは戻り値を一時変数に格納することしかできません。 finally モジュールを実行し、finally モジュールを実行します。実行後、この一時変数を返します

カスタム例外

カスタム例外を使用する理由
Javaでは例外の種類が豊富で、これらの例外を利用するにはまずその例外に慣れておく必要があり、膨大な作業量と時間がかかることは間違いありません。
例外をカスタマイズできる場合は、RuntimeException、Exception、および Throwable について理解するだけで済みます
これにより範囲が大幅に狭まり、カスタム例外は問題を迅速に特定するのにも役立ちます。

カスタム ランタイム例外構文:

public class 类名 extends RuntimeException{
    
    }

カスタムチェック例外構文:

public class 类名 extends Exception{
    
    }

例:
アカウントログイン

package org.device.Device;

import javax.management.BadAttributeValueExpException;
import java.util.Scanner;

public class DeviceTest {
    
    
    public static Scanner sc = new Scanner(System.in);
    public static void main(String[] args){
    
    
        System.out.println("请输入账号");
        String  username = sc.next();
        System.out.println("请输入密码");
        String  password = sc.next();
        try {
    
    
            login(username,password);
        } catch (BadAttributeValueExpException e) {
    
    
            throw new RuntimeException(e);
        } catch (UsernameNotFound e) {
    
    
            throw new RuntimeException(e);
        } catch (BadCredentialsException e) {
    
    
            throw new RuntimeException(e);
        }
    }
    public static void login(String username,String password) throws BadAttributeValueExpException, UsernameNotFound, BadCredentialsException {
    
    
        if("admin".equals(username)){
    
    
            if("12345".equals(password)){
    
    
                System.out.println("登录成功");
            }else{
    
    
                throw new BadCredentialsException("账号或者密码错误");
            }
        }else{
    
    
            throw new UsernameNotFound("账号不存在");
        }
    }
}
package org.device.Device;

public  class UsernameNotFound extends Exception {
    
    
    public UsernameNotFound(){
    
    }
    public UsernameNotFound(String msg){
    
    
        super(msg);
    }
}
package org.device.Device;

public class BadCredentialsException extends Exception{
    
    
    public BadCredentialsException(){
    
    }
    public BadCredentialsException(String msg){
    
    
        super(msg);
    }
}

例外の使用上の注意:

  • 実行時例外が処理されない可能性がある
  • 親クラスが複数の例外をスローする場合、サブクラスが親クラスのメソッドをオーバーライドすると、同じ例外または例外のサブセットのみをスローできます (共変戻り値の型の原則と同じ)
  • 親クラスのメソッドは例外をスローせず、サブクラスは親クラスのメソッドをオーバーライドするときにチェック例外をスローできません。このとき、サブクラスは例外を生成しますが、この例外はキャッチして処理することしかできず、宣言することはできません。投げられる

おすすめ

転載: blog.csdn.net/weixin_72138633/article/details/131807453