Механизм отражения Java: создать класс, реализующий
Class someInterface = Class.fromName("some.package.SomeInterface");
как мне теперь создать новый класс, который реализует someInterface?
мне нужно создать новый класс, и передать его в функцию, которая нужна SomeInterface в качестве аргумента.
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