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