[JAVA] Verwenden wir Reflection Private Method Access

WithOne AdventCalendar Dies ist der Artikel am 13. Tag.

In diesem Artikel das Paket "java.lang.reflect". Einführung der sogenannten Reflexion.

Dieses Mal werde ich über "Prirvate" -Methoden und den Zugriff auf Felder schreiben. Es ist einfach, wenn Sie die Reflexion kennen, aber "prirvate = von außen absolut unzugänglich". Es scheint, dass es ziemlich viele Leute gibt, die das denken.

Wenn Sie es nicht wissen, wirkt es sich auf den Fortschritt des Junit-Tests usw. aus, daher werde ich die Methode grob erläutern.

Lassen Sie es uns vorerst verwenden

Im Folgenden sind die als Argumente empfangenen Klassen und die Klassen aufgeführt, die die Methoden ausführen.

TestMain.java


public class TestMain {

	/**
	 *Hauptklasse<br>
	 *Haupt, um etwas zu tun
	 * @param args Argument
	 */
	public static void main(String[] args) {
		System.out.println("Starten Sie TestMain");

		//Das erste Argument ist der Klassenname
		String className = args[0];

		//Das zweite Argument ist der Methodenname
		String methodName = args[1];

		try {

			//Holen Sie sich Klasse
			Class<?> c = Class.forName(className);
			System.out.println("Ausführungsklasse:" + c.getName());

			//Erstellen Sie eine Instanz
			Object o = c.newInstance();

			//Methode abrufen
			Method m = c.getMethod(methodName);
			System.out.println("Ausführungsmethode:" + m.getName());

			//Lauf
			m.invoke(o);

		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			System.out.println("Beenden Sie TestMain");
		}
	}
}

Wenn Sie sich das Framework ansehen, scheint es ein Prozess zu sein, der gut geschrieben zu sein scheint. Wenn Sie einen Klassennamen in die Eigenschaftendatei schreiben, ist es in Ordnung, wenn Sie glauben, dass der Prozess wie dieser intern ausgeführt wird.

Lass es uns jetzt laufen lassen.

image

Wenn Sie die Klasse und Methode festlegen, die Sie im Argument ausführen möchten, und ...

image

Sie können sehen, dass TestExecute.execute ausgeführt wird.

Aber etwas stimmt nicht. Werfen wir einen Blick auf TestExecute.

TestExecute.java


public class TestExecute {

	/**Ausführungsflag*/
	private static boolean FLG = true;

	/**
	 *Ausführungsmethode
	 */
	public void execute() {
		System.out.println("Starten Sie TestExecute.execute");

		try {
			//Ganz egal wie sehr du es versuchst
			if (FLG) {
				throw new Exception();
			}

			//Rufen Sie einen Teil des Prozesses auf, den Sie ausführen möchten
			prirvateMethod();

		}catch (Exception e) {
			System.out.println("Fehler aufgetreten!");
		} finally {
			System.out.println("Beenden Sie TestExecute.execute");
		}
	}

	/**
	 *Private Methode
	 */
	private void prirvateMethod() {
		//Der Prozess, den Sie ausführen möchten
		System.out.println("Führen Sie TestExecute aus.prirvateMethod");
	}
}

Da das private Feld "FLG" "wahr" ist, wird es definitiv fehlschlagen. Darüber hinaus scheint der Prozess, den Sie tatsächlich als Kommentar verschieben möchten, "prirvateMethod ()" zu sein.

Lassen Sie uns das ausführen

image

Lauf!

image

Sie wurden wütend: "Es gibt keine solche Methode." Nun, es ist privat. Private Methoden sind normalerweise für die Außenwelt unsichtbar und können nicht aufgerufen werden.

Lassen Sie uns die Informationen "unzugänglich" umschreiben

Da "java.lang.reflect.Method" eine Klasse zur Steuerung von Methoden ist, kann die Zugriffssteuerung selbstverständlich geändert werden. Um auf privat zuzugreifen, ändern Sie die Quelle wie folgt.

