JavaRush /Java Blog /Random-JA /コーヒーブレイク#220。Java で例外を修正する方法 - 詳細ガイド

コーヒーブレイク#220。Java で例外を修正する方法 - 詳細ガイド

Random-JA グループに公開済み
出典: JavaTechOnline このチュートリアルは、Java の一般的な例外を修正する方法を学習するのに役立ちます。理論に加えて、そのような問題を解決するためのコード例も表示されます。 コーヒーブレイク#220。 Java で例外を修正する方法 - 詳細ガイド - 1他のプログラミング言語と同様に、Java 開発者はコードを作成するときにエラーや例外が発生することがあります。例外が発生すると作業時間がかかるため、例外を真剣に受け止める必要があります。ただし、少しの知識があれば、これらの問題のほとんどを迅速に解決できます。それでは、Java で一般的な例外を修正する方法を学びましょう。

Java で例外を回避するための一般的なガイドライン

Java で例外がスローされないようにするには、次のコーディング ガイドラインを理解し、従うことが重要です。
  1. ユーザー入力をコードで使用する前に、必ず検証してください。
  2. 特定のシナリオに何が適しているかに応じて、try-catchthrowsthrow tablesを使用します。
  3. 処理やエラーに関するコード内のメッセージを無視しないでください。これは、問題を特定して修正するのに役立ちます。
  4. デバッグ目的で例外を必ずログに記録してください。ロガー メッセージを使用すると、問題の特定に役立ちます。
  5. コーディングのベスト プラクティスに従って例外を回避し、コードを徹底的にテストします。
  6. API の依存関係を更新して、ライブラリとフレームワークの最新かつ最も安定したバージョンを使用していることを確認します。
  7. 必要なツールとテスト フレームワークを使用して、例外が発生する前にコード内の潜在的な問題を特定します。
  8. アプリケーションのパフォーマンスとログを監視して、問題を迅速に特定して解決します。
  9. セキュリティのベスト プラクティスを常に最新の状態に保ち、コードが安全であり、潜在的な攻撃から保護されていることを確認します。
  10. 他の開発者が理解しやすく、保守しやすいように、コードとその例外を徹底的に文書化します。

Java で最も一般的な例外のリスト

Java にはかなり長い例外リストがあります。最も一般的なものをいくつか見てみましょう。

NullPointerException

NullPointerException は、 RuntimeException例外の一種です。これは、NULL 値を持つ参照変数を使用しようとすると発生します。これは、値がnullのオブジェクトまたは変数を指していることを意味します。このようなエラーは、メソッドを呼び出したり、初期化されていないオブジェクトのフィールドにアクセスしようとしたり、それを処理しないメソッドにパラメータとしてnullを渡したときに発生する可能性があります。NullPointerException がスローされないようにするには、 ==演算子を使用して参照変数が null かどうかを確認します。この場合、null の場合を正しく処理する必要があります。あるいは、(可能な場合は) 変数をデフォルト値に初期化して、null 参照が発生しないようにすることもできます。NullPointerExceptionを回避するもう 1 つの方法は、Optionalクラスを使用することです。Java では、Optional は、null 以外の値を含む場合も含まれない場合もあるコンテナ オブジェクトです。これは、null 値を使用して値の不在を表すのと同様に、値の存在または不在を表すために使用されます。プログラマがOptionalオブジェクトの空の値にアクセスしようとすると、プログラムはNullPointerExceptionをスローせず、代わりに空のOptionalオブジェクトを返します。つまり、 Optional は、プログラマに値が欠落している場合の処理​​を強制するため、 NullPointerException を回避するのに役立ちます

IndexOutOfBoundsException

IndexOutOfBoundsException は、配列またはコレクションへのアクセスに使用されるインデックスが負であるか、配列またはコレクションのサイズ以上である場合にスローされる実行時例外です。この例外の発生を防ぐには、配列またはコレクションへのアクセスに使用されるインデックスがその境界内にあること、つまり、インデックスが 0 以上で配列またはコレクションのサイズ未満であることを確認する必要があります。

ArrayIndexOutOfBoundsException

