2016-10-05 18 views
3

メソッドの配列から静的メソッドを呼び出そうとしています。これはデバッガで正常に動作しますが、通常の実行モードでは正常に動作しません。これはなぜですか?以下のコードのコメントでJava Reflection:デバッガでコードは正常に実行されますが、通常の実行モードでは実行されません。

詳しい説明..簡単に再生のため

EDITちょうどデバッガ対通常モードでこのクラスを実行します。

backautomat_starten Exception in thread "main" java.lang.NullPointerException 
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) 
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) 
at java.lang.reflect.Method.invoke(Unknown Source) 
at com.relfection.easy.example.Stackoverflowquestion.main(Stackoverflowquestion.java:31) 
+0

例外はありますか?別のビットをコピーして別のファイルに貼り付けなくても、私たち自身で複製できるように[mcve]を提供できますか? (新しいファイルを1つ作成し、コピー、貼り付け、コンパイルして実行し、エラーを表示できるはずです) –

+0

['Class.getMethods()'](https://docs.oracle.com/javase/8/) docs/api/java/lang/Class.html#getMethods--)は保証された順序でメソッドを提供しません。デバッガ*で実行すると、注文に影響を与えることができます。実際には、* anything *はその順序に影響を与えることができますが、デバッガの場合もそうです... – Holger

+0

getMethods()のドキュメントから: "返された配列の要素はソートされず、特定の順序ではありません" – Zircon

答えて

5

documentation of Class.getMethods()考えてみましょスローしていました:中

...

要素を返される配列はソートされず、特定の順序ではありません。

これは、現在のJREの任意の側面が結果を変更し、デバッガを含めて実行する副作用を持つ可能性があることを意味します。

したがって、配列の最初のメソッドが期待通りでなく、予想外の名前を取得し、staticメソッドのようなインスタンスメソッドを実行しようとしたときに例外を生成する場合、同じ間違った前提があります。

+0

答えを教えていただきありがとうございます。私はデバッガでは正常に機能していますが、ノーマルモードでは動作しないため、ちょっとしたものでした。 – fred

+0

実際のコードパスをトレースすると、実際の実装に非常に深く浸る必要があります。この問題を理解するには、JVMとデバッガ間の通信を可能にする特定のコードをロードする必要があります。これは、特定のものが初期化される順序に影響を与え、このような微妙なものに影響を与える可能性があります'getMethods()'によって返される要素の順序と同じです。この情報がキャッシュされているかどうか予測できないため、同じセッション内の後続のコールでも注文が変更される可能性があります。 – Holger

+0

これはあまりにも遠すぎます。あなたの詳細な答えをありがとう! – fred

1
:EDIT例外は次のようになります

public class Stackoverflowquestion { 

public static class Backautomat { 
    private String aktuellBackendeBrotsorte = "Butterbrot"; 
    //Test für Statische Methoden: Brauche ich dazu auch eine Instanz für Invoke? 
    public static String getBezeichnung(){ 
     return "Bezeichnung: Bester-Backautomat-Ever"; 
    } 
    //Test für Methoden ohne Parameterliste 
    public boolean backautomat_starten(){ 
     return true; 
    } 
} 

public static void main(String[] args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { 
    //Get all methods of class 
    Method[] backaudomadMethoden = Backautomat.class.getMethods(); 
    //Get first Method of class -> I know this one is static -> see in source "Backautomat" 
    Method backMethod = backaudomadMethoden[0]; 
    //Printing out Method Name: In Debugger this returns the static method name: getBezeichnung(), 
    //In "normal" running mode (Run -> Run as -> Java Application) it prints out the second method: backautomat_starten() 
    System.out.println(backMethod.getName()); 
    //Invocation is successfull in debugger 
    //Invocation throws exception running in "normal" mode 
    System.out.println(String.valueOf(backMethod.invoke(null))); 

} 

https://docs.oracle.com/javase/7/docs/api/java/lang/reflect/Method.html#invoke(java.lang.Object,%20java.lang.Object...)

これは、 Uは、あなたがオブジェクトとしてnullを渡しているので、あなたがnullのオブジェクトのメソッドを呼び出そうとしているここで定義されたオブジェクトに渡された

String.valueOf(backMethod.invoke(null)); 

にそのメソッドを呼び出します。明らかに

Object x = null; 
x.toString(); 

とx.toString(のようなものをやっへの同様の

)NPE

+0

を使用してください。また、このメソッドは静的メソッドでなぜ機能するのかを明確に述べています。指定されたobj引数は無視されます。それはnull._ – Berger

+0

ああはい、そのメソッドの順序が非常にはっきりと返されるので、デバッグしているときには、1つの順序で、正常に別のものを実行しています – Ash

関連する問題