2009-03-02 17 views
1

Ich möchte den Programmierern, die meinen Code verwenden, durch Reflektion etwas Bequemlichkeit bieten. Um mein gewünschtes Ergebnis zu erreichen, möchte ich das Klassenobjekt für Klassen erhalten, die meinen Code erweitern. Auch wenn sie die statische Methode, auf die ich zugreifen möchte, nicht überschreiben können, wäre es momentan hilfreich. Ich könnte am Ende einfach das Design etwas umgestalten, um diese Situation zu vermeiden, aber ich wollte diese Frage an die Community weitergeben.getClass() und statische Methoden: Was ist die beste Vorgehensweise?

Die einzige Möglichkeit, dies zu erreichen, die ich kenne, ist, den aktuellen Thread zu nehmen, den Stack-Trace zu navigieren und den Klassennamen zu extrahieren und ihn dann in eine tatsächliche Instanz der Klasse umzuwandeln.

Haben Sie noch weitere Vorschläge?

Randnotiz: Der obige Ansatz ist auch die einzige Möglichkeit, dass ich die Aufrufmethode kennen.

Antwort

1

Wenn in der statischen Methode, ist die Garantie, dass einige (jede) Klasse, die von Ihrem erweitert wurde, auf dem Stapel ist?

Wenn Sie ein wenig darüber nachdenken, ich vermute, Sie werden erkennen, was Sie suchen, existiert nicht.

/EDIT 1/ Ich denke, was Sie brauchen, ist

abstract class B { 
    <T extends B> B create(Class<T> clazz) { 
    .... 
} 

Hmmm. Was ist, wenn createprotected Methode ist? Dann könnten Sie ziemlich sicher sein, dass der Anrufer ein B ist, können Sie sogar verlangen, UnsupportedOperation oder IllegalState werfen, wenn der Anrufer nicht zu B zuweisbar ist.

können Sie verwenden Thread.currentThread().getStackTrace()

+0

Das ist, wovor ich wirklich Angst habe. Für das, was ich tue, statische Methoden, die Instanzen der Klassen zurückgeben, die sie repräsentieren, unterstützt durch eine reflexionsbasierte automatische Verdrahtung. Ich denke, ich werde die Refactor-Route gehen und eine zentrale Factory-Klasse haben, die sowohl eine Klasse als auch die ursprüngliche Anfrage akzeptiert. –

+0

Oh, aber die statische Methode "repräsentiert" nur die Klasse, in der sie deklariert wurden. Sie * werden * eine Klasseninstanz benötigen. Siehe mein Beispiel in/EDIT 1/über –

2

Gehen der Stapel nicht unbedingt sicher ist leider zu tun:

Vom JDK 6 Javadoc für getStackTrace:

Einige virtuelle Maschinen können unter einigen Umständen , lassen Sie einen oder mehrere Stapel Frames aus dem Stack-Trace aus. Im Extremfall hat eine virtuelle Maschine, die keine Stack-Trace-Informationen in Bezug auf diese throwable von diese Methode zurückgeben erlaubt ist. Im Allgemeinen enthält das von dieser Methode zurückgegebene Array ein Element für jeden Rahmen , der von printStackTrace gedruckt werden würde.

Sie könnten vielleicht den Debugger API verwenden, um es zu tun. Ich bin der Meinung, dass das Debugging-Programm HotSpot mit voller Geschwindigkeit nutzen kann (ich könnte falsch liegen), so dass Sie keinen enormen Geschwindigkeitszuwachs sehen würden. Sie könnten durch einen Blick auf Start: http://java.sun.com/javase/6/docs/technotes/guides/jpda/trace.html

Auch dabei auf Unanswereds Antwort ...

class Base 
{ 
    // instance method helper 
    public final int foo() 
    { 
     return (foo(this.getClass())); 
    } 

    // the real helper, with access to the class 
    private static int foo(final Class clazz) 
    { 
     return (0); 
    } 
} 

class Child 
    extends Base 
{ 
    public void bar() 
    { 
     final int x; 

     x = foo(); 
    } 
} 
+0

Sie können den Stack als StackTraceElements laufen - es ist nicht notwendig oder empfohlen, die von printStackTrace() gedruckte Zeichenkette zu analysieren. –

+0

siehe mein Update dafür – TofuBeer

0

ich den Morast der Reflexion schlagen zu vermeiden. Du scheinst eine Art von direkter Programmierung zu machen. Verwenden Sie eine einfache Implementierung (es gibt nicht genug Informationen, um eine vernünftige Schätzung zu machen, was das sein könnte).

+0

Ich arbeite an einem Java ORM als kleines Nebenprojekt. Teil der Ziele sind a) kleine Nicht-Java-Konfiguration (kein XML-Schema def, Migrationen in Java) b) keine Codegenerierung (zur Kompilierungszeit) Um diese Ziele auf eine abstrakte Weise zu erreichen, bietet Reflexion eine Menge Syntax Zucker . –

1

ein Throwable zu schaffen, ist sehr teuer, so dass Sie diese nicht verwenden, wenn Ihre Methode oft genannt wird (.e.g. Mehr als einmal pro Sekunde) Ein leichter besserer Ansatz Thread.currentThread ist(). GetStackTrace().

Ein anderer Ansatz, wenn Sie Suns JVM verwenden, ist Reflection.getCallerClass (n). Dies ist viel schneller, aber nicht auf andere JVMs übertragbar. Wenn Sie sich darüber Gedanken machen, können Sie eine andere Methode verwenden, die dies aufruft, wenn sie verfügbar ist, und die Stack-Ablaufverfolgung verwendet, falls dies nicht der Fall ist.

All dies setzt voraus, dass Ihre statische Methode NICHT öffentlich ist. Wenn das alles ist, sind alle Wetten deaktiviert, da Ihre Methode von jeder Klasse aufgerufen werden kann, nicht nur von einer, die Ihre Klasse erweitert.

Verwandte Themen