ArrayIndexOutOfBoundsException は、無効なインデックスにある配列にアクセスしようとするとスローされるIndexOutOfBoundsExceptionの一種です。Java では、配列インデックスは0で始まりlength()-1で終わります。length()は配列内の要素の数です。この範囲外のインデックスにある要素にアクセスしようとすると、Java はArrayIndexOutOfBoundsExceptionをスローします。ArrayIndexOutOfBoundsExceptionが発生した場合は、コードを見直して、配列内の要素にアクセスするときに正しいインデックスを使用していることを確認する必要があります。

StringIndexOutOfBoundsException

StringIndexOutOfBoundsException は、無効なインデックスを持つ文字列内の文字にアクセスしようとするとスローされるIndexOutOfBoundsExceptionタイプです。前のArrayIndexOutOfBoundsExceptionと同様に、Java では文字列のインデックスは0から始まりlength()-1で終わることに注意してください。ここで、length()は文字列内の文字数です。この範囲外のインデックスにある文字にアクセスしようとすると、StringIndexOutOfBoundsException が発生する可能性があります。StringIndexOutOfBoundsExceptionが発生した場合は、コードを見直して、文字列内の文字にアクセスするときに正しいインデックスを使用していることを確認する必要があります。

クラスキャスト例外

この例外は、オブジェクトを実際の型と互換性のない型にキャストしようとしたときに発生します。このような問題を解決するには、Java プログラムがオブジェクトをインスタンスであるクラスにのみキャストしようとするようにすることが重要です。キャストを適用する前に、 instanceof演算子を使用してオブジェクトの型を確認できます。

IllegalArgumentException

IllegalArgumentException は、メソッドが不正な引数または不適切な引数を指定して呼び出された場合にスローされるRuntimeExceptionの一種です。つまり、このエラーは、予期された範囲外の引数、または予期された形式や構造を持たない引数を指定してメソッドが呼び出された場合に発生する可能性があります。たとえば、メソッドでは引数として正の数値が必要ですが、無効な入力である負の数値を指定します。IllegalArgumentException が発生した場合は、コードをチェックして、有効かつ適切な引数を指定してメソッドを呼び出しているかどうかを確認する必要があります。

IllegalStateException

IllegalStateException は、オブジェクトが実行中の操作にとって不適切な状態にある場合にスローされるRuntimeExceptionの一種です。これは、期待された状態にないオブジェクトに対してメソッドが呼び出された場合に発生する可能性があります。たとえば、データベース接続オブジェクトを作成して閉じた場合です。次に、閉じた接続でStatementオブジェクトを作成しようとすると、 createStatement()メソッドには開いた接続が必要であるため、IllegalStateExceptionがスローされます。IllegalStateException が発生した場合は、コードを見直して、適切な状態にあるオブジェクトのメソッドを呼び出していることを確認する必要があります。

UnsupportedOperationException

UnsupportedOperationException は、オブジェクトに対してサポートされていない操作を実行しようとするとスローされるRuntimeExceptionタイプです。このエラーは、オブジェクトによって実装されていないメソッド、またはオブジェクトによってサポートされていないメソッドを呼び出したときに発生する可能性があります。例外がスローされないようにするには、オブジェクトでサポートされていない操作を呼び出すべきではありません。コードを見直して、操作をサポートするオブジェクトのメソッドを呼び出していることを確認する必要があります。

算術例外

ArithmeticException は、算術演算によって無効な結果が生成された場合にスローされるRuntimeExceptionの一種です。この例外は、無効な引数または無効な引数を使用して算術演算を実行しようとすると発生する可能性があります。たとえば、ゼロで除算しようとしている場合です。この問題を解決するには、算術演算を実行する前に入力検証を実行し、引数が必要な条件を満たしていることを確認します。

セキュリティ例外

SecurityException は、プログラムの実行中にセキュリティ違反が発生した場合にスローされるRuntimeExceptionの一種です。このエラーは、プログラムがセキュリティ ポリシーで許可されていない操作を実行しようとすると発生することがあります。この問題を解決するには、リソースにアクセスし、特定の権限を持つ操作を実行できることを確認する必要があります。

NumberFormatException

