Java Reflection: créez une classe d’implémentation

Class someInterface = Class.fromName("some.package.SomeInterface"); 

Comment puis-je créer une nouvelle classe qui implémente someInterface ?

J’ai besoin de créer une nouvelle classe et de la transmettre à une fonction qui nécessite un SomeInterface comme argument.

Créer quelque chose qui prétend implémenter une interface à la volée n’est en fait pas trop difficile. Vous pouvez utiliser java.lang.reflect.Proxy après avoir implémenté InvocationHandler pour gérer les appels de méthode.

Bien sûr, vous pourriez réellement générer une vraie classe avec une bibliothèque comme BCEL .

Si ceci est à des fins de test, vous devriez regarder les frameworks moqueurs comme jMock et EasyMock .

Facilement, java.lang.reflect.Proxy à la rescousse!

Exemple de travail complet :

 interface IRobot { Ssortingng Name(); Ssortingng Name(Ssortingng title); void Talk(); void Talk(Ssortingng stuff); void Talk(int stuff); void Talk(Ssortingng stuff, int more_stuff); void Talk(int stuff, int more_stuff); void Talk(int stuff, Ssortingng more_stuff); } public class ProxyTest { public static void main(Ssortingng args[]) { IRobot robot = (IRobot) java.lang.reflect.Proxy.newProxyInstance( IRobot.class.getClassLoader(), new java.lang.Class[] { IRobot.class }, new java.lang.reflect.InvocationHandler() { @Override public Object invoke(Object proxy, java.lang.reflect.Method method, Object[] args) throws java.lang.Throwable { Ssortingng method_name = method.getName(); Class[] classes = method.getParameterTypes(); if (method_name.equals("Name")) { if (args == null) { return "Mr IRobot"; } else { return args[0] + " IRobot"; } } else if (method_name.equals("Talk")) { switch (classes.length) { case 0: System.out.println("Hello"); break; case 1: if (classes[0] == int.class) { System.out.println("Hi. Int: " + args[0]); } else { System.out.println("Hi. Ssortingng: " + args[0]); } break; case 2: if (classes[0] == Ssortingng.class) { System.out.println("Hi. Ssortingng: " + args[0] + ". Int: " + args[1]); } else { if (classes[1] == Ssortingng.class) { System.out.println("Hi. int: " + args[0] + ". Ssortingng: " + args[1]); } else { System.out.println("Hi. int: " + args[0] + ". Int: " + args[1]); } } break; } } return null; } }); System.out.println(robot.Name()); System.out.println(robot.Name("Dr")); robot.Talk(); robot.Talk("stuff"); robot.Talk(100); robot.Talk("stuff", 200); robot.Talk(300, 400); robot.Talk(500, "stuff"); } } 

Si vous voulez aller au-delà des interfaces, vous pouvez regarder cglib et objenesis . Ensemble, ils vous permettront de faire des choses assez puissantes, d’étendre une classe abstraite et de l’instancier. ( jMock les utilise à cette fin, par exemple.)

Si vous voulez restr avec les interfaces, faites ce que Jon Skeet a dit :).

En fait, vous devez utiliser le nom de la classe dans la méthode Class.fromName () et le convertir en votre type d’interface. Voir si l’échantillon ci-dessous aide.

 public class Main { public static void main(Ssortingng[] args) throws Exception { Car ferrari = (Car) Class.forName("Mercedez").newInstance(); System.out.println(ferrari.getName()); } } interface Car { Ssortingng getName(); } class Mercedez implements Car { @Override public Ssortingng getName() { return "Mercedez"; } } class Ferrari implements Car { @Override public Ssortingng getName() { return "Ferrari"; } }