Class someInterface = Class.fromName("some.package.SomeInterface");
Wie erstelle ich jetzt eine neue Klasse, die implementiert someInterface
?
Ich muss eine neue Klasse erstellen und sie an eine Funktion übergeben, SomeInterface
die ein Argument benötigt.
java
reflection
interface
Isaac Waller
quelle
quelle
Antworten:
Es ist nicht allzu schwierig, etwas zu erstellen, das vorgibt, eine Schnittstelle im laufenden Betrieb zu implementieren. Sie können
java.lang.reflect.Proxy
nach der ImplementierungInvocationHandler
alle Methodenaufrufe verarbeiten.Natürlich können Sie mit einer Bibliothek wie BCEL tatsächlich eine echte Klasse generieren .
Wenn dies zu Testzwecken dient, sollten Sie sich spöttische Frameworks wie jMock und EasyMock ansehen .
quelle
Leicht
java.lang.reflect.Proxy
zur Rettung!Vollständiges Arbeitsbeispiel :
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"); } }
quelle
Wenn Sie über Schnittstellen hinausgehen möchten, sollten Sie sich cglib und objenesis ansehen . Zusammen ermöglichen sie es Ihnen, einige ziemlich mächtige Dinge zu tun, eine abstrakte Klasse zu erweitern und sie zu instanziieren. ( jMock verwendet sie beispielsweise zu diesem Zweck.)
Wenn Sie sich an Schnittstellen halten möchten, tun Sie, was Jon Skeet gesagt hat :).
quelle
Tatsächlich müssen Sie den Klassennamen in der Methode Class.fromName () verwenden und in Ihren Schnittstellentyp umwandeln. Überprüfen Sie, ob das folgende Beispiel hilft.
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"; } }
quelle