Wie funktioniert das mit reflection?

Smily0412

Mitglied
Hoi,

ich würde gerne eine Funktion, deren Namen ich nur als String habe, aufrufen.

Allerdings werde ich aus dem, was ich bisher über die suche gefunden habe nicht großartig schlau.

Kann mir jemand bitte ein primitives Beispiel geben, wie ich z.B. hier die Funktion "addition" mit bestimmten Parametern aufrufen kann? (und natürlich den rückgabewert in eine variable bekommen)

Code:
class Funktions  { 
	public static int addition(int i1, int i2) {
		return i1+i2;
	}
}

thx, Smily0412
 
Hallo,

schau mal hier
http://www.tutorials.de/forum/java/277836-string-als-methoden-oder-variablennamen-verwenden.html

Java:
package de.tutorials.reflection;

import java.lang.reflect.Method;

public class ReflectionExample {
	
	public static void main(String[] args) {
		Foo foo = new Foo();
		
		try {
			Method method = Foo.class.getDeclaredMethod("machWas", /*hier muss bestimmt werden von welchem Typ die Übergabeparameter sind*/new Class[]{String.class});
			
			method.invoke(foo, /*Übergabeparameter*/new Object[]{"Hello Reflection :-)"});
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static class Foo{
		public void machWas(String text){
			System.out.println(text);
		}
	}
}

MFG

zEriX
 
hoi,
der Ansatz ist schonmal gut, danke.
Allerdings sollte das ganze bei mir noch ein stück weitergehen:

Ich habe nicht nur den Methodennamen als Variable, sondern auch die Anzahl, den Typ und den Inhalt er einzelnen Parameter bzw. Argumente.

gruß,
Smily0412
 
Das problem ist, ich bekomme wirklich sämtliche daten nur als String (eigentlich als aufruf in einem einzelnen String, aber das zerlegen bekomme ich selbst hin ^^)

Am ende müsste das im Programm dann so aussehen:
Also muss ich die einzelnen Parameter auch erst in den Datentyp konvertieren, der gefordert ist.

Code:
public class Main{
	
	public static void main(String[] args) throws Exception {
		String funcname = "addition";
		String[] paramTypes = {"int", "int", "int"};
		String[] params = {"45", "12", "3"};

		// und nu?


	}
}


class Funktions  { 
	public static int addition(int i1, int i2) {
		return i1+i2;
	}
	
	public static int addition(int i1, int i2, int i3) {
		return i1+i2;
	}
}
 
Schau mal hier
Java:
package de.tutorials.reflection;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

public class StringReflectionExample {

	private static final Map<String, Class> primitiveTypes = new HashMap<String, Class>();

	private static final Map<Class, Class> wrapperTypes = new HashMap<Class, Class>();

	public static void main(String[] args) {
		primitiveTypes.put("int", int.class);
		primitiveTypes.put("float", float.class);
		primitiveTypes.put("byte", byte.class);
		primitiveTypes.put("double", double.class);
		primitiveTypes.put("long", long.class);
		primitiveTypes.put("boolean", boolean.class);

		wrapperTypes.put(int.class, Integer.class);
		wrapperTypes.put(float.class, Float.class);
		wrapperTypes.put(long.class, Long.class);
		wrapperTypes.put(byte.class, Byte.class);
		wrapperTypes.put(double.class, Double.class);
		wrapperTypes.put(boolean.class, Boolean.class);

		String[] paramTypes = { "java.lang.String", "int" };
		String[] params = { "test", "3" };

		Foo foo = new Foo();

		try {
			Class[] classes = stringArrayToClassArray(paramTypes);
			Object[] objects = getObjectArray(params, classes);
			Method method = Foo.class.getMethod("machWas", classes);

			method.invoke(foo, objects);

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static class Foo {
		public void machWas(String text, int i) {
			System.out.println("Text="+text+" zahl="+i);
		}
	}

	private static Class[] stringArrayToClassArray(String[] classes) {
		Class[] clazzes = new Class[classes.length];

		for (int i = 0, size = classes.length; i < size; i++) {

			clazzes[i] = getClassObject(classes[i]);
		}

		return clazzes;
	}

	private static Class getClassObject(String clazz) {

		Class c = primitiveTypes.get(clazz);
		if (c == null) {
			try {
				c = Class.forName(clazz);
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			}
		}

		return c;
	}

	private static Object[] getObjectArray(String[] params, Class[] classes) {

		Object[] objects = new Object[params.length];
		for (int i = 0, size = params.length; i < size; i++) {
			if (classes[i].isPrimitive()) {
				objects[i] = parse(params[i], classes[i]);
			} else {
				objects[i] = classes[i].cast(params[i]);
			}

		}
		return objects;
	}

	private static Object parse(String param, Class clazz) {
		Class wrapperClass = wrapperTypes.get(clazz);

		Method[] methods = wrapperClass.getMethods();

		for (int i = 0, size = methods.length; i < size; i++) {
			Method method = methods[i];
			Class<?>[] parameterTypes = method.getParameterTypes();
			if (method.getName().startsWith("parse")
					&& parameterTypes.length == 1
					&& parameterTypes[0].equals(String.class)) {
				try {
					return method.invoke(null, new Object[] { param });
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
		return null;
	}
}

MFG

zEriX
 
Joa vielen dank, das hat mich erstmal ein ganzes stück weitergebracht :D

aber eine letzte frage hätte ich noch:
Code:
            method.invoke(foo, objects);
gibt es dafür eine Alternative für aufrufe von statischen methoden (also ohne ein objekt der Classe als referenz)? ich habe schon versucht einfach als ersten parameter null zu verwenden, aber das scheint nicht zu gehen.
 
Schau dir mal die Methode parse() in meinem Beispiel an, die macht genau das was du willst. Sie ruft eine statische Methode ohne Object auf.

MFG

zEriX
 
Zurück