コンテンツにスキップ

例外処理

例外処理

例外とは、通常の処理では考えられないような、いわゆる「例外」のことで、多くの場合「エラー」と同じと考えてください。

例外が発生する場所

プログラム中のどこでも例外が発生する可能性があります。

例外を発生させることを「例外を投げる(throw)」ともいいます。

たとえば、以下のスクリプトがエラーを起こしたとします。

    "3%0"!; // "0 で除算をしようとしました" 例外が発生する

このように 明らかに例外が発生する場合もありますが、発生するかしないかわからない場合もあります。

例外の捕捉

**try** (試す) キーワードと、**catch** (捕捉) キーワードを使うと、例外を捕捉できます。

たとえば、上の例で発生するかもしれない例外を捕捉するために、以下のようなスクリプトを書くことができます。

    try // 例外が発生するするかもしれないので
    {
        func1(); // ここでは例外が発生するかもしれない
    }
    catch // 例外を捕捉する
    {
        // 例外がおきたとき、ここが実行される
        inform("画像を読み込むことができません。"); // メッセージを表示する
    }

このように、try のブロック内で例外の発生するかもしれない処理を書けば、例外がおきたときに catch のブロックを実行することができます。エラー処理をこのようにすっきりと書くことができます。

try のブロックでなにも例外が起きなかった場合は、catch のブロックも実行されません。

try のブロックでは何でも書くことができます。この例のように、はっきりとその行で例外がおきる可能性があることもありますが、関数呼び出しのそのまた関数呼び出しの先で例外が発生したときも、try ... catch を書いておけば例外が発生した時点でここに戻ってくることができます。

例外が発生した場合は、ブロックの残りの処理は中断され、try のある場所まで戻ってきます。

catch のブロックでまた例外が発生した場合は、例外はこの場所では捕捉されません。そのまま例外は関数呼び出しなどをさかのぼり、もしほかの場所で try で例外の捕捉が行われていればそこで捕捉されます。

例外が投げられてから、catch ブロックに到達する間に別の例外が発生する可能性もありますが、動作は未定義です。

例外がスクリプト内のどこでも捕捉されなかった場合、例外はそのままスクリプトを抜けてアプリケーションに渡され、そこで処理されます。

Note: 通常、このような例外はエラーとして実行を中断させてしまうので、なるべくエラーが起こりそうな場所には try ... catch を書くことをおすすめします。

例外オブジェクト

例外に関するさまざまな情報が、Exception というクラスのオブジェクトとともに投げられてきます。このオブジェクトを例外オブジェクトと呼びます。これを、catch で受け取ることができます。詳しくは Exception クラス を参照してください。

たとえば、以下のようなスクリプトを書くことができます。

    try
    {
        loadImages("nothing.jpeg"); // 例外が発生するかもしれない処理
    }
    catch (e) // e という変数で例外を受け取る
    {
        // e.message は、例外とともに投げられたメッセージ文字列を表します。
        // これには例外が発生した理由が説明されている場合があります。
        inform("画像を読み込むことができません。\n"+e.message);
    }

このように、catch の後の丸カッコ内に受け取る変数を書き、その変数に例外オブジェクトを受け取ることができます。

この変数のスコープは、catch の次のブロック内で始まり、このブロックとともに終わります。この変数はあらかじめ宣言されている必要はありません。

throw ステートメント

例外を投げることもできます。例外を投げるには **throw** キーワードを使います。

たとえば、以下のようなスクリプトを書くことができます。

    function pow2(n)
    {
        // 2 の n 乗を計算する n は正の整数でなければならない
        if(n<0) throw new Exception("負の数は指定できません。");
            // ↑ 例外を発生する
        return 1<<n;
    }

この関数の引数に -1 など、負の数が渡された場合、例外が発生します。例外を投げているのは以下のステートメントです。

throw new Exception("負の数は指定できません。");

new Exception("負の数は指定できません。") についてですが、これは Exception クラスのオブジェクトを、文字列を引数にして作成しています。詳しくは Exception クラス を参照してください。そして、この新しく作成されたオブジェクトを throw キーワードで投げています。

throw キーワードで投げることができるのは Exception クラスのオブジェクトとは限りません。数値でも文字列でも、関数への参照を投げることもできます。しかし、Exception クラス、またはそれから派生したクラスのオブジェクトを投げることが推奨されます。捕捉したときに catch のブロックで、Exception クラスのオブジェクトがくることのみを想定して書けばいいからです。

例外を再び投げる

catch で例外を捕捉したのはいいが、まだ例外を受け取る可能性のある try がどこかに宣言されているかもしれない、そのような場合に例外を再び投げることができます。

以下のようなスクリプトを書くことができます。

    function tryloadimage()
    {
        try
        {
            primaryLayer.loadImages("test1.bmp"); // test1.bmp を読んでみる
        }
        catch(e)
        {
            inform("画像読み込みに失敗しました。");
            throw e; // メッセージを表示はするが、例外を再び投げる
        }
    }

    function test()
    {
        // tryloadimage を呼び出し、画像読み込みが成功すれば true
        // そうでなければ false を返す関数
        try
        {
            tryloadimage();
        }
        catch
        {
            return false;
        }
        return true;
    }

ここで test() を呼び出し、画像読み込みに失敗した場合は、inform メソッドによりメッセージが表示されますが、再び例外が投げられるため、test 関数内の catch により捕捉することができます。