NumberFormatException は、文字列を数値形式に変換するメソッドが呼び出されたときに、文字列が適切な形式ではない場合にスローされるRuntimeExceptionの一種です。この問題を解決するには、変換を試みる前に、まずユーザーの入力を検証する必要があります。また、コードをチェックして、ターゲットの数値型に適切にフォーマットされた文字列を変換しようとしていることを確認してください。

中断された例外

InterruptedException は、スレッドが何らかのイベントを待機、スリープ、またはブロックしており、そのイベントが別のスレッドによって中断された場合にスローされるチェック例外です。このエラーは、スレッドが入力を待機しているとき、ロックを解放しているとき、またはその他の操作を完了しているときに、別のスレッドが待機中のスレッドに割り込んだときに発生する可能性があります。この問題を解決するには、InterruptedException をキャッチし、リソースをクリーンアップするか、スレッドを停止するか、その他の適切なアクションを実行して応答します。InterruptedExceptionが発生した場合は、コードをチェックして、スレッドの割り込みが正しく処理されていることを確認する必要があります。

ファイルが見つかりません例外

FileNotFoundException は、指定された場所に存在しないファイル、または見つからないファイルにプログラムがアクセスしようとしたときにスローされるチェック例外です。ファイルのスペルが間違っていたり、移動または削除されたり、プログラムがファイルにアクセスするために必要なアクセス許可を持っていない場合でも、このメッセージが表示されることがあります。このエラーを修正するには、入力検証を実行して、ファイル パスが正しいこと、およびファイルにアクセスするために必要な権限がプログラムにあることを確認します。

IO例外

IOExceptionは Java のチェック例外で、ファイルまたはネットワーク ソケットの読み取りまたは書き込みなどの入出力操作の実行中に発生したエラーを表します。この問題は、指定されたファイルが見つからないかアクセスできない、ネットワーク エラー、権限が不十分であるなど、さまざまな理由で発生する可能性があります。この問題を解決するには、エラー メッセージの確認、 try-catchを使用した例外の処理、リソースの終了、ファイルのアクセス許可の確認など、 いくつかのアクションを実行する必要があります。

NoSuchMethodException

NoSuchMethodException は、クラスに存在しないメソッドを呼び出そうとしたときに実行時にスローされる例外です。この例外は通常、 Class.getMethod()またはClass.getDeclaredMethod()を使用してメソッドを呼び出し、指定されたメソッド名がクラスまたはインターフェイスで見つからない場合に発生します。java.lang.reflect.Methodクラスを使用してメソッドを呼び出そうとしたときに、指定されたメソッド名がオブジェクトに存在しない場合にも例外が発生することがあります。この例外を回避するには、正しいメソッド シグネチャとアクセス指定子を使用して有効なメソッドを呼び出すようにしてください。

NoSuchFieldException

NoSuchFieldException は、クラスにないフィールドにアクセスしようとしたときに発生する実行時例外です。この例外は通常、 Class.getField()またはClass.getDeclaredField()を使用してメソッドを呼び出し、指定されたフィールド名がクラスまたはインターフェイスで見つからない場合に発生します。さらに、 java.lang.reflect.Fieldクラスを使用してフィールドにアクセスしようとしていて、指定されたフィールド名がオブジェクトに存在しない場合にも呼び出すことができます。この例外を回避するには、正しい名前とアクセス修飾子を使用して有効なフィールドにアクセスしていることを確認してください。プライベート フィールドにアクセスする場合は、getField ()メソッドの代わりにgetDeclaredField()メソッドを必ず使用してください。

不正アクセス例外

IllegalAccessException は、クラス内のフィールドまたはメソッドにアクセスしようとしたが、必要なアクセス権がない場合に発生する実行時例外です。この例外は通常、クラスの外部からプライベート フィールドまたはメソッドにアクセスしようとしたとき、または元のクラスのサブクラスではないクラスから保護されたフィールドまたはメソッドにアクセスしようとしたときに発生します。また、 java.lang.reflect.AccessibleObjectクラスによって使用不可としてマークされているフィールドまたはメソッドにアクセスしようとするときに呼び出すこともできます。この問題を回避するには、アクセスしようとしているフィールドまたはメソッドに対して必要な権限があることを確認してください。フィールドまたはメソッドがプライベートである場合、リフレクションを使用し、 (アクセスするには) AccessibleObjectをtrueに設定する必要がある場合があります。ただし、リフレクションを使用してプライベート フィールドまたはメソッドにアクセスする場合は、カプセル化が破壊され、クラスの整合性が損なわれる可能性があるため注意してください。

