2009-12-25 17 views
7

Tengo un pequeño problema en mi códigoproblema en el GetDeclaredMethods (Java)

tengo 2 clases

public class A { 

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

public class B extends A{ 

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

ahora en mi código Quiero imprimir sólo el método que fue declarado en la clase B

de esta manera

B b = new B(); 

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

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

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

por qué la salida es

foo 

foo 

¿por qué GetDeclaredMethods encuentra también el foo en la clase A? ¿cómo puedo solucionarlo?

gracias

Respuesta

0

Puede llamar m.getDeclaringClass() para ver si es el Método de Clase A o Clase B.

+0

en ambos casos el getDeclaringClass devuelve B – Dazel

1

Por defecto, todos los getDeclaredMethods() rendimientos de los métodos para la clase dada, así ya que es clases e interfaces para padres. Sin embargo, el objeto Method le permite probar a qué clase pertenece un Method llamando al getDeclaringClass() en ese Method. Por lo tanto, cuando recorra todos los objetos Method, puede agregar lógica para imprimir solo un método si pertenece a la clase B.

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: El código anterior no funciona como se desea - se devuelve B como la clase de todos los métodos que se declara. El método isSynthetic() parece funcionar como se desea, devolviendo verdadero para un método reemplazado (uno que vino de A), pero falso para uno que vino de B. Entonces, el siguiente código podría ser lo que estás buscando.

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

lo siento, pero esto no es la solución correcta sigo teniendo 2 foo en la salida – Dazel

+0

Lemme ejecutarlo y ver cuál es el problema ... –

+0

he encontrado el método isSynthetic() Devuelve falso para el foo original en la clase B y devuelve verdadero para el foo de la clase A pero como no estoy familiarizado con el método isSynthetic() No estoy seguro de que este sea el uso correcto de la misma. ¿Es este el lugar correcto para usar este método? – Dazel

1

Porque B.foo y A.foo son métodos diferentes. Si desea reemplazar el método A.foo, entonces el método B.foo debe devolver la clase A.

+0

Respuesta correcta, por lo tanto +1, pero no está muy bien expresado si aún no entiendes la respuesta. – Yishai

0

Esto puede funcionar:

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

La razón por la que está teniendo un problema es debido a los tipos de retorno covariantes de tus dos métodos Como tiene un tipo de retorno covariante (el tipo de retorno de B es B, no A, a diferencia de la superclase), Java bajo el capó genera un método separado con el tipo de retorno original para actuar como un puente entre la especificación del código de bytes anterior a la 1.5 nuevo comportamiento del lenguaje Java 1.5.

Sin embargo, el método que debe utilizar para verificar es el método isBridge(), ya que expresa exactamente lo que tiene la intención de excluir. Por lo que el código final sería algo como esto:

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

for (Method method : methods) { 

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

Parece ser la solución a mi problema, gracias ¿Pero cuál es la diferencia entre IsBridge() y isSynthetic()? – Dazel

+2

@Dazel, básicamente isBridge identifica cosas que hace el compilador de Java para adaptarse a las características del lenguaje Java introducidas por Generics en las limitaciones del bytecode. isSynthetic te dice si el método se genera de forma sintética, qué métodos de puente son, pero también lo son más cosas, como algunos elementos de las clases internas. Entonces, un puente siempre es sintético, pero un sintético no siempre es un puente. Pensando aún más en esto, sintético podría ser lo que más te importa, el método no existe en el código fuente, no te importa por qué. – Yishai

+0

Bien, nunca me di cuenta de esto. Parece que algunas de las cosas que tuvieron que hacer para que Java funcione con las especificaciones 1.5 y superiores son ... interesantes. –

0

Cuando se dice que si (! AMethods.contains (m)) no contiene comparan por su nombre? tipo de argumentos? tipo de valor de retorno? porque la única diferencia del método deseado al no es el tipo de retorno de covarianza ...

+0

otra diferencia: uno es un método de puente (también sintético), pero esto no se comprueba con 'iguales'). 'contains' utiliza el método' equals', y la documentación de 'Method.equals' dice:" ... Devuelve true si los objetos son iguales. Dos métodos son iguales si fueron declarados por la misma clase y tienen el mismo nombre y tipos de parámetros formales y tipo de devolución ". –