JAVAの基礎-第15章例外とスレッド

メインコンテンツ

例外、スレッド、
教育目標、
プログラムの例外とエラーの違いを区別できる、例外
の分類を説明
する、仮想マシンが例外を処理する方法を言う、
3つの一般的なランタイム例外をリスト
する、try ... catchキーワードを
使用して例外を処理できる、throwsキーワードを使用できる例外を処理
する例外クラスをカスタマイズする機能
カスタム例外クラス
を処理する機能プロセスの概念
話すスレッドの概念話す
並行処理と並列処理の違いを理解
する機能新しいスレッドを開始する機能

# 第一章 异常

## 1.1 异常概念

### 异常,就是不正常的意思。在生活中:医生说,你的身体某个部位有异常,该部位和正常相比有点不同,该部位的功能将

### 受影响.在程序中的意思就是:

### 异常 :指的是程序在执行过程中,出现的非正常的情况,最终会导致JVM的非正常停止。

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

例外は構文エラーに関するものではありません。構文が間違っているため、コンパイルは失敗し、バイトコードファイルは生成されず、まったく実行されません。

## 1.2 异常体系

异常机制其实是帮助我们找到程序中的问题,异常的根类是java.lang.Throwable,其下有两个子类:
java.lang.Error与java.lang.Exception,平常所说的异常指java.lang.Exception。


Throwable体系:

エラー:重大なエラーエラー(処理できないエラー)は、端末の病気のように事前に回避する必要があります。
例外:例外を示します。例外が発生した後、プログラマーはコードを使用してそれを修正し、プログラムを引き続き実行させることができます。それ
は風邪や虫垂炎のようなものです。

Throwable中的常用方法:

public void printStackTrace():例外の詳細情報を出力します。
例外のタイプ、例外の原因、および例外の場所が含まれます。PrintStackTraceは、開発段階とデバッグ段階で使用する必要があります。
public String getMessage():例外の理由を取得します。
ユーザーにプロンプ​​トが出されると、エラーの理由がプロンプトされます。
public String toString():例外のタイプと説明を取得します(使用されません)。

出现异常,不要紧张,把异常的简单类名,拷贝到API中去查。

## 1.3 异常分类

我们平常说的异常就是指Exception,因为这类异常一旦出现,我们就要对代码进行更正,修复程序。


异常(Exception)的分类:根据在编译时期还是运行时期去检查异常?

