「例外」というトピックに出会ったとき、多くの疑問が生じました。すべてがどのように機能するかを詳しく理解するために、インターネットのさまざまな場所で答えを探す必要がありました。その結果、この現象に遭遇したばかりの初心者にとってよりわかりやすいかもしれない私なりの説明をまとめました。 コンピュータにおける割り込みは、即時応答を必要とするイベントが発生していることをプロセッサに伝える受信信号です。割り込み信号は、実行中のプログラムを少し後で継続できるようにプロセッサに一時停止を要求します。つまり、コンピュータはプログラムの実行に関連するすべての情報を記憶する必要があります。このような中断は、致命的ではないにしても、一時的なものです。このような中断は、プログラム コードまたは一部のハードウェア機能 (たとえば、キーボードのキーを押すだけ、コンピューターの電源を自動的にオフにするタイマーなど) によって引き起こされる可能性があります。割り込みの数は、特定のプロセッサの製品に組み込まれている特定の数に制限されています。つまり、特別な通信「チャネル」がこれに割り当てられており、他のすべてのプロセスをバイパスしてプロセッサにアクセスできます。 実行中のプログラム コードでエラーが発生した場合 (たとえば、ゼロによる除算が発生した場合)、割り込みも自動的に生成されます。このような中断は伝統的にトラップまたは例外と呼ばれています。このような場合、「例外がスローされました」と言うのが通例です。つまり、例外がトリガーされたか、例外がスローされました (スローされた)、つまり割り込みの要求です。「何をすればいいですか?」という質問とともに、プロセッサに送信されます。この時点で、プロセッサは動作を停止し、停止した時点、つまり実行する必要がある情報である次のセルのクラスタを記憶します。実行された命令と実行されなかった命令のチェーン全体が記憶されます。その後、プロセッサは、そのようなエラーが発生した場合のアクションのためにメモリから命令を読み取ります。この命令に従って、特定のクラスターに新しい値を入力したり、アクションのチェーンや新しいサイクル (リターンやループ サイクルなど) を追加したりすることができます。つまり、エラーに応じて、以前に設定されたダウン命令が実行されます。コンピューター システム自体には多くの自動割り込みが組み込まれており、コンピューター上で実行中のプロセスを制御したり、アラームの設定を実行したり、受信する外部信号やさまざまなデータ コンバーターを収集したりするために、一定の時間が経過するとトリガーされます。多数の割り込みが発生すると、さまざまな理由でシステムが完全に「ハング」する可能性があることを覚えておく価値があります。プログラム コードにエラーが発生すると、プロセッサは自動的に中断を引き起こし、プロセッサは定められた命令に従って処理を試みます。ただし、すべての割り込みが割り込みを処理できるように設計されているわけではありません。また、単純にアプリケーションをクラッシュさせるなど、私たちに合わない手順が生成される場合もあります。したがって、プログラミングでは、プログラマがエラーの可能性を認識したコードの特定のセクションに対して独自の割り込みを構成することができます。この場合、エラーはプログラム内で処理され、処理命令のためにプロセッサに連絡することはありません。このようなブロックの定義は、「例外」オブジェクトを作成することによって整理されます。このオブジェクトはブロック内に自動的に作成されます
try-catch
。ブロックで>try
エラーの有無がチェックされ、エラーがある場合、プログラムはブロックに進みcatch
、そこでエラーを防止または平準化するためのアクションが実行されます。たとえば、キーボードから数値を入力した場合、後で加算および減算する必要がありますが、キーボードから文字を入力すると、それらを数値で加算することができなくなります(これら 2 つの変数の合計を文字 S で示します)。したがって、チームとして、try
数字を含む番号 A を文字を含む番号 B に加算できるかどうか (つまり、S = A + B) を確認する必要があります。これが不可能であり、不可能な場合は、確実です。エラーが発生せず、「何をすべきか?」という質問を伴う新しい割り込みがプロセッサに飛ばされないように、対策を講じる必要があります。プログラムに例外がない場合、その実行はプロセッサによって中断されます。例外があり、それが command によって「キャッチ」された場合try
、制御は command に渡されcatch
、代替の解決策を設定できます。たとえば、これら 2 つの数値を加算するのではなく、S = A を設定します。
int a = 4;
String b = “hello”;
int S = 0;
try {
S = a + b;
int r = 1;
} catch (Exception igogo1) {
S = a;
}
return S;
/* 文字列「int r = 1;」エラーが発生したため実行されず、プログラムは作業を例外ハンドラー (キャッチ ブロック*/) に直接リダイレクトします。 したがって、例外の存在は、プロセッサ レベルで問題をスローすることなくプログラム内で問題を解決する機会となります。try
「例外」オブジェクトは、エラーが検出されたときにブロック内に自動的に作成され、エラーの種類の値が含まれます。これを「OurException」と呼びます。これは、特定のエラーの説明を含む特定のケースに対応します。Java 言語の作成者は、典型的なエラーの特定のリストと、それらを修正するための典型的なオプションを事前に作成しました。つまり、Java には、発生したエラーを処理するために利用できるExceptions の特定のライブラリがあります。自分で処理コードを記述する必要はありません。そのため、OurException はすでに誰かが記述している可能性が高く、障害が発生する可能性があるコードを処理するためにプログラムにこれらの例外のどれを挿入するかの名前を知る必要があるだけです。間違ってライブラリから間違った例外を選択した場合、ハンドラーはそれを「キャッチ」せず、エラーはプログラム内で解決策を見つけられず、リクエストはプロセッサに送信されます。しかし、怠け者にも方法はあります。ライブラリから必要な例外の名前がわからない場合は、上記の例のように、 「 Exception 」という名前の一般的な例外を取得できます。この例外はあらゆる種類のエラーを処理できますが、ログに記録できるインシデントに関する特定の情報を提供することはできません。以前に書き込まれた例外のライブラリは、チェックされた例外とチェックされていない例外で構成されます。チェック可能なものは、プログラムの作業を中断せずに修正できるものです。つまり、存在しないフォルダー内のファイルを開こうとすると、システムがそれを通知し、ファイルをドロップできます。目的のフォルダーに移動し、プログラムを続行します。つまり、実際には、割り込み要求がプロセッサに送信されましたが、「この問題について何をすべきか探してください?!?!」という質問はありませんでした。私たちは、私たち自身が検出した割り込みを既成の命令とともに送信し、プロセッサーがそれを処理してプログラムの実行を継続しました。チェックを外すと、修正できないエラーが表示され、プログラムは完了前に閉じられます。つまり、プロセッサに割り込み要求が送信されます。いずれの場合もプログラムの実行が中断されます。このような例外をプログラムに記述する唯一のポイントは、何が起こったのかをユーザーに理解させることです。なぜなら、この中断を捕捉すると、プログラムがクラッシュしたことによる情報メッセージを画面に表示できるからです。このような中断を捕捉する 2 番目の理由は、後で分析するためにログに記録できることです (ハッキングされたが、少なくともどこで行われたかはわかります)。このようなライブラリが存在するため、それらを忘れずに含める必要があります。(ライブラリに関するチェック済み例外とチェックなし例外のリストは、たとえばここにあります) どのライブラリを含めるべきか正確にわからない場合、またはいくつかのエラー オプションがある場合は、catch
必要な例外をいくつかリストすることができます。リストにある場合は、システム自体が正しいハンドラーを選択します。特定の例外の代わりに、前のブロックで処理されなかった あらゆる種類の例外を処理できる一般的な「例外」を作成できます。
int a = 4;
String b = “hello”;
int S = 0;
try {
S = a + b;
int r = 1;
}
catch(NullPointerException blabla2) {
System.out.println("Exception handling code for the NullPointerException.");
}
catch (ArithmeticException ex1) {
S = a;
}
catch(Exception uups1) {
System.out.println("Exception occured");
}
return S;
ブロックがある場合、try
例外が自動的に作成されます。ある時点で例外を強制する必要がある場合は、このコマンドが使用されますthrow
。つまり、独立してオブジェクトを作成しますnew throw
...その後、プログラムは作業を停止し、プロセッサに割り込み要求を送信し、プログラムセクションに転送されcatch
、そこからさらなるアクションの指示を取得しようとします。Exception を手動で作成することで、ライブラリからその特定のタイプを指定できます。
throw new ArithmeticException("Access denied - You must be at least 18 years old.");
catch
次に、ハンドラーはこの特定の例外を持つ ブロックを検索します。プログラム全体をあらゆる面から検索しますcatch
。例外処理コマンドの後はthrow
、ブロック内のプログラム コードを除き、残りのプログラム コードはすべて実行されませんcatch
。ハンドラーがプログラム内に見つからない場合、プロセッサーは「何をするか自分で決めてください」という質問をされ、プログラムが中断されます。...の呼び出しは、ブロックの new throw
内側と外側の両方 (プログラムのどこでも) 行うことができます。>try
try {
/* функция or действие, в котором есть сомнения. То есть: «попробуй выполнить это, а если не получится, а, если не получится, запускай режим исключения» */
throw new CallForException(); /* Назначаем исключение, которое будет работать в случае наличия ошибки в функции, описанной выше. Здесь исключение «CallForException» - берется из библиотеки существующих исключений */
} catch (CallForException ee1) {
/* Корректируем ошибку, чтобы программа не «отвалилась» or выводим сообщение об ошибке or что-то ещё */
} finally {
/* этот блок работает всегда независимо от того была ошибка or нет. А если была, то сработало ли решение в catch or нет */
/* часто используется для подчистки хвостов, например, для закрытия запущенного file or базы данных */
/* в ряде случаев блок catch вообще может быть опущен и оставлен только блок finally и наоборот finally может быть опущен и оставлен только catch */
/* Не допускается использование этого блока в ряде случаев, например, когда функция System.exit() запущена or другие системные Исключения, типа «отключение электроэнергии» и т.п. */
}
例外の通知
誰かが以前に作成したメソッドには、例外のスローが含まれている場合があります。念のため、コードを書いたプログラマーは、自分が書いたメソッドでエラーが発生する可能性があることを後続のプログラマーに警告しました。したがって、たとえば、以下で説明するファイル作成方法では、ファイルの作成時にエラーが発生する可能性がある (指定されたパスにファイルがない) と規定されており、これはエラー ハンドラーが必要になることを意味します。public void createFile(String path, String text) throws IOException {
FileWriter writer = new FileWriter(path, true);
writer.write(text);
writer.close();
}
しかし同時に、ハンドラー自体がありません。これは、通常モードでプログラム内に記述されたメソッドを単純に呼び出すことができないことを意味します。次に、エラー ハンドラーを作成し、ブロック内でこのメソッドを呼び出す必要がありますtry
。
String filePath = "hello.txt";
String text = "Hello World";
try {
createFile(filePath, text);
} catch (IOException ex) {
System.err.println("Error creating file: " + ex);
}
ネイティブ例外
既存のライブラリでは不十分な場合は、特定のエラーを処理する独自の例外を作成することができます。これを行うには、Exception クラスを継承するクラスを作成するだけです。public class StudentNotFoundException extends Exception {
public StudentNotFoundException (String message) {
super(message);
}
}
独自の例外を作成する場合は、次の 2 つのルールに留意する必要があります。
- クラス名は「Exception」で終わる必要があります
- このクラスには、例外問題の詳細を記述する文字列変数を含むコンストラクターが含まれている必要があります。コンストラクターでは、スーパー コンストラクターが呼び出され、メッセージが渡されます。
public class StudentManager {
public Student find(String studentID) throws StudentNotFoundException {
if (studentID.equals("123456")) {
return new Student();
} else {
throw new StudentNotFoundException(
"Could not find student with ID " + studentID);
}
}
}
この例外は次のコードでキャッチします。
public class StudentTest {
public static void main(String[] args) {
StudentManager manager = new StudentManager();
try {
Student student = manager.find("0000001");
} catch (StudentNotFoundException ex) {
System.err.print(ex);
}
}
}
プログラムの実行結果は次のようになります: StudentNotFoundException: ID 0000001 の学生が見つかりませんでした
GO TO FULL VERSION