検証エラー

VerifyError は、 LinkageError のサブクラスである実行時エラーです。これは、Java 仮想マシン (JVM) が特定の検証ルールに違反するクラス ファイルを検出したときに発生します。Java クラスがコンパイルされるとき、コンパイラは、バイトコードがタイプ セーフやスタックとローカル変数の適切な使用など、特定のルールと制限に従っているかどうかをチェックします。クラス ファイルがこれらのルールに違反している場合、JVM は実行時にクラスをロードしてチェックするときにVerifyError をスローします。VerifyErrorを回避するには、コードが Java 言語の正しい構文とセマンティクスに従っていることを確認してください。VerifyError が発生した場合は、コードをチェックして、コードが有効であること、および Java バイトコード検証ルールに違反していないことを確認する必要があります。

メモリ不足エラー

OutOfMemoryError は、実行時に解決できない重大な問題を引き起こすThrowableタイプであるError のサブクラスです。Java 8 にはガベージ コレクションとメモリ管理におけるいくつかの改善が含まれていますが、アプリケーションがメモリを多量に使用している場合、またはメモリ使用量の管理が正しくない場合には、依然としてOutOfMemoryErrorが発生する可能性があります。OutOfMemoryErrorを回避するには、Java アプリケーションでメモリ使用量を適切に管理する必要があります。これには、メモリを効率的に使用するデータ構造とアルゴリズムを使用し、不必要なオブジェクトの作成を回避し、不要になったオブジェクトを適切に削除することが含まれます。さらに、 Java プログラムの実行時に -Xmxフラグを使用すると、JVM の最大ヒープ サイズを増やすことができます。

スタックオーバーフローエラー

StackOverflowError は、プログラムに必要なスタック サイズが、プログラムに割り当てられたメモリ量を超えた場合に発生するエラーの一種です。これは、プログラムがネストされたメソッドを呼び出す場合、またはメソッドがそれ自体を再帰的に何度も呼び出し、その結果無限ループが発生する場合に発生することがあります。Java 仮想マシン (JVM) は、メソッド呼び出しとローカル変数を追跡するために使用される実行スタックに固定量のメモリを割り当てます。スタックがオーバーフローすると、JVM はStackOverflowErrorをスローします。StackOverflowErrorを回避するには、Java プログラムが再帰とメソッド呼び出しを適切に使用していることを確認することが重要です。StackOverflowErrorが発生した場合は、 Java プログラムの実行時に -Xssフラグを使用してスタック サイズを増やしてみてください。

呼び出しターゲット例外

InvocationTargetException は、Java リフレクション メカニズムによってスローされるチェック例外です。これはjava.lang.reflect.InvocationTargetExceptionパッケージの一部であり、メソッドまたはコンストラクターの呼び出し中に例外が発生したことを示すために使用されます。Java リフレクション メカニズムを使用してメソッドまたはコンストラクターが呼び出される場合、java.lang.reflect.Method クラスまたはjava.lang.reflect.Constructorクラスのinvoke()メソッドが呼び出されます。呼び出されたメソッドまたはコンストラクターが例外をスローした場合、invoke()メソッドはそれをキャッチし、InvocationTargetExceptionでラップします。この例外は、 invoke()メソッドの呼び出し元に渡されます。InvocationTargetExceptionを修正するには、これをキャッチし、 getCause()メソッドを使用して根本原因の例外を取得し、それに応じて根本原因の例外を処理する必要があります。根本原因はチェック例外または実行時例外である可能性があるため、必ず正しく処理してください。

Java で最も一般的な例外を修正する方法

NullPointerExceptionを修正する方法

