what reflexion programming principio method ejemplos java reflection

programming - reflexion java ejemplos



¿Hay alguna manera de obtener los nombres de los parámetros del método en Java? (8)

Esta pregunta ya tiene una respuesta aquí:

Escribo un framework pequeño y muy DRY , que depende en gran medida de los metadatos. Me gustaría saber si hay una forma de obtener nombres de parámetros de métodos, es decir, dado algún método

public void a(int myIntParam, String theString) { ... }

obtener las cadenas "myIntParam" y "theString" .

Sé que podría anotar parámetros, pero eso no sería bueno ...

public void a( @Param("myIntParam") int myIntParam, @Param("theString") String theString ) { ... }


@bobwienholt es correcto: los nombres de los parámetros no se compilan en clases Java, por lo que no están disponibles en tiempo de ejecución.



Podría estar equivocado sobre esto ... pero no creo que los nombres de los parámetros aparezcan en un archivo de clase, así que supongo que no hay forma de obtenerlos a través de la reflexión.


Aquí hay una solución sucia que necesita algunos ajustes. Tal vez alguien pueda hacerlo mejor.

Contras:

  • Requiere que conozca la ubicación del archivo de clase compilado.
  • Tiene que compilarse con la bandera -g.

Código:

import com.sun.org.apache.bcel.internal.classfile.ClassParser; import com.sun.org.apache.bcel.internal.classfile.JavaClass; import com.sun.org.apache.bcel.internal.classfile.LocalVariable; import com.sun.org.apache.bcel.internal.classfile.Method; import java.io.IOException; public class Main { public static void main(String[] args) throws IOException { ClassParser parser = new ClassParser("Main.class"); JavaClass clazz = parser.parse(); for (Method m : clazz.getMethods()) { System.out.println("Method: " + m.getName()); int size = m.getArgumentTypes().length; if (!m.isStatic()) { size++; } for (int i = 0; i < size; i++) { LocalVariable variable = m.getLocalVariableTable().getLocalVariable(i); System.out.println(" - Param: " + variable.getName()); } } } public void a(int myIntParam, String theString) { } }

Salida:

$ javac -g Main.java
$ java Main
Method: <init>
- Param: this
Method: main
- Param: args
Method: a
- Param: this
- Param: myIntParam
- Param: theString


El nombre de los parámetros está presente en el archivo de clase, cuando el código de Java se compiló con información de depuración (a través de la opción -g). El archivo de clase contiene un atributo LocalVariableTable (consulte http://java.sun.com/docs/books/jvms/second_edition/html/ClassFile.doc.html#5956 ). Esto contiene los nombres de las variables locales y los parámetros son solo variables locales. Los parámetros corresponden a las ranuras variables que comienzan en el índice 1 (o el índice 0 para los métodos estáticos).


Los nombres de los parámetros están disponibles a través de apt (ahora parte de javac).


Creamos una anotación personalizada para el método que contiene una cadena [] de nombres de parámetros. Este enfoque se sintió un poco más fácil de administrar que tener que anotar cada parámetro individual. Planeamos agregar verificación de tiempo de compilación para que la cantidad de nombres de parámetros anotados coincida con la cantidad de argumentos, ya que es lo que necesitamos.


Si estás usando Spring estás de suerte. Simplemente agregue esto a su applicationContext.xml:

<bean class="org.springframework.core.LocalVariableTableParameterNameDiscoverer"/>

Entonces puedes inyectar este frijol donde sea necesario:

@Autowired private ParameterNameDiscoverer parameterNameDiscoverer; Method m = ... String[] names = parameterNameDiscoverer.getParameterNames(m);

Como su nombre lo sugiere, esta implementación se basa en clases compiladas con información de depuración.