Java Reflection: Utwórz klasę implementującą

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

Jak teraz utworzyć nową klasę, która implementuje someInterface?

Muszę utworzyć nową klasę i przekazać ją do funkcji, która potrzebuje SomeInterface jako argumentu.

Author: Daniel Rikowski, 2009-07-04

4 answers

Stworzenie czegoś, co udaje zaimplementowanie interfejsu w locie, w rzeczywistości nie jest zbyt trudne. Możesz użyć java.lang.reflect.Proxy po wdrożeniu InvocationHandler do obsługi dowolnych wywołań metod.

Oczywiście, możesz wygenerować prawdziwą klasę z biblioteką taką jak BCEL .

Jeśli jest to do celów testowych, powinieneś spojrzeć na szydercze frameworki, takie jak jMock i EasyMock .

 50
Author: Jon Skeet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-04 19:53:44

Łatwo, java.lang.reflect.Proxy na ratunek!

Pełny przykład roboczy :

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 ProxyTest {
    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");
    }
}
 68
Author: Pacerier,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-19 08:59:21

Jeśli chcesz wyjść poza interfejsy, możesz rzucić okiem na cglib i objenesis . Razem pozwolą Ci zrobić całkiem potężne rzeczy, rozszerzając abstrakcyjną klasę i tworząc jej instancję. ( jMock używa ich w tym celu, na przykład.)

Jeśli chcesz trzymać się interfejsów, zrób to, co powiedział Jon Skeet :).

 2
Author: jqno,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-04 20:06:25

Właściwie, musisz użyć nazwy klasy w klasie.metoda fromName() i cast do typu interfejsu. Sprawdź, czy poniższa próbka pomoże.

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";
    }

}
 -3
Author: nandokakimoto,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-04 21:01:03