67 votes

Java Reflection: Créer une classe d'implémentation

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

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

Je dois créer une nouvelle classe et la transmettre à une fonction qui nécessite un argument SomeInterface .

75voto

Pacerier Points 15960

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

Exemple de travail complet :

 interface IRobot {

    String Name();

    String Name(String title);

    void Talk();

    void Talk(String stuff);

    void Talk(int stuff);

    void Talk(String stuff, int more_stuff);

    void Talk(int stuff, int more_stuff);

    void Talk(int stuff, String more_stuff);
}

public class Test {
    public static void main(String 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 {
                String 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. String: " + args[0]);
                        }
                        break;
                    case 2:
                        if (classes[0] == String.class) {
                            System.out.println("Hi. String: " + args[0] + ". Int: " + args[1]);
                        } else {
                            if (classes[1] == String.class) {
                                System.out.println("Hi. int: " + args[0] + ". String: " + 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");
    }
}
 

54voto

Jon Skeet Points 692016

La création de quelque chose qui fait semblant de mettre en œuvre une interface à la volée n'est pas vraiment trop difficile. Vous pouvez utiliser java.lang.reflect.Proxy après la mise en œuvre InvocationHandler pour gérer tous les appels de méthode.

Bien sûr, vous pouvez effectivement générer une véritable classe avec une bibliothèque comme BCEL.

Si c'est à des fins de test, vous devriez regarder les moqueries des frameworks comme jMock et EasyMock.

3voto

jqno Points 7831

Si vous voulez aller au-delà des interfaces, vous voudrez peut-être jeter un oeil à cglib et objenesis. Ensemble, ils vous permettront de faire quelques assez puissant, l'extension d'une classe abstraite et de son instanciation. (jMock les utilise à cette fin, par exemple.)

Si vous voulez coller avec des interfaces, de faire ce que Jon Skeet dit :).

-4voto

nandokakimoto Points 952

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

 public class Main {

    public static void main(String[] args) throws Exception {
    	Car ferrari = (Car) Class.forName("Mercedez").newInstance();
    	System.out.println(ferrari.getName());
    }
}

interface Car {
    String getName();
}

class Mercedez implements Car {

    @Override
    public String getName() {
    	return "Mercedez";
    }

}

class Ferrari implements Car {

    @Override
    public String getName() {
    	return "Ferrari";
    }

}
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X