2009-09-03 6 views

答えて

324

はい、コンストラクタは例外をスローすることができます。通常、これは新しいオブジェクトがすぐにガベージコレクションの対象となることを意味します(ただし、しばらくは収集できません)。 「半構造」オブジェクトは、コンストラクタの前に表示されている場合(たとえば、静的フィールドを割り当てたり、コレクションに追加するなど)には使用できます。

呼び出し元(通常は)が新しいオブジェクトを使用する方法を持たないため、コンストラクタはアンマネージリソース(ファイルハンドルなど)の取得を避けるように注意する必要があります。解放しないで例外をスローします。たとえば、コンストラクタがFileInputStreamFileOutputStreamを開こうとしたときに、最初のコンストラクタが成功しても2番目のコンストラクタが失敗した場合は、最初のストリームを閉じようとする必要があります。例外をスローするサブクラスのコンストラクタであれば、これはもっと難しくなります。もちろん、それは少し難解です。それは非常に頻繁に問題ではありませんが、検討する価値があります。

+25

+1。通常、サブクラスによってスローされる例外は誰も考えません。 –

+1

@JonSkeet:**コンストラクタの前に(*静的フィールドを割り当てたり、コレクションに自身を追加するなどして)* *についてのコード例をいくつか教えてください。 – Tarik

+3

@Tarik:コード例はまあまあです。コンストラクタ内の 'someStaticField = this;'または 'someCollection.add(this)'です。 –

31

絶対に。

コンストラクタが有効な入力を受け取らないか、有効な方法でオブジェクトを構築できない場合は、例外をスローして呼び出し元に警告する以外のオプションはありません。

7

はい。

コンストラクタは特別なメソッドであり、他のメソッドと同様に例外をスローすることができます。

+0

をして投げることができますあなたの声明で重要なのは「特別な方法」です。だから彼らは他の方法のようではありません。非最終クラスのコンストラクタ**から例外をスローすると、セキュリティホールが作成される可能性があるので、これを行うには特別な注意が必要です。上記の@Billyによる回答と、Javaセキュアコーディングガイドラインの抜粋を参照してください。 –

11

はい、コンストラクタは例外をスローすることができます。

ただし、例外をチェックする場合は、例外をチェックするかチェックしないかを選択するのが賢明です。未チェックの例外は、基本的にRuntimeExceptionのサブクラスです。

ほとんどの場合(私はこのケースの例外を思いつくことができませんでした)、チェック例外を投げる必要があります。その理由は、NullPointerExceptionのようなチェックされていない例外は、通常、プログラミングエラー(入力を十分に検証しないなど)によるものです。

チェックされた例外が提供する利点は、プログラマがインスタンス化コードで例外を捕捉し、オブジェクトインスタンスの作成に失敗する可能性があることです。もちろん、コードレビューだけでは、例外を飲み込むプログラミングの習慣が貧弱になることがあります。

76

はい、例外をスローすることができます。そうであれば、それらは部分的にのみ初期化され、非最終的であれば攻撃の対象となります。

以下はSecure Coding Guidelines 2.0のものです。

非最終的なクラスの部分的に初期化されたインスタンスには、ファイナライザ攻撃を介してアクセスできます。攻撃者は、サブクラスのprotected finalizeメソッドをオーバーライドし、そのサブクラスの新しいインスタンスを作成しようとします。上記の例では、ClassLoaderのコンストラクタのSecurityManagerチェックでセキュリティ例外がスローされますが、攻撃者は例外を無視して部分的に初期化されたオブジェクトに対して仮想マシンがファイナライズを実行するまで待機します。これが発生すると、悪意のあるファイナライズメソッドの実装が呼び出され、攻撃者はファイナライズされるオブジェクトへの参照をこのオブジェクトにアクセスできます。オブジェクトは部分的にのみ初期化されますが、攻撃者は引き続きメソッドを呼び出すことができます(これにより、SecurityManagerのチェックを回避します)。

+1

これは、最終的でないクラスから投げることがセキュリティ侵害であることを意味しますか?これはまだ問題なのでしょうか? – kroiz

+1

このガイドラインは、コードがセキュリティが重要なコンテキストで使用されている、または使用される可能性が高い場合にのみ関連します。たとえば、ほとんどのJavaコードは、SecurityManagerが存在しないコンテキストで使用されます。 –

0

コンストラクタは例外をスローすることができます。しかし、いずれかのサブクラスコンストラクタが例外をスローするスーパークラスコンストラクタを呼び出す場合、サブクラスコンストラクタは例外をキャッチするかスローする必要があります。

+8

super()がコンパイルエラーを引き起こす前にtryブロックを使用するので、サブクラスコンストラクタは例外をキャッチできません( "superはコンストラクタの最初のステートメントでなければなりません") –

10

はい、それは例外をスローすることができますし、次の例に示す過ぎるようコンストラクタの署名にそれを宣言することができます。

public class ConstructorTest 
{ 
    public ConstructorTest() throws InterruptedException 
    { 
     System.out.println("Preparing object...."); 
     Thread.sleep(1000); 
     System.out.println("Object ready"); 
    } 

    public static void main(String ... args) 
    { 
     try 
     { 
      ConstructorTest test = new ConstructorTest(); 
     } 
     catch (InterruptedException e) 
     { 
      System.out.println("Got interrupted..."); 
     } 
    } 
} 
-1

はい、それは他の方法のような例外が

+1

この詳細な回答はありがとうございます。既に多くの優れた投稿によって回答されています。 – Tom

関連する問題