2009-12-25 6 views
7

ich ein kleines Problem in meinem CodeProblem im GetDeclaredMethods (Java)

Ich habe 2 Klassen

public class A { 

    public A foo(int a) {return new A();} 
} 

public class B extends A{ 

    public B foo(int x){ return new B();} 
} 

jetzt in meinem Code habe ich nur die Methode drucken möchten, die in der Klasse B erklärt wurde

auf diese Weise

B b = new B(); 

Method[] m = b.getClass().getDeclaredMethods(); 

for (int i = 0; i < m.length; i++) { 

System.out.print(m[i].getName()); 
} 

warum die Ausgabe

foo 

foo 

Warum findet GetDeclaredMethods auch das foo in der A-Klasse? Wie kann ich es beheben?

dank

Antwort

0

Sie können m.getDeclaringClass() aufrufen, um zu sehen, ob es die Methode von der Klasse A oder B ist

+0

in beiden Fällen die getDeclaringClass kehrt B – Dazel

1

standardmäßig getDeclaredMethods() kehrt für die gegebene Klasse die Methoden alle von, als auch wie es Elternklassen und Schnittstellen ist. Mit dem Objekt Method können Sie jedoch testen, zu welcher Klasse Method gehört, indem Sie getDeclaringClass() unter der Nummer Method aufrufen. Wenn Sie also alle Method-Objekte durchlaufen, können Sie eine Logik hinzufügen, die nur dann eine Methode ausgibt, wenn sie zur Klasse B gehört.

Method[] m = b.getClass().getDeclaredMethods(); 
for (int i = 0; i < m.length; i++) { 
    if (m[i].getDeclaringClass().equals(B.class)) { 
    System.out.print(m[i].getName()); 
    } 
} 

EDIT: Der obige Code wie gewünscht funktioniert nicht - es gibt B als die deklarierte Klasse aller Methoden. Die isSynthetic()-Methode scheint, wie gewünscht zu funktionieren, True für eine überschriebene Methode zurückzugeben (eine, die von A kam) aber falsch für eine, die von B kam. Also könnte der folgende Code das sein wonach Sie suchen.

Method[] m = b.getClass().getDeclaredMethods(); 
for (int i = 0; i < m.length; i++) { 
    if (!m[i].isSynthetic()) { 
    System.out.print(m[i]); 
    } 
} 
+0

leid, aber das ist nicht die richtige Lösung I Get 2 foo noch – Dazel

+0

Lemme führen Sie es in den Ausgang und sehen, was das Problem ist ... –

+0

ich die Methode isSynthetic gefunden() Es gibt false für das Original foo in Klasse B zurück und true für das foo aus Klasse A zurück, aber weil ich nicht vertraut mit der isSynthetic() -Methode bin ich mir nicht sicher, ob dies der richtige Gebrauch davon ist. Ist dies der richtige Ort, um diese Methode zu verwenden? – Dazel

1

Weil B.foo und A.foo unterschiedliche Methoden sind. Wenn Sie Methode A.foo außer Kraft setzen möchten, dann B.foo Methode muss Klasse A. Rückkehr

+0

Richtige Antwort, so +1, aber es ist nicht sehr gut ausgedrückt, wenn Sie die Antwort nicht bereits verstehen. – Yishai

0

Diese Arbeit kann:

A a = new A(); 
B b = new B(); 

List<Method> aMethods = Arrays.asList(a.getClass().getMethods()); 
List<Method> bMethods = Arrays.asList(b.getClass().getMethods()); 

for (Method m : bMethods) 
{ 
    if(! aMethods.contains(m)) 
    { 
    //Your action code here 
    } 
} 
15

Der Grund, warum Sie ein Problem haben, ist wegen der kovarianten Rückgabetypen von Deine zwei Methoden. Da Sie einen kovarianten Rückgabetyp haben (der Rückgabetyp von B ist B, nicht A, im Gegensatz zur Oberklasse), generiert Java unter der Haube eine separate Methode mit dem ursprünglichen Rückgabetyp, die als Brücke zwischen der vor-1,5 Bytecode-Spezifikation fungiert neues Java 1.5 Sprachverhalten.

Die Methode, die Sie verwenden sollten, um zu überprüfen, obwohl ist die isBridge() Methode, wie es genau ausdrückt, was Sie ausschließen möchten. So ist der endgültige Code würde in etwa so aussehen:

Method[] methods = B.class.getDeclaredMethods(); 

for (Method method : methods) { 

    if (!method.isBridge()) { 
     System.out.println(method.getName()); 
    } 
} 
+0

Es scheint die Lösung für mein Problem zu sein, danke Aber was ist der Unterschied zwischen IsBridge() und isSynthetic()? – Dazel

+2

@Dazel, im Grunde identifiziert isBridge Dinge, die vom Java-Compiler gemacht werden, um eine Java-Sprache anzupassen, die von Generics in Bytecode-Beschränkungen eingeführt wurde. isSynthetic sagt Ihnen, ob die Methode synthetisch erzeugt wird, welche Methoden es gibt, aber es gibt auch mehr Dinge, wie zum Beispiel einige Elemente innerer Klassen. Eine Brücke ist also immer synthetisch, aber eine Synthese ist nicht immer eine Brücke. Wenn du darüber nachdenkst, ist es vielleicht das, was dir am meisten am Herzen liegt - die Methode existiert nicht im Quellcode, dir ist es egal warum. – Yishai

+0

Schön, das habe ich nie realisiert. Scheint, dass einige der Dinge, die sie tun mussten, um Java mit der 1.5-und-up-Spezifikation arbeiten zu lassen, ... interessant sind. –

0

Wenn Sie sagt if (! AMethods.contains (m)) nicht enthält namentlich vergleichen? Argumente eingeben? Rückgabewerttyp? weil der einzige Unterschied von der gewünschten Methode zum Nicht-Typ der Kovarianz-Rückgabetyp ist ...

+0

ein weiterer Unterschied: man ist eine Bridge-Methode (auch synthetisch), aber das wird nicht durch 'equals' überprüft. 'contains' verwenden die' equals' Methode, und die Dokumentation von 'Method.equals' sagt:" ... Gibt true zurück, wenn die Objekte gleich sind. Zwei Methoden sind gleich, wenn sie von derselben Klasse deklariert wurden und die gleicher Name und formale Parametertypen und Rückgabetyp. " –