2013-07-12 10 views
15

コンストラクタがコンパイラによって生成されたデフォルトのコンストラクタであるかどうかをリフレクションによって調べる方法はありますか?それとも別の方法がありますか?コンストラクタはデフォルトのコンストラクタを生成していますか?

驚くべきことに、isSynthetic方法はこの情報を与えないので使用できません。そして、Generated注釈が存在しません。

public class JavaTest { 
    public void run() throws Exception { 
     out.println(JavaTest.class.getConstructors()[0].isSynthetic()); // Prints false 
     out.println(Arrays.asList(JavaTest.class.getConstructors()[0].getAnnotations())); // Prints [] 
    } 
} 

この質問は同じことを要求しますが、C#の場合:Detect compiler generated default constructor using reflection in C#

+5

答えはC#の答えと同じであると思います:) – PermGenError

+1

自動的なデフォルトのコンストラクタは、間違いなく言語の設計ミスです。理想的な世界では、それは存在しません、なぜあなたも気にします:)どのような機能は、デフォルトのコンストラクタの検出に依存しますか? – ZhongYu

+0

自動的なデフォルトコンストラクタは素晴らしいです!それは静的分析を行うためのものです。私が知っているよりもコンストラクタがデフォルトであることが分かっている場合、クラスの宣言だけを見ることで、空であり、例えば 'this'ポインタをどこにでもリークさせません。 – Lii

答えて

8

いいえ、コンパイラはそれらを生成します。その後、

public class A{ 
public String t(){return "";} 
} 

私はファイル A.javaを作成

javac A.java 

やコンテンツを見るためにjavap -c Aを実行している:

Compiled from "A.java" 
public class A { 
    public A(); 
    Code: 
     0: aload_0  
     1: invokespecial #1     // Method java/lang/Object."<init>":()V 
     4: return   

    public java.lang.String t(); 
    Code: 
     0: ldc   #2     // String 
     2: areturn  
} 

私はコンストラクタ追加した場合:

public A(){} 

を結果は次のとおりです。

Compiled from "A.java" 
public class A { 
    public A(); 
    Code: 
     0: aload_0  
     1: invokespecial #1     // Method java/lang/Object."<init>":()V 
     4: return   

    public java.lang.String t(); 
    Code: 
     0: ldc   #2     // String 
     2: areturn  
} 

それは同じです。私は64ビットOpenJDKでJava 7を使用していますが、すべてのバージョンで同じであると確信しています。

編集:実際、同じバイトコードだけでも、情報がメタデータとして存在しないことを保証するものではありません。 16進エディタとthis programを使用すると、2バイトが異なり、(スタックトレースの印刷に使用される)行番号に対応することが分かりました。そのため、この場合は情報は存在しません。

+0

生成されたデフォルトのコンストラクタと空のコンストラクタが同じバイトコードを生成することは合理的です。しかし、これに関する情報を持つメタデータがまだ存在する可能性があります。 – Lii

+0

ああ、生データエディタでクラスファイルを調べて解決してください!ありがとう。 – Lii

5

いいえ、コンパイルで生成されたデフォルトのコンストラクタと生成されていないコンストラクタを区別できるメタデータはバイトコードにありません。

ほとんどの場合、コンパイラによって生成されたコンストラクタおよびメソッドは、生成されたバイトコードのACC_SYNTHETICフラグまたはSynthetic属性でマークされます。しかし、jvm-spec

からJava Language Specおよび4.7.8から13.1項目7あたりなど、いくつかの注目すべき例外は、ここにありますJLSから関連するビットです:

は、Javaコンパイラにより導入された任意の構造ソースコード内の対応する構造を持っていないデフォルトコンストラクタ、クラスの初期化メソッド、および値と列挙型クラスのvalueOfメソッドを除く

私の知る限りとして、合成としてマークする必要がありますjavapACC_SYNTHETICフラグを表示しませんが、設定されている場合はisSyntheticで読むことができます。

+0

'javap -verbose'は' ACC_SYNTHETIC'を含むフラグを表示します。 –

関連する問題