Code Fix

上級

finally の return が結果を上書きする問題

finallyでreturnを書いてはいけない理由と、try-with-resourcesによる安全なリソース解放を扱います。

なぜエラーが出ないのか

出力: 2
(エラーなし)
javacは何も報告しません。文法として正しいためです
出力: 2
実際の挙動 — 期待した結果と食い違っている箇所
見つけ方
エラーが出ないので、出力を目で確かめるしかありません。この種の誤りが最も発見が遅れます

このエラーが出る典型パターン

パターン1

 1  public class Main {
 2      static int f() {
 3          try { return 1; }
 4          finally             { return 2; }
                     ^
 5      }
 6      public static void main(String[] args) {
 7          System.out.println(f());
 8      }
 9  }
出力: 2期待: 1 (コンパイルは通っています)

finally内のreturnはtry内のreturnを上書きします。finallyでreturnを書かないのが鉄則です。

直し方: finallycatch (Exception e) にします。

この問題を解いてみる →

広告
広告スロット(未設定)

パターン2

 1  import java.io.*;
 2  
 3  public class Main {
 4      public static void main(String[] args) throws IOException {
 5          try (String         r = new BufferedReader(new StringReader("a"))) {
                        ^
 6              System.out.println(r.readLine());
 7          }
 8      }
 9  }
Main.java:5: error: incompatible types: BufferedReader cannot be converted to String

try-with-resourcesの変数はAutoCloseableを実装した型で宣言します。ブロックを抜けると自動でcloseされます。

直し方: StringBufferedReader にします。

この問題を解いてみる →

パターン3

 1  public class Main {
 2      public static void main(String[] args) {
 3          try {
 4              System.out.println("try");
 5          }         {
                 ^
 6              System.out.println("always");
 7          }
 8      }
 9  }
Main.java:5: error: 'try' without 'catch', 'finally' or resource declarations

tryは単独では書けません。catchかfinally、またはリソース宣言のいずれかが必要です。

直し方: (空)finally にします。

この問題を解いてみる →

よくある誤解

finallyは必ず実行されると言われますが、System.exit() を呼んだ場合は実行されません。

まとめ

finally の return が結果を上書きする問題は上級でつまずきやすい項目です。上の3パターンを実際に手で直すと、エラーメッセージのどこを読めばよいかが掴めます。

演習をはじめる

関連するエラー

広告
広告スロット(未設定)