[JAVA] Utilisons la réflexion Accès aux méthodes privées

WithOne AdventCalendar Ceci est l'article du 13ème jour.

Dans cet article, le package "java.lang.reflect". Présentation de la soi-disant réflexion.

Cette fois, j'écrirai sur les méthodes "prirvate" et comment accéder aux champs. C'est facile si vous connaissez le reflet, mais "prirvate = absolument inaccessible de l'extérieur". Il semble que beaucoup de gens pensent cela.

Si vous ne le savez pas, cela affectera la progression du test Junit etc., donc je vais vous expliquer la méthode grossièrement.

Utilisons-le pour le moment

Voici les classes reçues comme arguments et les classes qui exécutent les méthodes.

TestMain.java


public class TestMain {

	/**
	 *Classe principale<br>
	 *Principal pour faire quelque chose
	 * @argument param args
	 */
	public static void main(String[] args) {
		System.out.println("Démarrer le test");

		//Le premier argument est le nom de la classe
		String className = args[0];

		//Le deuxième argument est le nom de la méthode
		String methodName = args[1];

		try {

			//Obtenez la classe
			Class<?> c = Class.forName(className);
			System.out.println("Classe d'exécution:" + c.getName());

			//Créer une instance
			Object o = c.newInstance();

			//Get méthode
			Method m = c.getMethod(methodName);
			System.out.println("Méthode d'exécution:" + m.getName());

			//Courir
			m.invoke(o);

		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			System.out.println("Terminer le test");
		}
	}
}

Eh bien, si vous regardez à l'intérieur du cadre, c'est un processus qui semble bien écrit. Lors de l'écriture d'un nom de classe dans le fichier de propriétés, c'est OK si vous pensez que le processus comme celui-ci est exécuté en interne.

Lançons-le maintenant.

image

Si vous définissez la classe et la méthode que vous souhaitez exécuter dans l'argument et exécuter ...

image

Vous pouvez voir que TestExecute.execute est en cours d'exécution.

Mais quelque chose ne va pas. Jetons un coup d'œil à TestExecute.

TestExecute.java


public class TestExecute {

	/**Drapeau d'exécution*/
	private static boolean FLG = true;

	/**
	 *Méthode d'exécution
	 */
	public void execute() {
		System.out.println("Démarrer TestExecute.execute");

		try {
			//Peu importe à quel point vous essayez
			if (FLG) {
				throw new Exception();
			}

			//Appelez une partie du processus que vous souhaitez exécuter
			prirvateMethod();

		}catch (Exception e) {
			System.out.println("Un échec s'est produit!");
		} finally {
			System.out.println("Terminer TestExecute.execute");
		}
	}

	/**
	 *Méthode privée
	 */
	private void prirvateMethod() {
		//Le processus que vous souhaitez exécuter
		System.out.println("Exécuter TestExecute.prirvateMethod");
	}
}

Puisque le champ privé "FLG" est "true", il échouera définitivement. De plus, le processus que vous souhaitez déplacer en tant que commentaire semble être "prirvateMethod ()".

Lançons ça

image

Courir!

image

Vous vous êtes fâché, "Il n'y a pas de telle méthode." Eh bien, c'est privé. Normalement, les méthodes privées sont invisibles pour le monde extérieur et ne sont pas accessibles.

Réécrivons les informations "inaccessibles"

Cependant, étant donné que "java.lang.reflect.Method" est une classe de contrôle des méthodes, le contrôle d'accès peut être modifié naturellement. Pour accéder à privé, modifiez la source comme suit.

TestMain.java


public class TestMain {

	/**
	 *Classe principale<br>
	 *Principal pour faire quelque chose
	 *
	 * @argument param args
	 */
	public static void main(String[] args) {
		System.out.println("Démarrer le test");

		//Le premier argument est le nom de la classe
		String className = args[0];

		//Le deuxième argument est le nom de la méthode
		String methodName = args[1];

		try {

			//Obtenez la classe
			Class<?> c = Class.forName(className);
			System.out.println("Classe d'exécution:" + c.getName());

			//Créer une instance
			Object o = c.newInstance();

			//Get méthode
			Method m = c.getDeclaredMethod(methodName);
			System.out.println("Méthode d'exécution:" + m.getName());

			//Changer la méthode en accessible
			m.setAccessible(true);

			//Courir
			m.invoke(o);

		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			System.out.println("Terminer le test");
		}
	}
}

"GetMethod" a été changé en "getDeclaredMethod" et une ligne "m.setAccessible (true)" a été ajoutée. Déclaré signifie qu'il a été déclaré, donc si vous l'écrivez pour le moment, vous pouvez l'utiliser ou non, mais vous l'obtiendrez! C'est une méthode appelée.

Vous pouvez l'obtenir avec "getDeclaredMethod", Il ne peut pas être exécuté simplement en le récupérant, et «java.lang.IllegalAccessException» se produit comme indiqué ci-dessous.

image

Par conséquent, utilisez "setAccessible" pour le changer de force en un état accessible.

Exécutons-le réellement.

image

Vous pouvez voir que la "méthode prirvate" est en cours d'exécution.

Réécrivons le champ privé

Mais après tout, je veux que vous exécutiez "exécuter", alors réécrivons le champ "FLG". Le champ "FLG" est privé et normalement inaccessible, mais vous pouvez le modifier pour qu'il soit accessible de la même manière qu'une méthode.

TestMain.java


public class TestMain {

	/**
	 *Classe principale<br>
	 *Principal pour faire quelque chose
	 *
	 * @param args
	 *argument
	 */
	public static void main(String[] args) {
		System.out.println("Démarrer le test");

		//Le premier argument est le nom de la classe
		String className = args[0];

		//Le deuxième argument est le nom de la méthode
		String methodName = args[1];

		try {

			//Obtenez la classe
			Class<?> c = Class.forName(className);
			System.out.println("Classe d'exécution:" + c.getName());

			//Créer une instance
			Object o = c.newInstance();

			//Obtenez le champ "FLG"
			Field f = c.getDeclaredField("FLG");
			System.out.println("Changer de champ:" + f.getName());

			//accès
			f.setAccessible(true);

			//Définir la valeur
			f.set(o, false);

			//Get méthode
			Method m = c.getMethod(methodName);
			System.out.println("Méthode d'exécution:" + m.getName());

			//Courir
			m.invoke(o);

		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			System.out.println("Terminer le test");
		}
	}
}

Courir

image

image

Vous avez pu exécuter la "méthode prirvate" lors de l'exécution de "execute".

C'est tout pour l'explication de cette réflexion. Cela a-t-il été utile?

Recommended Posts

Utilisons la réflexion Accès aux méthodes privées
méthode privée
Utilisons jcmd
[Swift] Utilisons l'extension
[Swift] Utilisons le contrôle segmenté
[RSpec] Utilisons FactoryBot [Rails]
[spring] Utilisons Spring Data JPA
Array.map facile à utiliser (&: méthode)
Utilisez Modifier # isStatic pour déterminer si la méthode [Reflection] est statique.