Механизм отражения Java: создать класс, реализующий



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


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



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

515   4  

4 ответов:

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

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

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

легко java.lang.reflect.Proxy на помощь!

полный рабочий пример:

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

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

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

на самом деле, вы должны использовать имя класса в класс.метод 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";
    }

}

Comments

    Ничего не найдено.