2011-04-12 11 views
50

यह this question about java private constructors पर एक फॉलोअप है।जावा: टाइप पैरामीटर के साथ निजी कन्स्ट्रक्टर तक पहुंच

मान लीजिए मैं निम्नलिखित वर्ग है:

class Foo<T> 
{ 
    private T arg; 
    private Foo(T t) { 
     // private! 
     this.arg = t; 
    } 

    @Override 
    public String toString() { 
     return "My argument is: " + arg; 
    } 
} 

मैं एक new Foo("hello") प्रतिबिंब का उपयोग कैसे बनाएगी?

उत्तर

पर jtahlborn's answer आधार पर निम्न काम करता है:

public class Example { 
    public static void main(final String[] args) throws Exception { 
     Constructor<Foo> constructor; 
     constructor = Foo.class.getDeclaredConstructor(Object.class); 
     constructor.setAccessible(true); 
     Foo<String> foo = constructor.newInstance("arg1"); 
     System.out.println(foo); 
    } 
} 
+2

यह काम नहीं करता है :( java.lang.NoSuchMethodException:। My.package.path.Foo (java.lang.Object) \t java.lang.Class.getConstructor0 (Class.java:2892) पर \t java.lang.Class.getDeclaredConstructor पर (Class.java:2058) \t ProductCatalogAgentTest.testConnect पर (ProductCatalogAgentTest.java:461) \t sun.reflect.NativeMethodAccessorImpl.invoke0 (मूल निवासी विधि) –

उत्तर

23

आप (में निर्माता जो टी के निचले बाध्य के साथ एक एकल तर्क लेता मिल जाए, वर्ग पाने के लिए की आवश्यकता होगी इस मामले ऑब्जेक्ट), कन्स्ट्रक्टर को सुलभ करने के लिए मजबूर करें (setAccessible विधि का उपयोग करके), और आखिरकार इसे वांछित तर्क के साथ बुलाएं।

+6

पर यह लेख मदद कर सकता है: http : //dunwood.blogspot.com/2004/05/instantiate-java-class-that-has.html –

33

सुनिश्चित करें कि आप कन्स्ट्रक्टर प्राप्त करते समय getDeclaredConstructors का उपयोग करें और इसकी निजीता के बाद से इसकी पहुंच सुनिश्चित करें।

ऐसा कुछ काम करना चाहिए।

Constructor<Foo> constructor= (Constructor<Foo>) Foo.class.getDeclaredConstructors()[0]; 
constructor.setAccessible(true); 
Foo obj = constructor.newInstance("foo"); 
System.out.println(obj); 

अद्यतन

आप getDeclaredConstructor का उपयोग करना चाहते हैं, तो एक तर्क जो एक सामान्य टी

Class fooClazz = Class.forName("path.to.package.Foo"); 
Constructor<Foo> constructor = fooClazz.getDeclaredConstructor(Object.class); 
constructor.setAccessible(true); 
Foo obj = constructor.newInstance("foo"); 
System.out.println(obj); 
+0

मुझे यकीन नहीं है कि क्यों, लेकिन मुझे यह अपवाद मिल रहा है कि मेरा कन्स्ट्रक्टर मौजूद नहीं है (यह अस्तित्व में है) । कोई विचार ? [अधिक जानकारी] (https://hastebin.com/usexeqanun.java) –

1

करने के लिए अनुवाद के रूप में Object.class पारित वहाँ JUnit के लिए एक पुस्तकालय है (dp4j) जो स्वचालित रूप से निजी विधियों तक पहुंचने के लिए कोड डालता है। इसका उपयोग हो सकता है।

3

जैसा कि @ArtB ने कहा है कि आप dp4j.com, का उपयोग कर सकते हैं यदि आप उस कंस्ट्रक्टर को जानते हैं जिसे आप संकलन-समय पर उपयोग करना चाहते हैं। प्रोजेक्ट होमपेज पर केवल एक उदाहरण है, जो सिंगलटन कन्स्ट्रक्टर तक पहुंच रहा है।

JUnit के @Test करने के बजाय, जिसमें @Reflect साथ प्रतिबिंब सुई विधि व्याख्या:

public class Example { 
    @com.dp4j.Reflect 
    public static void main(final String[] args){ 
     Foo<String> foo = new Foo("hello"); 
     System.out.println(foo); 
    } 
} 

प्रतिबिंब देखने के लिए this answer में के रूप में कोड उपयोग -Averbose = सच तर्क उत्पन्न।

8

अच्छी तरह से अगर निजी कन्स्ट्रक्टर कोई तर्क नहीं लेता है तो हम नए उदाहरण बनाते समय समस्या लाते हैं, इस मामले में सेट के बाद सही है हम ऑब्जेक्ट नहीं बना सकते हैं। यहां तक ​​कि construct.newInstance(null); कोई तर्क निर्माता के लिए ऑब्जेक्ट नहीं बनाएगा।

public class Singleton { 

    private static Singleton instance = new Singleton(); 

    /* private constructor */ 
    private Singleton() {} 

    public static Singleton getDefaultInstance() { 
     return instance; 
    } 
} 

हाँ हम ऊपर वर्ग की वस्तु बना सकते हैं:

हम प्रतिबिंब का उपयोग कर नीचे कोड की वस्तु बना सकते हैं।

// reflection concept to get constructor of a Singleton class. 
Constructor<Singleton> constructor = Singleton.class.getDeclaredConstructor(); 

// change the accessibility of constructor for outside a class object creation. 
constructor.setAccessible(true); 

// creates object of a class as constructor is accessible now. 
Singleton secondOb = constructor.newInstance(); 

// close the accessibility of a constructor. 
constructor.setAccessible(false); 

आप संदर्भ लें कर सकते हैं: उदाहरण 2: "उत्सुक प्रारंभ" और मेरे ब्लॉग के "प्रतिबिंब द्वारा सिंगलटन उल्लंघन": http://sanjaymadnani.wordpress.com/2014/04/14/singleton-design-pattern-in-java/

2

JUnit टेस्ट क्लास (टेस्ट फ़ोल्डर में) के रूप में एक ही पैकेज नाम है तो वास्तविक वर्ग, फिर जूनिट टेस्ट केस से, हम डीपी 4 जे जैसी अतिरिक्त लाइब्रेरी के बिना परीक्षण करने के लिए सभी निजी तरीकों को कॉल कर सकते हैं।

+0

यदि आपकी कक्षा src/main/java फ़ोल्डर में है और पैकेज में: com.temp (इस वर्ग में निजी कन्स्ट्रक्टर है) और मान लीजिए कि आपकी टेस्ट क्लास है src/test/java फ़ोल्डर में और पैकेज com.temp में। इस मामले में आप परीक्षा वर्ग के साथ वास्तविक वर्ग के निजी कन्स्ट्रक्टर तक नहीं पहुंच सकते हैं। आपको या तो dp4j लाइब्रेरी के माध्यम से या अपने स्वयं के प्रतिबिंब कोड का उपयोग करके प्रतिबिंब का उपयोग करना होगा। –