2009-07-04 15 views
56
Class someInterface = Class.fromName("some.package.SomeInterface"); 

Wie erstelle ich jetzt eine neue Klasse, die someInterface implementiert?Java Reflection: Erstellen Sie eine implementierende Klasse

Ich muss eine neue Klasse erstellen und an eine Funktion übergeben, die ein SomeInterface als Argument benötigt.

+0

Erstellen von Klassen on the fly ist gar nicht so einfach, ich habe Angst. –

+0

@MichaelMyers Es ist nicht so schwer wie gut, http://StackOverflow.com/a/9583681/632951 – Pacerier

Antwort

46

Etwas zu erstellen, das vorgibt, eine Schnittstelle im laufenden Betrieb zu implementieren, ist nicht allzu schwer. Sie können java.lang.reflect.Proxy nach der Implementierung InvocationHandler verwenden, um alle Methodenaufrufe zu verarbeiten.

Natürlich könnten Sie tatsächlich eine echte Klasse mit einer Bibliothek wie BCEL erzeugen.

Wenn dies für Testzwecke ist, sollten Sie spöttische Frameworks wie jMock und EasyMock betrachten.

+2

Whoa, ordentlich! Ich frage mich, was sonst noch im Paket java.lang.reflect ist, von dem ich nichts weiß? –

2

Wenn Sie über die Schnittstellen hinausgehen möchten, sollten Sie einen Blick auf cglib und objenesis werfen. Zusammen ermöglichen sie Ihnen, einige ziemlich mächtige Dinge zu tun, eine abstrakte Klasse zu erweitern und sie zu instantiieren. (jMock verwendet sie für diesen Zweck, zum Beispiel.)

Wenn Sie mit Schnittstellen bleiben wollen, tun, was Jon Skeet sagte :).

-3

Eigentlich müssen Sie den Klassennamen in Class.fromName() -Methode verwenden und zu Ihrem Schnittstellentyp umwandeln. Sehen Sie, ob das Beispiel unten 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"; 
    } 

} 
+1

Das vermisst den Punkt der Frage. Die Frage des OP ist etwas unklar, aber sie suchen nach einer Möglichkeit, eine Klasse zur Laufzeit zu implementieren. Erstellen Sie nicht einfach ein Objekt einer unbekannten Klasse, sondern erstellen Sie effektiv eine neue Klasse. –

+0

es ist nicht einmal in der Nähe des Themas –

63

Leicht, java.lang.reflect.Proxy zur Rettung!

Voll funktions Beispiel:

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

Dies ist ein guter zusätzlicher Beitrag zu dieser Antwort: http://tutorials.jenkov.com/java-reflection/dynamic-proxies.html – jonashackt

+0

smoove .. danke. – kwikness

Verwandte Themen