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

Come creare una nuova classe che implementa someInterface?Java Reflection: creare una classe di implementazione

Ho bisogno di creare una nuova classe e passarla a una funzione che ha bisogno di un SomeInterface come argomento.

+0

Creazione di classi al volo non è affatto facile, temo. –

+0

@MichaelMyers Non è poi così difficile, http://stackoverflow.com/a/9583681/632951 – Pacerier

risposta

46

Creare qualcosa che pretenda di implementare un'interfaccia al volo in realtà non è troppo difficile. È possibile utilizzare java.lang.reflect.Proxy dopo l'implementazione di InvocationHandler per gestire qualsiasi chiamata di metodo.

Ovviamente, è possibile generare una vera classe con una libreria come BCEL.

Se questo è per scopi di test, si dovrebbe guardare quadri di simulazione come jMock e EasyMock.

+2

Whoa, pulito! Mi chiedo cos'altro c'è nel pacchetto java.lang.reflect che non conosco? –

2

Se si desidera andare oltre le interfacce, si consiglia di dare un'occhiata a cglib e objenesis. Insieme, ti permetteranno di fare cose piuttosto potenti, estendendo una classe astratta e istanzializzandola. (jMock li utilizza a tale scopo, ad esempio.)

Se si desidera attenersi alle interfacce, fare ciò che Jon Skeet ha detto :).

-3

In realtà, è necessario utilizzare il nome classe nel metodo Class.fromName() e trasmettere al proprio tipo di interfaccia. Vedere se l'esempio qui sotto aiuta.

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

Manca il punto della domanda. La domanda dell'OP è un po 'poco chiara, ma stanno cercando un modo per implementare una classe in fase di esecuzione. Non semplicemente creare un oggetto di una classe sconosciuta, ma creare efficacemente una nuova classe interamente. –

+0

non è nemmeno vicino all'argomento –

63

Facilmente, java.lang.reflect.Proxy per il salvataggio!

completa esempio di lavoro:

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

Questo è un buon post aggiuntivo a questa risposta: http://tutorials.jenkov.com/java-reflection/dynamic-proxies.html – jonashackt

+0

smoove .. grazie. – kwikness

Problemi correlati