Вопрос по java, interface, reflection – Отражение Java: создайте реализующий класс

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

Как мне теперь создать новый класс, который реализуетsomeInterface?

Мне нужно создать новый класс и передать его в функцию, которая нуждается вSomeInterface в качестве аргумента.

Боюсь, создавать классы на лету совсем непросто. Michael Myers♦
@MichaelMyers Также это не так сложно,stackoverflow.com/a/9583681/632951 Pacerier

Ваш Ответ

4   ответа
71

Без труда,java.lang.reflect.Proxy в помощь!

Full working example:

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");
    }
}
Это хороший дополнительный пост к этому ответу:tutorials.jenkov.com/java-reflection/dynamic-proxies.html
Круто .. спасибо.
3

Если вы хотите выйти за рамки интерфейсов, вы можете взглянуть наCGLIB а такжеobjenesis, Вместе они позволят вам сделать довольно мощные вещи, расширяя абстрактный класс и создавая его экземпляры. (JMock использует их для этой цели, например.)

Если вы хотите придерживаться интерфейсов, делайте то, что сказал Джон Скит :).

52

Создание чего-то, что претендует на реализацию интерфейса на лету, на самом деле не так уж сложно. Ты можешь использоватьjava.lang.reflect.Proxy после реализацииInvocationHandler обрабатывать любые вызовы методов.

Конечно, вы можете создать реальный класс с такой библиотекой, какBCEL.

Если это для целей тестирования, вы должны смотреть на насмешливые рамки, такие какJMock а такжеEasyMock.

Вау, аккуратно! Интересно, что еще находится в пакете java.lang.reflect, о котором я не знаю?
-3

На самом деле, вы должны использовать имя класса в методе Class.fromName () и привести его к типу вашего интерфейса. Посмотрите, поможет ли приведенный ниже пример.

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

}
Это упускает суть вопроса. Вопрос OP немного неясен, но они ищут способ реализовать класс во время выполнения. Не просто создать объект неизвестного класса, но эффективно создать новый класс полностью.
это даже не близко к теме

Похожие вопросы