質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.97%

try catch finally 文のテキストがコンパイルエラー

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 2
  • VIEW 3,432

tkh

score 11

始めまして。初心者で学習中のものです。

いま使用している教材(Java8対応と謳っている)でtry catch finally文の説明の項目があるのですが、例題があり「以下のコードで解決しましたね」という話のになっているのですが、実行してみるとコンパイルエラーが起きます。

 この教材ではちょくちょくそういった物があるにもかかわらず説明がない為、四苦八苦しています。

コンパイルエラーになる原因をご教授いただけたら幸いです。

よろしくお願いします。

import java.io.*;

public class Main {
    public static void main(String[] args) {
        FileWriter fw = null;
        try {
            fw = new FileWriter("data.txt");
            fw.write("hello!");
        } catch (IOException e) {
            System.out.println("エラー" );
        } finally {
            fw.close();
        }
    }
}

例外IOExceptionは報告されません。スローするには、補足または宣言する必要があります。
            fw.close();
             ^
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

+3

Java8対応だというのなら、次のような書き方があります。
Java7で導入されたtry-with-resourcesという構文です。

import java.io.*;

public class Main {
    public static void main(String[] args) {
        try(FileWriter fw = new FileWriter("data.txt")) {
            fw.write("hello!");
        } catch (IOException e) {
            System.out.println("エラー" );
        }
    }
}


tryのあとの括弧にリソースを指定します。(具体的には、AutoClosableインタフェースを実装しているクラス)
この構文を使えば、tryを抜ける際に指定されたリソースのclose()処理が自動で行われ、closeでの例外処理を気にする必要がなくなります。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/01/18 23:05

    Java が C# に負けてるなと思っていた点ですが、機能追加されていたのですね。
    勉強になりました。

    キャンセル

  • 2016/01/19 03:08

    ご回答いただきありがとうございます。
    この構文については、問題のコードの次に紹介されていました。
    教材では問題のコードのfw.close()を置き去りのまま、この構文の項目へ進んでたので混乱していました。
    ありがとうございました。

    キャンセル

checkベストアンサー

+2

そんな使えない教材は捨てたほうがいいですよ。

まず、コンパイルエラーが出る原因ですが、FileWriter.close() のメソッド自体を FileWriter クラスのリファレンスなどを調べてみると解ると思うのですが、このメソッドは例外 IOException への対処を必要とします。しかし、その教材のコードでは行われていませんね。

それ以外にも、(何らかの原因で) FileWriter の生成に失敗した場合、fw は null のままになる可能性があるわけですが、finally ではその対処も無いため、null を指し示している fw に対して close() を呼んでしまう可能性があります。ちなみに、その場合、NullPointerException の例外が発生してしまうでしょう。

例外をどこでどう捉えるか?で幾つか書き方はありますが、例えば、以下のような書き方があります。

FileWriter fw = null;
try {
    try {
        fw = new FileWriter("data.txt");
        fw.write("hello!");
    } finally {
        if (null != fw) fw.close();
        fw = null; // 腐った参照になるのを防ぐため null を代入しておく
    }
} catch (IOException e) {
    System.out.println("エラー");
}


上記のコードでは FileWriter が生成できなかった事を考慮して null との比較を行った上で、(null ではない、つまり)存在すれば close() を呼び出しているわけですが、null のままの状況が起こっている時点で動作は破綻しているため、開発対象によっては、ここまで厳密に捉えなくても良いと思います。しかし、こういった挙動を理解せずに省略するのは危険ですので、色々な対処方法は知っておくべきです。

以上、ご参考になれば幸いです。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/01/19 02:59 編集

    ご回答いただきありがとうございます。
    出来るだけ自分で理解して対処できるようになりたいと思っています。まだ学習段階でFileWriterが生成できないというケースに遭遇したことも考えたこともなかったので、大変参考になりました。
    私の現学習段階でps13zierさんのコードは理解するのに時間がかかりましたが、
    ファイルを書込み禁止にしたり、削除したりなどの不足の事態を自分で発生させ実験してみたところ、このコードが様々なケースに対応してあり、大変勉強になりましたのでベストアンサーとさせていただきました。

    ありがとうございました。

    キャンセル

+1

こんにちは。
分かる範囲でお答えします。

まず、try-catchっていうのは、
try-catchで囲まれた中で発生したExceptionを拾うような動きをします。

なので、

fw = new FileWriter("data.txt");
fw.write("hello!");

でIOExceptionが発生すると、

  } catch (IOException e) {
System.out.println("エラー" );

が拾ってくれるのです。

では、fw.close()はどうでしょう?
finallyの中に記述されていますが、
IOExceptionが発生すると、誰がcatchしてくれますか?

答えは、「残念ながら誰もcatchしません」です。

finallyは、try-catchで何があっても、最後に必ず実行する部分です。
従って、catchの部分は既に通り過ぎてしまっているのです!!!

じゃあどうしたらいいのか?
答えは二つあります。

1.fw.close()も、try-catchに入れちゃう。

  fw = new FileWriter("data.txt");
fw.write("hello!");
fw.close();

こんな感じですね。これなら、fw.close()でIOExceptionが発生しても、
catchが拾ってくれますよね!?

2.finallyの中にtry-catchを書いてしまう。

  }finally{
    try{
        fw.close();
    }catch( IOException e ){
        System.out.println( "finallyでIOException発生!" );
    }
}

上記のような感じです。
これなら、finallyの中のfw.close()でIOExceptionが発生しても、
catchが拾ってくれますよね!?

こんな具合に、好きな方を選ばれると良いと思います。

ちなみに、Exception(エラー)は、想定外のものも発生します。

catch( IOException  e )

これだけだと、IOExceptionが発生した時にしか、
catchに入ってくれません。。。
何が起こるか分からないのに、エラーをあらかじめ予測するなんて、困りますよね?

なので、全てのExceptionを網羅する以下の記述を加えることをお勧めします。

  }catch( Exception e ){
    System.out.println( "エラーをキャッチ!" );
    System.out.println(e);
}

最初は慣れないと思いますが、
是非頑張ってください!

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/01/19 02:41

    ご回答いただきありがとうございます。
    1.の方法で例外がおきたときにファイルが開きっぱなしになるのを回避するコードが今回の問題のコードで解決っていうことでfinallyを学習するものだったのです。
    2.の方法のご説明をいただきようやく理解ができました。教材の説明より判りやすく大変助かりました。ありがとうございました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.97%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る