シナリオ:値がnullであるオブジェクトにアクセスするメソッドがあります。
String title= null;
System.out.println(title.length()); // Это вызовет NullPointerException
解決策 #1:使用する前にオブジェクトが null かどうかを確認します。
if(title!= null) {
   System.out.println(title.length());
} else {
   System.out.println("title is null");
}
解決策 2: NullPointerException を回避するには、Optional を使用します。
Optional<String> optionalTitle = Optional.ofNullable(getTitle());
if (optionalTitle.isPresent()) {
   String title= optionalTitle.get();
   System.out.println("Title: " + title);
} else {
   System.out.println("Title is not available.");
}

ArrayIndexOutOfBoundsException を修正する方法

シナリオ:配列の境界外にあるインデックスにある配列にアクセスしようとしています。
int[] numbers = {4, 5, 6};
System.out.println(numbers[3]);   // Это вызовет ArrayIndexOutOfBoundsException
解決策:配列にアクセスする前に配列の長さをチェックし、有効なインデックスを使用していることを確認してください。
int[] numbers = {4, 5, 6};
if (numbers.length > 3) {
   System.out.println(numbers[3]);
} else {
   System.out.println("ArrayIndexOutOfBoundsException: Please use valid indexes of the Array");
}

ClassCastExceptionを修正する方法

シナリオ:オブジェクトを実際の型と互換性のない型にキャストしようとしています。
Object obj = "Java Exception";
Integer number = (Integer) obj; // Это вызовет ClassCastException
解決策:互換性のある型にのみオブジェクトをキャストするようにしてください。
Object obj = "Java Exception";
if(obj instanceof Integer) {
   Integer number = (Integer) obj;
   System.out.println(number);
} else {
   System.out.println("Object cannot caste to Integer");
}

IllegalArgumentExceptionを修正する方法

シナリオ:無効な引数をメソッドに渡しました。
public void printNumber(int number) {
   if(number <= 0) {
      throw new IllegalArgumentException("You cannot pass a negative number or zero");
   }
   System.out.println(number);
}

printNumber(-1); // Это вызовет IllegalArgumentException
解決策:有効な引数をメソッドに渡していることを確認してください。この場合、正の数を渡します。
printNumber(1); //  Это успешно напечатает 1.

IllegalStateExceptionを修正する方法

シナリオ:オブジェクトは無効な状態にあります。
public class Bike {

   private Boolean isStarted;

   public void start() {
      if(isStarted) {
        throw new IllegalStateException("Bike is already started");
      }
      isStarted = true;
      System.out.println("Bike started");
   }
}

Bike bike= new Bike();
bike.start();
bike.start(); // Это вызовет IllegalStateException потому что bike is already started
解決策:オブジェクトの状態が正しく維持されていることを確認してください。
Bike bike= new Bike();
bike.start();

UnsupportedOperationExceptionを修正する方法

シナリオ:オブジェクトでサポートされていない操作を使用します。よくある例の 1 つは、不変コレクションに対してRemove()オペレーションを使用すると、 UnsupportedOperationException例外が発生する可能性があります。
List<String> list = Arrays.asList("Java", "Angular", "Spring");
list.add("Python"); // Это вызовет UnsupportedOperationException
Arrays.asList()メソッドは不変のリストを返す ため、要素の追加や削除はサポートされていません。解決策:オブジェクトに対してサポートされている操作のみを呼び出すようにしてください。
List<String> list = new ArrayList<>(Arrays.asList("Java", "Angular" "Spring"));
list.add("Python");
System.out.println(list);

ArithmeticException を修正する方法

シナリオ #1:小数の結果を生成する整数の除算演算を実行しようとしています。
int i = 10;
int j = 4;
int k = i/j; // Это вызовет исключение ArithmeticException: целочисленное деление будет дробным
ここで、除算演算の結果は 2.5 であり、これは小数値です。整数には小数値を格納できないため、ArithmeticExceptionがスローされます。 解決策:この例外を回避するには、 doubleなどの小数値をサポートするデータ型を使用して、除算演算の結果を保存します。以下に例を示します。
int i = 10;
int j = 4;
double k = (double) i/j;
シナリオ #2:ゼロで除算しようとすると、この例外が発生します。これは最も一般的なシナリオです。
int i = 4;
int j = 0;
int k = i/j; // Это вызовет исключение ArithmeticException: нельзя делить на ноль
解決策:ゼロ除算を正しく処理します。たとえば、以下のコードは正しい処理を示しています。
int i = 4;
int j = 0;
if(j != 0) {
int k = i/j;
System.out.println(k);
} else {
System.out.println("ArithmeticException: Cannot divide by zero");
}

