Via Java Reflection Methoden-Parameter-Bezeichnung ermitteln

DarthShader

Erfahrenes Mitglied
Hallo,

ist es Möglich, per Java Reflection (oder auch anders :) die Bezeichnung eines Methodenparameters zu ermitteln? Das folgende Codestück

Java:
public void printMyParameterName( String parameter )
{
  // ... Name des Parameters ermitteln
  String parameterName = .....

  System.out.println( parameterName );
}

sollte die Ausgabe "parameter" haben.


Vielen Dank für Eure Hilfe!
 
Also ohne groß nachgeschaut zu haben würde ich tippen, dass es per reflection nicht möglich ist.
Du kannst die Methodensignatur auslesen.
Zur identification einer Methode ist die Signatur wichtig. Dabei ist es aber egal, wie die Parameter heißen.

Java:
public void printMyParameterName( String parameter ){
  Class c = Parametername.class;
  Method m = c.getDeclaredMethods()[0];    //Nur weil ich mir hier sicher bin, das es die einzige Methode ist            
  System.out.println( m.toString() );
}

Obs anders geht weiß ich leider auf Anhieb nicht.

Gruß
Daniel
 
Hallo,

die Namen der Parameter lassen sich nicht per Reflection auslesen (zumindest nicht mit dem normalen Reflection API) wenn die Java Class Files jedoch mit entsprechenden Debug Informationen angereichert sind (das ist AFAIK default, sofern nicht manuell per javac -g:none abgeschaltet...) sind die Informationen auf jeden Fall im Class-File zu finden... man könnte also hingehen und die Namen mit entsprechenden Bytecode Analyse Blibotheken wie ASM / BCEL analysieren.
Will man die Informationen über Parameternamen per einfacher Java Reflection verfügbar machen so kann man sich beispielsweise der Annotations bedienen:

Java:
/**
 * 
 */
package de.tutorials;

import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Method;
import java.util.Arrays;

import org.objectweb.asm.ClassReader;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.commons.EmptyVisitor;

import com.sun.org.apache.bcel.internal.Repository;
import com.sun.org.apache.bcel.internal.classfile.LocalVariable;
import com.sun.org.apache.bcel.internal.classfile.LocalVariableTable;

/**
 * @author Thomas.Darimont
 * 
 */
public class ParameterNamesViaReflection {

	/**
	 * @param args
	 */
	public static void main(String[] args) throws Exception {
		Method method = ParameterNamesViaReflection.class
				.getMethod("someOperation", new Class<?>[] { String.class,
						Integer.class });

		printParameterInfoFor(method); //Reflection + Annotations
		System.out.println("####");
		printParameterInfoFor1(method); // BCEL 
		System.out.println("####");
		printParameterInfoFor2(method); //ASM
	}

	private static void printParameterInfoFor2(final Method method) {
		try {
			new ClassReader(method.getDeclaringClass().getName()).accept(
					new EmptyVisitor() {
						@Override
						public MethodVisitor visitMethod(int access,
								String name, String desc, String signature,
								String[] exceptions) {

							if (name.equals(method.getName())) {
								org.objectweb.asm.commons.Method asmMethod = org.objectweb.asm.commons.Method
										.getMethod(method.toString());

								if (Arrays.equals(org.objectweb.asm.Type
										.getArgumentTypes(desc), asmMethod
										.getArgumentTypes())) {

									return new EmptyVisitor() {
										int currentArgumentCount;

										@Override
										public void visitLocalVariable(
												String name, String desc,
												String signature, Label start,
												Label end, int index) {
											if (currentArgumentCount++ < method
													.getParameterTypes().length) {
												System.out.println(name + " "
														+ desc);
											}
										}
									};
								}
							}

							return null;
						}
					}, 0);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	/**
	 * @param method
	 */
	private static void printParameterInfoFor1(Method method) {
		com.sun.org.apache.bcel.internal.classfile.Method bcelMethod = Repository
				.lookupClass(method.getDeclaringClass()).getMethod(method);
		LocalVariableTable localVariableTable = bcelMethod
				.getLocalVariableTable();
		for (int currentLocalVariableIndex = 0; currentLocalVariableIndex < localVariableTable
				.getTableLength(); currentLocalVariableIndex++) {
			LocalVariable localVariable = localVariableTable
					.getLocalVariable(currentLocalVariableIndex);
			if (localVariable.getStartPC() == 0) {
				System.out.println(localVariable.getName() + " "
						+ localVariable.getSignature());
			}
		}
	}

	/**
	 * @param method
	 */
	private static void printParameterInfoFor(Method method) {
		Annotation[][] parameterAnnotations = method.getParameterAnnotations();

		for (int parameterIndex = 0; parameterIndex < parameterAnnotations.length; parameterIndex++) {

			Class<?> parameterType = method.getParameterTypes()[parameterIndex];
			Named namedAnnotation = null;
			for (Annotation annotation : parameterAnnotations[parameterIndex]) {
				if (annotation.annotationType().equals(Named.class)) {
					namedAnnotation = (Named) annotation;
					break;
				}
			}
			System.out
					.println(String
							.format(
									"The parameter at index: %s of Method: %s with parameter type: %s is named by: %s",
									parameterIndex, method, parameterType,
									namedAnnotation.value()));
		}
	}

	public static void someOperation(@Named("firstArgument")
	String firstArgument, @Named("secondArgument")
	Integer secondArgument) {
		int i = 0;
		Object o = "";
	}

	public static void someOperation(@Named("firstArgument")
	String firstArgument) {
		int j = 0;
		Object u = "";
	}

	@Retention(RetentionPolicy.RUNTIME)
	@Target(ElementType.PARAMETER)
	static @interface Named {
		String value() default "";
	}
}

Ausgabe:
Code:
The parameter at index: 0 of Method: public static void de.tutorials.ParameterNamesViaReflection.someOperation(java.lang.String,java.lang.Integer) with parameter type: class java.lang.String is named by: firstArgument
The parameter at index: 1 of Method: public static void de.tutorials.ParameterNamesViaReflection.someOperation(java.lang.String,java.lang.Integer) with parameter type: class java.lang.Integer is named by: secondArgument
####
firstArgument Ljava/lang/String;
secondArgument Ljava/lang/Integer;
####
firstArgument Ljava/lang/String;
secondArgument Ljava/lang/Integer;

Gruß Tom
 

Neue Beiträge

Zurück