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

अब मैं एक नई कक्षा कैसे बना सकता हूं जो someInterface लागू करता है?जावा प्रतिबिंब: एक कार्यान्वयन वर्ग

मुझे एक नई कक्षा बनाने की आवश्यकता है, और इसे एक ऐसे फ़ंक्शन पर पास करें जिसे SomeInterface को तर्क के रूप में चाहिए।

+0

मक्खी पर कक्षाएं बनाना बिल्कुल आसान नहीं है, मुझे डर लग रहा। –

+0

@ माइकलमेयर्स यह भी मुश्किल नहीं है, http://stackoverflow.com/a/9583681/632951 – Pacerier

उत्तर

46

कुछ ऐसा बनाना जो फ्लाई पर एक इंटरफेस को लागू करने का नाटक करता है वास्तव में बहुत कठिन नहीं है। किसी भी विधि कॉल को संभालने के लिए InvocationHandler लागू करने के बाद आप java.lang.reflect.Proxy का उपयोग कर सकते हैं।

बेशक, आप वास्तव में BCEL जैसी लाइब्रेरी के साथ एक वास्तविक कक्षा उत्पन्न कर सकते हैं।

यदि यह परीक्षण उद्देश्यों के लिए है, तो आपको jMock और EasyMock जैसे नकली ढांचे को देखना चाहिए।

+2

वाह, साफ! मुझे आश्चर्य है कि java.lang.reflect पैकेज में और क्या है जो मुझे नहीं पता? –

2

यदि आप इंटरफेस से आगे जाना चाहते हैं, तो आप cglib और objenesis पर एक नज़र डालना चाहेंगे। साथ में, वे आपको कुछ सुंदर शक्तिशाली सामान करने, एक अमूर्त वर्ग का विस्तार करने और इसे तुरंत चालू करने की अनुमति देंगे। (jMock उदाहरण के लिए, उस उद्देश्य के लिए उनका उपयोग करता है।)

यदि आप इंटरफेस के साथ रहना चाहते हैं, तो जॉन स्कीट ने क्या कहा :)।

-3

असल में, आपको कक्षा.फ्रेमनाम() विधि में कक्षा का नाम उपयोग करना होगा और अपने इंटरफ़ेस प्रकार पर डालना होगा। देखें कि नीचे नमूना मदद करता है या नहीं।

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

यह प्रश्न के बिंदु को याद करता है। ओपी का सवाल थोड़ा अस्पष्ट है, लेकिन वे रन टाइम पर कक्षा को लागू करने का एक तरीका ढूंढ रहे हैं। न केवल अज्ञात वर्ग का एक वस्तु बनाएं बल्कि प्रभावी ढंग से एक नई कक्षा बनाएं। –

+0

यह विषय के करीब भी नहीं है –

63

आसानी से, 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"); 
    } 
} 
+0

यह इस उत्तर के लिए एक अच्छा अतिरिक्त पोस्ट है: http://tutorials.jenkov.com/java-reflection/dynamic-proxies.html – jonashackt

+0

smoove .. धन्यवाद। – kwikness

संबंधित मुद्दे