TestMain.java


public class TestMain {

	/**
	 *Hauptklasse<br>
	 *Haupt, um etwas zu tun
	 *
	 * @param args Argument
	 */
	public static void main(String[] args) {
		System.out.println("Starten Sie TestMain");

		//Das erste Argument ist der Klassenname
		String className = args[0];

		//Das zweite Argument ist der Methodenname
		String methodName = args[1];

		try {

			//Holen Sie sich Klasse
			Class<?> c = Class.forName(className);
			System.out.println("Ausführungsklasse:" + c.getName());

			//Erstellen Sie eine Instanz
			Object o = c.newInstance();

			//Methode abrufen
			Method m = c.getDeclaredMethod(methodName);
			System.out.println("Ausführungsmethode:" + m.getName());

			//Ändern Sie die Methode in zugänglich
			m.setAccessible(true);

			//Lauf
			m.invoke(o);

		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			System.out.println("Beenden Sie TestMain");
		}
	}
}

"GetMethod" wurde in "getDeclaredMethod" geändert und eine Zeile "m.setAccessible (true)" wurde hinzugefügt. Deklariert bedeutet, dass es deklariert wurde. Wenn Sie es also vorerst schreiben, können Sie es verwenden oder nicht, aber Sie werden es bekommen! Es ist eine Methode namens.

Sie können es mit "getDeclaredMethod" erhalten, Es kann nicht einfach durch Abrufen ausgeführt werden, und "java.lang.IllegalAccessException" tritt wie unten gezeigt auf.

image

Verwenden Sie daher "setAccessible", um es zwangsweise in einen zugänglichen Zustand zu ändern.

Lassen Sie es uns tatsächlich ausführen.

image

Sie können sehen, dass die "Prirvate-Methode" ausgeführt wird.

Lassen Sie uns das private Feld neu schreiben

Aber schließlich möchte ich, dass Sie "execute" ausführen, also schreiben wir das Feld "FLG" neu. Das Feld "FLG" ist privat und normalerweise nicht zugänglich. Sie können es jedoch so ändern, dass es wie eine Methode zugänglich ist.

TestMain.java


public class TestMain {

	/**
	 *Hauptklasse<br>
	 *Haupt, um etwas zu tun
	 *
	 * @param args
	 *Streit
	 */
	public static void main(String[] args) {
		System.out.println("Starten Sie TestMain");

		//Das erste Argument ist der Klassenname
		String className = args[0];

		//Das zweite Argument ist der Methodenname
		String methodName = args[1];

		try {

			//Holen Sie sich Klasse
			Class<?> c = Class.forName(className);
			System.out.println("Ausführungsklasse:" + c.getName());

			//Erstellen Sie eine Instanz
			Object o = c.newInstance();

			//Feld "FLG" abrufen
			Field f = c.getDeclaredField("FLG");
			System.out.println("Feld ändern:" + f.getName());

			//Zugriff
			f.setAccessible(true);

			//Wert einstellen
			f.set(o, false);

			//Methode abrufen
			Method m = c.getMethod(methodName);
			System.out.println("Ausführungsmethode:" + m.getName());

			//Lauf
			m.invoke(o);

		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			System.out.println("Beenden Sie TestMain");
		}
	}
}

Lauf

image

image

Sie konnten die "Prirvate-Methode" ausführen, während Sie die "Execute" ausführen.

Das ist alles für die Erklärung dieser Reflexion. War es hilfreich?

Recommended Posts

Verwenden wir Reflection Private Method Access
private Methode
Verwenden wir jcmd
[Swift] Verwenden wir die Erweiterung
[Swift] Verwenden wir die segmentierte Steuerung
[RSpec] Verwenden wir FactoryBot [Rails]
[spring] Verwenden wir Spring Data JPA
Einfach zu bedienende array.map (&: Methode)
Verwenden Sie den Modifikator # isStatic, um festzustellen, ob die Methode [Reflection] statisch ist.