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