この文章は Salesforce 機械翻訳システムを使用して翻訳されました。詳細はこちらをご参照ください。
英語に切り替える

try、catch、finally ステートメント

Apex では、trycatch、および finally ステートメントを使用して例外を処理します。次の例は、これらのステートメントとそれを記述する順序を示します。
1swfobject.registerObject("clippy.codeblock-0", "9");try {
2    // Perform some database operations that 
3    //   might cause an exception.
4} catch(DmlException e) {
5    // DmlException handling code here.
6} catch(Exception e) {
7    // Generic exception handling code here.
8} finally {
9    // Perform some clean up.
10}

try ステートメントは例外が発生する可能性のあるコードのブロックを識別します。例外を生成する可能性のあるコードでは、コードのこのセクションを try ブロックでラップし、その後に catch ブロックを追加します。try ブロックでラップしたコードから発生する例外のみが、catch ブロックで処理されます。

catch ステートメントは、特定の種別の例外を処理するコードのブロックを示します。上の例には、2 つの catch ステートメントがあります。catch ステートメントは、キャッチする例外種別ごとに 1 つずつ、必要な数だけ使用できます。

catch ステートメントは、固有なものから汎用的なものへと具体性の高い順に並べます。すべての例外は Exception 種別とみなされるため、汎用的な例外を最初にキャッチすると、1 つの catch ブロックのみが実行され、その他の catch ステートメントが実行されなくなるからです。

catch ステートメントでは、受け取った例外を処理します。たとえば、ログの記録やメールの送信、その他の何らかの処理を実行できます。

finally ステートメントは省略可能で、catch ブロックが実行された後に実行されます。finally ブロック内のコードは、発生して処理された例外の種別に関係なく、常に実行されます。ここに最終的なクリーンアップコードを追加できます。

実際に試してみる

例外の発生を確認するには、DML 例外を発生させるいくつかのコードを実行します。開発者コンソールで次のコードを実行します。
1swfobject.registerObject("clippy.codeblock-1", "9");Merchandise__c m = new Merchandise__c();
2insert m;

この例の insert DML ステートメントは、必須項目を設定せずに商品品目を挿入しているため、DMLException を発生させます。この例外エラーは、デバッグログに次のように表示されます。

System.DmlException: Insert failed. First exception on row 0; first error: REQUIRED_FIELD_MISSING, Required fields are missing: [Description, Price, Total Inventory]: [Description, Price, Total Inventory]
続いて、開発者コンソールで次のスニペットを実行します。これは前の例に基づいていますが、try-catch ブロックが追加されています。
1swfobject.registerObject("clippy.codeblock-2", "9");try {
2    Merchandise__c m = new Merchandise__c();
3    insert m;
4} catch(DmlException e) {
5    System.debug('The following exception has occurred: ' + e.getMessage());
6}

開発者コンソールに表示される要求の状況は、正常に完了したことを報告しています。これは、コードが例外を処理しているためです。

例外の後に出現する try ブロックのステートメントはすべてスキップされ、実行されません。たとえば、insert m; の後にステートメントを追加しても、ステートメントは実行されません。次のコードを実行します。

1swfobject.registerObject("clippy.codeblock-3", "9");try {
2    Merchandise__c m = new Merchandise__c();
3    insert m;
4    // This doesn't execute since insert causes an exception
5    System.debug('Statement after insert.');
6} catch(DmlException e) {
7    System.debug('The following exception has occurred: ' + e.getMessage());
8}

新しいデバッグログエントリには、「Statement after insert」というデバッグメッセージは表示されません。これは、この debug ステートメントが挿入で発生した例外の後に出現し、実行されないためです。例外が発生した後にコードステートメントの実行を続行するには、try-catch ブロックの後にステートメントを配置します。この変更されたコードスニペットを実行すると、デバッグログに「Statement after insert」というデバッグメッセージが表示されるようになります。

1swfobject.registerObject("clippy.codeblock-4", "9");try {
2    Merchandise__c m = new Merchandise__c();
3    insert m;
4} catch(DmlException e) {
5    System.debug('The following exception has occurred: ' + e.getMessage());
6}
7// This will get executed
8System.debug('Statement after insert.');
9

または、try-catch ブロックを追加できます。このコードスニペットでは、2 つ目の try-catch ブロック内に System.debug ステートメントがあります。これを実行すると、前と同じ結果になります。

1swfobject.registerObject("clippy.codeblock-5", "9");try {
2    Merchandise__c m = new Merchandise__c();
3    insert m;
4} catch(DmlException e) {
5    System.debug('The following exception has occurred: ' + e.getMessage());
6}
7
8try {
9    System.debug('Statement after insert.');
10    // Insert other records
11}
12catch (Exception e) {
13    // Handle this exception here
14}

finally ブロックは、発生した例外に関係なく、また例外が発生しなくても常に実行されます。実際にどう使用されるのか見てみましょう。次のコードを実行します。

1swfobject.registerObject("clippy.codeblock-6", "9");// Declare the variable outside the try-catch block
2// so that it will be in scope for all blocks.
3XmlStreamWriter w = null;
4try {
5    w = new XmlStreamWriter();
6    w.writeStartDocument(null, '1.0');
7    w.writeStartElement(null, 'book', null);
8    w.writeCharacters('This is my book');
9    w.writeEndElement(); 
10    w.writeEndDocument();
11
12    // Perform some other operations
13    String s;
14    // This causes an exception because
15    // the string hasn't been assigned a value.
16    Integer i = s.length();
17} catch(Exception e) {
18    System.debug('An exception occurred: ' + e.getMessage());
19} finally {
20    // This gets executed after the exception is handled
21    System.debug('Closing the stream writer in the finally block.');
22    // Close the stream writer
23    w.close();
24}

上記のコードスニペットでは、XML ストリームライタを作成し、いくつかの XML 要素を追加します。次に、null の String 変数 s にアクセスしたために例外が発生します。catch ブロックがこの例外を処理します。続いて、finally ブロックが実行されます。このブロックでデバッグメッセージが書き出され、ストリームライタが終了し、それによって関連リソースが解放されます。デバッグログでデバッグ出力を確認します。例外エラーの後にデバッグメッセージ「Closing the stream writer in the finally block.」が表示されます。これにより、例外がキャッチされた後に finally ブロックが実行されたことがわかります。

ランタイムがガバナ制限に達した結果として発生させる例外など、処理できない例外もあります。ガバナ制限についての詳細は、第 3 章のガバナ実行制限内での Apex の実行で学習します。

メモ