コンパイル中の例外:チェック例外。コンパイル時にチェックされ、例外が処理されない場合、コンパイルは失敗します。(異常な日付フォーマットなど)
実行時例外:実行時例外。ランタイム中に例外を確認します。コンパイル中、ランタイム例外はコンパイラによって検出されません(エラーは報告されません)。(例:異常な数学

## 1.4 异常的产生过程解析

先运行下面的程序,程序会产生一个数组索引越界异常ArrayIndexOfBoundsException。我们通过图解来解析下
异常产生的过程。

工具类

### 测试类

public class ArrayTools { //指定されたインデックスを使用して、指定された配列の要素を取得します。public static int getElement(int [] arr、int index){ int element = arr [index]; return element; } }






### 上述程序执行过程图解:

# 第二章 异常的处理

Java异常处理的五个关键字:try、catch、finally、throw、throws

## 2.1 抛出异常throw

### 在编写程序时,我们必须要考虑程序出现问题的情况。比如,在定义方法时,方法需要接受参数。那么,当调用方

### 法使用接受到的参数时,首先需要先对参数数据进行合法的判断,数据若不合法,就应该告诉调用者,传递合法的

### 数据进来。这时需要使用抛出异常的方式来告诉调用者。

在java中,提供了一个throw关键字,它用来抛出一个指定的异常对象。那么,抛出一个异常具体如何操作呢?

  1. 例外オブジェクトを作成します。いくつかのプロンプト情報をカプセル化します(情報は自分で書き込むことができます)。
  2. この例外オブジェクトを呼び出し元に通知する必要があります。見分け方は?この例外オブジェクトを呼び出し元に渡す方法は?
    これは、キーワードthrowで実行できます。例外オブジェクトをスローします。
    Throwは、メソッドで例外オブジェクトをスローし、例外オブジェクトを呼び出し元に渡し、現在のメソッドの実行を終了するために使用されます。
使用格式:

パブリッククラスExceptionDemo { public static void main(String [] args){ int [] arr = {34、12、67}; intnum = ArrayTools.getElement(arr、4)System.out.println(“ num =” + num); System.out.println( "over"); } }







### 例如:

学习完抛出异常的格式后,我们通过下面程序演示下throw的使用。

注:問題が発生すると、問題の説明クラスまたは例外がスローされます。つまり、問題がメソッドの呼び出し元
返されます。
では、発信者に対して何をすべきでしょうか?1つは処理をキャプチャすることで、もう1つは問題のステートメントについて話し続け、スローを使用
して処理宣言することです。

## 2.2 Objects非空判断

还记得我们学习过一个类Objects吗,曾经提到过它由一些静态的实用方法组成,这些方法是null-save(空指针安
全的)或null-tolerant(容忍空指针的),那么在它的源码中,对对象为null的值进行了抛出异常操作。

public static T requireNonNull(T obj):指定された参照オブジェクトがnullでないことを確認します。

查看源码发现这里对为null的进行了抛出异常操作:

新しい例外クラス名(パラメーター)をスローします。

throw new NullPointerException( "アクセスされるarr配列は存在しません");

新しいArrayIndexOutOfBoundsException( "インデックスは配列に存在せず、範囲外です。");

public class ThrowDemo { public static void main(String [] args){ //配列を作成int [] arr = { 2、4、52、2 }; //インデックスに従って対応する要素を検索int index = 4; int element = getElement(arr、index);





System.out.println(element);
System.out.println( "over");
}
/ *

  • index
    /
    public static int getElement(int [] arr、int index){ //インデックスが範囲外かどうかの判断if(index <0 || index> arr.length-1){ /



    条件が満たされているかどうかの判断、throwの実行により例外オブジェクトがスローされた後、メソッドは続行できなくなります。
    この時点で、現在のメソッドの実行が終了し、例外が呼び出し元に通知されます。現時点では、例外によって解決する必要があります。
    * /
    throw new ArrayIndexOutOfBoundsException( "デュード、コーナーマークが範囲外です~~~");
    }
    int element = arr [index];
    return element;
    }
    }

## 2.3 声明异常throws

声明异常:将问题标识出来,报告给调用者。如果方法内通过throw抛出了编译时异常,而没有捕获处理(稍后讲
解该方式),那么必须通过throws进行声明,让调用者去处理。

关键字throws运用于方法声明之上,用于表示当前方法不处理异常,而是提醒该方法的调用者来处理异常(抛出异常).

声明异常格式:

### 声明异常的代码演示:

throws用于进行异常类的声明,若该方法可能有多种异常情况产生,那么在throws后面可以写多个异常类,用逗
号隔开。

public static T requireNonNull(T obj){ if(obj == null)throw new NullPointerException(); objを返す; }



修飾子の戻り値のタイプメソッド名(パラメーター)は例外クラス名1、例外クラス名2 ... {}をスローします

public class ThrowsDemo { public static void main(String [] args)throws FileNotFoundException { read(“ a.txt”); }


//関数の定義時に問題が発生した場合は、呼び出し元に報告する必要があります。メソッドでthrowsキーワードを使用して宣言できます
public static void read(String path)throws FileNotFoundException { if(!path.equals( "a.txt")){//それがa.txtでない場合、このファイル// a.txtでない場合は、ファイルが存在しないというエラーが発生します。これは例外で、スローがスローされます。新しいFileNotFoundException( "File does not exist"); } } }





public class ThrowsDemo2 { public static void main(String [] args)throws IOException { read(“ a.txt”); }


public static void read(String path)throws FileNotFoundException、IOException { if(!path.equals( "a.txt")){//a.txtでない場合、このファイル// a.txtでない場合、ファイルはないと思います存在はエラー、つまり例外throw throw new FileNotFoundException( "File does not exist"); } if(!path.equals( "b.txt")){ throw new IOException(); } } }









## 2.4 捕获异常try...catch

### 如果异常出现的话,会立刻终止程序,所以我们得处理异常:

  1. このメソッドは処理しませんが、スローするように宣言します。これは、メソッドの呼び出し元(スロー)によって処理されます。
  2. メソッドでtry-catchブロックを使用して、例外を処理します。
try-catch的方式就是捕获异常。

例外をキャッチ:Javaは例外のターゲットステートメントをキャプチャし、指定された方法で例外を処理できます。

捕获异常语法如下:

try:该代码块中编写可能产生异常的代码。

catch:用来进行某种异常的捕获,实现对捕获到的异常进行处理。

注:try and catchは単独で使用することはできません。一緒に使用する必要があります。

演示如下:

### 如何获取异常信息:

Throwable类中定义了一些查看方法:

try { 例外を引き起こす可能性のあるコードを記述する} catch(例外タイプe){ 例外コードを処理する//ログを記録する/例外情報を出力する/例外をスローし続ける}




public class TryCatchDemo { public static void main(String [] args){ try {//例外が発生した場合、それを処理する方法が必要です。キャプチャまたは宣言します。read( "b.txt"); } catch(FileNotFoundException e){//括弧内に何を定義する必要がありますか?//試行でスローされる例外は、括弧で例外のタイプを定義しますSystem.out.println(e); } System.out.println( "over"); } / * *










  • 現在のメソッドとコンパイル時の例外には例外があります
    * /
    public static void read(String path)throws FileNotFoundException { if(!path.equals( "a.txt")){//それがa.txtファイルでない場合/ /それがa.txtでない場合、ファイルが存在しない、つまり例外がスローされて新しいFileNotFoundException( "file does not exist");がスローされるとエラーになると思います} } }






public String getMessage():例外と理由の説明情報を取得します(ユーザーにプロンプ​​トが出されると、エラーの理由がプロンプトされます。

public String toString():例外のタイプと説明を取得します(使用されません)。
public void printStackTrace():異常なトレーススタック情報を出力し、コンソールに出力します。

包含了异常的类型,异常的原因,还包括异常出现的位置,在开发和调试阶段,都得使用printStackTrace。

## 2.4 finally 代码块

finally:有一些特定的代码无论异常是否发生,都需要执行。另外,因为异常会引发程序跳转,导致有些语句执行
不到。而finally就是解决这个问题的,在finally代码块中存放的代码都是一定会被执行的。

什么时候的代码必须最终执行?

当我们在try语句块中打开了一些物理资源(磁盘文件/网络连接/数据库连接等),我们都得在使用完之后,最终关闭打开
的资源。

finally的语法:

try...catch....finally:自身需要处理异常,最终还得关闭资源。

注:最後に、単独で使用することはできません。

比如在我们之后学习的IO流中,当打开了一个关联文件的资源,最后程序不管结果如何,都需要把这个资源关闭
掉。

finally代码参考如下:

関連するJVM終了メソッドのみがtryまたはcatchで呼び出された場合、finallyは現時点では実行されません。そうでない場合、finallyは常に実行されます。

public class TryCatchDemo4 { public static void main(String [] args){ try { read( "a.txt"); } catch(FileNotFoundException e){ //キャッチはコンパイル時の例外であり、ランタイムですthrow new RuntimeException(e); } finally { System.out.println( "プログラムに関係なく、ここで実行されます。"); } System.out.println( "over"); } / * *












  • 現在のメソッドとコンパイル時の例外には例外があります
    * /
    public static void read(String path)throws FileNotFoundException { if(!path.equals( "a.txt")){//それがa.txtファイルでない場合/ /それがa.txtでない場合、ファイルが存在しない、つまり例外がスローされて新しいFileNotFoundException( "file does not exist");がスローされるとエラーになると思います} } }






## 2.5 异常注意事项

### 多个异常使用捕获又该如何处理呢?

### 1. 多个异常分别处理。

### 2. 多个异常一次捕获,多次处理。

### 3. 多个异常一次捕获一次处理。

### 一般我们是使用一次捕获多次处理方式,格式如下:

注:複数の例外を必要とするこの例外処理は、同じものをキャッチすることができず、親の複数の異常な
関係のキャッチが正常である場合と、上記のキャッチサブクラスの例外処理要件と、親クラスとで異なる場合があります。例外は以下のキャッチで処理されます。

実行時例外は、スローされると処理されない場合があります。捕獲もスロー宣言もしない。
最終的にreturnステートメントがある場合、この状況を回避するために、常にfinallyで結果を返します。

try { 例外が発生する可能性のあるコードを記述する} catch(exception type A e){tryでAタイプの例外が発生した場合は、catchを使用してキャッチします。例外を処理するためのコード//ログを記録/例外情報を出力/継続して例外をスローします} catch(Exception type B e){タイプBの例外がtryで発生したときに、catchを使用してキャッチします。例外を処理するためのコード//ログを記録/例外情報を出力/継続して例外をスローします}








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

### 常。

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

### 能声明抛出

# 第三章 自定义异常

## 3.1 概述

### 为什么需要自定义异常类:

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

在上述代码中,发现这些异常都是JDK内部定义好的,但是实际开发中也会出现很多异常,这些异常很可能在JDK中
没有定义过,例如年龄负数问题,考试成绩负数问题.那么能不能自己定义异常呢?

什么是自定义异常类:

在开发中根据自己业务的异常情况来定义异常类.

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

异常类如何定义:

  1. コンパイル時の例外のカスタマイズ:クラスをカスタマイズし、java.lang.Exceptionから継承します。
  2. ランタイム例外クラスをカスタマイズします:カスタムクラスで、java.lang.RuntimeExceptionから継承します。
## 3.2 自定义异常的练习

### 要求:我们模拟注册操作,如果用户名已存在,则抛出异常并提示:亲,该用户名已经被注册。

首先定义一个登陆异常类RegisterException:

### 模拟登陆操作,使用数组模拟数据库中存储的数据,并提供当前注册账号是否存在方法用于判断。

### // 业务逻辑异常

パブリッククラスRegisterExceptionは例外{ / **を拡張します

  • nullパラメータの構築
    * /
    public RegisterException(){ }

/ **
*

  • @paramメッセージは、異常なプロンプトを意味します
    * /
    public RegisterException(String message){ super(message); } }



# 第四章 多线程

### 我们在之前,学习的程序在没有跳转语句的前提下,都是由上至下依次执行,那现在想要设计一个程序,边打游戏

### 边听歌,怎么设计?

### 要解决上述问题,咱们得使用多进程或者多线程来解决.

## 4.1 并发与并行

### 并发:指两个或多个事件在同一个时间段内发生。

### 并行:指两个或多个事件在同一时刻发生(同时发生)。

public class Demo { //アカウントはシミュレーションデータベースに既に存在しますprivate static String [] names = {"bill"、 "hill"、 "jill"};

public static void main(String [] args){ // Callメソッドtry { //異常である可能性のあるコードcheckUsername( "nill"); System.out.println( "Registration successful"); //例外がない場合は、登録成功} catch(RegisterException e){ //例外を処理e.printStackTrace(); } }









//現在登録されているアカウントが存在するかどうかを判断します
//これはコンパイル時の例外であり、呼び出し側で処理する必要があるため、例外を宣言します
public static boolean checkUsername(String uname)throws LoginException { for(String name:names){ if(name.equals (uname)){//名前が含まれている場合は、ログイン例外をスローしますthrow new RegisterException( "Dear" + name + "has registered!"); } } return true; } }








### 在操作系统中,安装了多个程序,并发指的是在一段时间内宏观上有多个程序同时运行,这在单 CPU 系统中,每

### 一时刻只能有一道程序执行,即微观上这些程序是分时的交替运行,只不过是给人的感觉是同时运行,那是因为分

### 时交替运行的时间是非常短的。

### 而在多个 CPU 系统中,则这些可以并发执行的程序便可以分配到多个处理器上(CPU),实现多任务并行执行,

### 即利用每个处理器来处理一个可以并发执行的程序,这样多个程序便可以同时执行。目前电脑市场上说的多核

### CPU,便是多核处理器,核 越多,并行处理的程序越多,能大大的提高电脑运行的效率。

### 注意:单核处理器的计算机肯定是不能并行的处理多个任务的,只能是多个任务在单个CPU上并发运行。同

### 理,线程也是一样的,从宏观角度上理解线程是并行运行的,但是从微观角度上分析却是串行运行的,即一个

### 线程一个线程的去运行,当系统只有一个CPU时,线程会以某种顺序执行多个线程,我们把这种情况称之为

### 线程调度。

## 4.2 线程与进程

### 进程:是指一个内存中运行的应用程序,每个进程都有一个独立的内存空间,一个应用程序可以同时运行多

### 个进程;进程也是程序的一次执行过程,是系统运行程序的基本单位;系统运行一个程序即是一个进程从创

### 建、运行到消亡的过程。

### 线程:线程是进程中的一个执行单元,负责当前进程中程序的执行,一个进程中至少有一个线程。一个进程

### 中是可以有多个线程的,这个应用程序也可以称之为多线程程序。

### 简而言之:一个程序运行后至少有一个进程,一个进程中可以包含多个线程

### 我们可以再电脑底部任务栏,右键----->打开任务管理器,可以查看当前任务的进程:

### 进程


### 线程


### 线程调度:

### 分时调度

### 所有线程轮流使用 CPU 的使用权,平均分配每个线程占用 CPU 的时间。

### 抢占式调度

優先度の高いスレッドを優先してCPUを使用します。スレッドの優先度が同じである場合は、ランダムに選択されます(スレッドのランダム性)。Javaは
プリエンプティブスケジューリングを使用します。
スレッドの優先順位を設定する


### 抢占式调度详解

### 大部分操作系统都支持多进程并发运行,现在的操作系统几乎都支持同时运行多个程序。比如:现在我

们上课一边使用编辑器,一边使用录屏软件,同时还开着画图板,dos窗口等软件。此时,这些程序是
在同时运行,”感觉这些软件好像在同一时刻运行着“。

实际上,CPU(中央处理器)使用抢占式调度模式在多个线程间进行着高速的切换。对于CPU的一个核而
言,某个时刻,只能执行一个线程,而 CPU的在多个线程间切换速度相对我们的感觉要快,看上去就是
在同一时刻运行。 其实,多线程程序并不能提高程序的运行速度,但能够提高程序运行效率,让CPU的
使用率更高。


## 4.3 创建线程类

Java使用java.lang.Thread类代表线程,所有的线程对象都必须是Thread类或其子类的实例。每个线程的作用是
完成一定的任务,实际上就是执行一段程序流即一段顺序执行的代码。Java使用线程执行体来代表这段程序流。
Java中通过继承Thread类来创建并启动多线程的步骤如下:

  1. Threadクラスのサブクラスを定義し、このクラスのrun()メソッドを書き換えます。run()メソッドのメソッド本体は、スレッドが完了する必要のあるタスクを表すため、
    run()メソッドはスレッド実行本体と呼ばれます。
  2. Threadサブクラスのインスタンスを作成します。つまり、スレッドオブジェクトを作成します。
  3. スレッドを開始するには、スレッドオブジェクトのstart()メソッドを呼び出します。
代码如下:

测试类:

### 自定义线程类:

public class Demo01 { public static void main(String [] args){ //カスタムスレッドオブジェクトを作成しますMyThread mt = new MyThread( "New thread!"); //新しいスレッドを開始しますmt.start(); // In mainメソッドforループを実行します(int i = 0; i <10; i ++){ System.out.println( "main thread!" + i); } } }










パブリッククラスMyThread extends Thread { //指定されたスレッド名の構築メソッドを定義しますpublic MyThread(String name){ //親クラスのStringパラメータの構築メソッドを呼び出し、スレッドの名前を指定しますsuper(name); } / **






### /**

 * 重写run方法,完成该线程执行的逻辑
 */
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(getName()+":正在执行!"+i);
}
}
}

おすすめ

転載: blog.csdn.net/weixin_43419256/article/details/108230713