IndexOutOfBoundsException を修正する方法

シナリオ:コレクション外のインデックスを使用してコレクションにアクセスしようとしています。
List<String> list = Arrays.asList("Apple", "Papaya", "Mango");
System.out.println(list.get(3)); // Это вызовет IndexOutOfBoundsException
解決策:コレクションにアクセスする前にコレクションのサイズを確認し、有効なインデックスを使用していることを確認してください。
List<String> list = Arrays.asList("Apple", "Papaya", "Mango");
if (list.size() > 3) {
   System.out.println(list.get(3));
} else {
   System.out.println("You are using the Index which is out of bounds");
}

IOExceptionを修正する方法

シナリオ:ファイルにアクセスできないため、入出力操作が失敗します。
try {
   File inputFile = new FileReader("pqr.txt");
   BufferedReader reader = new BufferedReader(inputFile);
   String line = reader.readLine();
   System.out.println(line);
} catch (IOException e) {
   e.printStackTrace();
}
解決策: I/O エラーを処理し、リソースが正しく閉じられていることを確認します。
File inputFile = new File("pqr.txt");

if (!inputFile.exists() || !inputFile.canRead()) {
 System.out.println("The input file is missing or not readable.");
 return;
}

try {
BufferedReader reader = new BufferedReader(inputFile);
 String line = reader.readLine();
 System.out.println(line);
  reader.close();
} catch (IOException e) {
 e.printStackTrace();
}
代わりに、Java 7 で導入されたtry-with-resource機能を使用して、以下に示すようにリソースを自動的に閉じることができることに注意してください。tryステートメントで 1 つ以上のリソースを宣言できます。ブロックが正常に完了するか例外がスローされるかに関係なく、Java はブロックの終わりでリソースを自動的に閉じます。
try (BufferedReader reader = new BufferedReader(new FileReader("pqr.txt"))) {
....
} catch {
....
}

FileNotFoundExceptionを修正する方法

シナリオ:指定された場所にファイルが見つかりませんでした。
try {
     BufferedReader reader = new BufferedReader(new FileReader("abc.txt"));
     String line = reader.readLine();
     System.out.println(line);
     reader.close();
} catch (FileNotFoundException | IOException e) {
     System.out.println("An error has occurred while reading the file: " + e.getMessage());
}
解決策:ファイルが存在し、それにアクセスするための適切な権限があることを確認してください。
try {
    File file = new File("abc.txt");
    if(!file.exists()) {
    throw new FileNotFoundException("File not found at the specified location");
    }
    BufferedReader reader = new BufferedReader(new FileReader(file));
    String line = reader.readLine();
    System.out.println(line);
    reader.close();
} catch (IOException e) {
    e.printStackTrace();
}

NoSuchMethodExceptionを修正する方法

シナリオ:見つからないメソッドにアクセスしようとしている場合。
public class TestClass {
   public void sayHello() {
      System.out.println("Hello");
   }
}

TestClass obj = new TestClass();
Method method = obj.getClass().getMethod("printHello"); // Это вызовет NoSuchMethodException
解決策:メソッドが存在すること、およびメソッド名と署名が正しいことを確認してください。
public class TestClass {
   public void sayHello() {
      System.out.println("Hello");
   }
}

TestClass  obj = new TestClass();
try {
    Method method = obj.getClass().getMethod("sayHello");
} catch (NoSuchMethodException e) {
    e.printStackTrace();
}

ConcurrentModificationException を修正する方法

シナリオ:反復中にコレクションが変更されます。
List<String> list = new ArrayList<>();
list.add("Java");
list.add("Python");
for (String str : list) {
  list.remove(str);  // Это вызовет ConcurrentModificationException
}
解決策:イテレータを使用してコレクションを反復処理し、イテレータ メソッドを使用してコレクションを変更します。
List<String> list = new ArrayList<>();
list.add("Java");
list.add("Python");
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
    String str = iterator.next();
    iterator.remove();
}
コメント
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION