Problem mit dynamischem Methodenaufruf

karfy

Grünschnabel
Hallo,

irgendwie fehlt mir hier der Durchblick, woran es bei mir hapert. Die Klasse sollte eigentlich den Wert aus myF ersetzen und dann ausgeben. Lasse ich das ganze mit dem Debugger laufen, erhalte ich das richtige Ergebnis. Lasse ich die Application ganz normal laufen, bekomme ich Exception aber kein Ergebnis. Vielleicht hat von euch jemand einen Rat für mich?

Code:
package bonin;

import java.lang.reflect.*;

public class Foo {
	private String slot;

	public String getSlot() {
		return slot;
	}

	public void setSlot(String slot) {
		this.slot = slot;
	}

	Foo(String slot) {
		this.slot = slot;
	}

	public static void main(String[] args) {
		Foo myF = new Foo("Just started");
		Class myClass = myF.getClass();
		System.out.println("Class: " + myClass.getName());
		Method[] myMethods = myClass.getDeclaredMethods();
		for (int i = 0; i < myMethods.length; i++) {
			Method m = myMethods[i];
			System.out.println("Method: " + m);
		}
		try {
			Field slot = myClass.getDeclaredField("slot");
			slot.setAccessible(true);
			try {
				Object[] arguments = new Object[] { "Hello World" };
				Method m2 = myMethods[2];
				slot.set(myF, "mama");
				m2.invoke(myF, arguments);
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			} 
			catch (InvocationTargetException e) {
				e.printStackTrace();
			}
			try {
				Method m1 = myMethods[1];
				System.out.println("47: " + m1.invoke(myF, null));
			
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			} catch (InvocationTargetException e) {
				e.printStackTrace();
			}
		} catch (SecurityException e1) {
			e1.printStackTrace();
		} catch (NoSuchFieldException e1) {
			e1.printStackTrace();
		}
	}
}
 
Der StackTrace würde wirklich helfen.

Ist bei dir vielleicht eine Methode oder ein Feld private? In dem Fall versuchs mal mit setAccessible(true) vor dem Aufruf.
 
Ähm ok, seh ich ein, ohne die Exception ist es vielleicht ein wenig sinnbefreit, das einzustellen, hier die Exception, die ich erhalte:

Code:
Class: bonin.Foo
Method: public void bonin.Foo.setSlot(java.lang.String)
Method: public static void bonin.Foo.main(java.lang.String[])
Method: public java.lang.String bonin.Foo.getSlot()
java.lang.IllegalArgumentException: wrong number of arguments
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.lang.reflect.Method.invoke(Unknown Source)
	at bonin.Foo.main(Foo.java:36)
java.lang.IllegalArgumentException: wrong number of arguments
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.lang.reflect.Method.invoke(Unknown Source)
	at bonin.Foo.main(Foo.java:47)

/Edit

Und das erhalte ich mit einem Debug-Lauf:

Code:
Class: bonin.Foo
Method: public static void bonin.Foo.main(java.lang.String[])
Method: public java.lang.String bonin.Foo.getSlot()
Method: public void bonin.Foo.setSlot(java.lang.String)
47: Hello World
 
Zuletzt bearbeitet:
@zeja: Der String slot ist private, den habe ich, weil ich das ebenfalls vermutet habe, direkt angesprochen und per .setAccessible zugreifbar gemacht. Das sollte aber eigentlich kein Grund für den Fehler sein, da ich lediglich über die Methoden zugreifen wollte, die soweit public bzw. friendly (beim Konstruktor) sind, wobei der Konstruktor eigentich nicht angesprochen werden dürfte, wenn ich .getDeclaredMethods() richtig verstanden habe.

Den müsste ich dann ja über getConstructor()[0] direkt aufgreifen ([0] weil es ja nur den einen gibt, wenn ich das richtig aufgenommen habe).
 
Hmm ist schon ziemlich schwer zu lesen dein code da oben ;)

Ruf doch mal mit getDeclaredMethod(name) explizit die Methode ab die du Aufrufen möchtest, statt das über das Array zu machen. Dann achte darauf einer Methode die Argumente erwartet nicht im invoke als zweiten Parameter null zu übergeben. Das darfst du nur bei Methoden ohne Argumente. Daher kommt wohl auch die Exception.
 
Ich habe den Fehler mittlerweile gefunden, das ist aber auch zu blöd gewesen.

Der Debug-Modus hat richtig gearbeitet, weil er die Methoden in einer anderen Reihenfolge in das Array geschrieben hat und dementsprechend die richtigen Methoden an den angegebenen Positionen zu finden waren.

Ich habe mir einfach direkt nach der Zuweisung der Methode aus dem Array den Methodennamen anzeigen lassen.

Ablauf im Debugger:

[0] --> main-Methode
[1] --> getSlot-Methode
[2] --> setSlot-Methode

Einfacher Application-Ablauf:

[0] --> setSlot
[1] --> main
[2] --> getSlot

Warum das nun zu Stande kommt, das verstehe ich überhaupt nicht, weil mir sich damit der Sinn des debugging im Bereich invoke nicht erschließen will, aber zumindest ist der Fehler erkannt und beseitigt (für dieses Mal :) ).
 

Neue Beiträge

Zurück