वर्ग नाम और निर्माण निर्माता का उपयोग करके एक उदाहरण बनाना


312

क्या एक विशेष वर्ग का उदाहरण बनाने के लिए एक तरीका है जिसे कक्षा का नाम (डायनामिक) दिया गया है और इसके निर्माता को मापदंडों को पारित करना है।

कुछ इस तरह:

Object object = createInstance("mypackage.MyClass","MyAttributeValue");

जहां "MyAttributeValue"के निर्माता के लिए एक तर्क है MyClass

जवाबों:


497

हां, कुछ इस तरह:

Class<?> clazz = Class.forName(className);
Constructor<?> ctor = clazz.getConstructor(String.class);
Object object = ctor.newInstance(new Object[] { ctorArgument });

यह केवल एकल स्ट्रिंग पैरामीटर के लिए काम करेगा, लेकिन आप इसे बहुत आसानी से संशोधित कर सकते हैं।

ध्यान दें कि कक्षा का नाम पूरी तरह से योग्य होना चाहिए, यानी नाम स्थान सहित। नेस्टेड कक्षाओं के लिए, आपको एक डॉलर का उपयोग करने की आवश्यकता है (जैसा कि कंपाइलर उपयोग करता है)। उदाहरण के लिए:

package foo;

public class Outer
{
    public static class Nested {}
}

उस Classवस्तु को प्राप्त करने के लिए , आपको आवश्यकता होगी Class.forName("foo.Outer$Nested")


5
newInstance()एक varargs विधि है (बस के रूप में GetConstructor()), वहाँ स्पष्ट Object-सृजन की कोई आवश्यकता नहीं है ।
जोकिम सॉयर

18
@ जोकिम: मुझे पता है कि यह वैरिएग है, लेकिन जब आपके पास कोई Object[]तर्क होता है तो यह मुश्किल हो सकता है, मैं इस मामले में स्पष्ट रूप से सरणी बनाना पसंद करता हूं।
जॉन स्कीट

2
clazz.getConstructor (String.class); क्यों String.class यहाँ?
उमैर ए।

2
@ न्यूट्रलाइज़र: हाँ, लेकिन मैं एक सवाल का जवाब दे रहा था जहाँ उसे गतिशील होने की ज़रूरत नहीं थी।
जॉन स्कीट

3
@JonSkeet मैं समझता हूं कि आप कहां से आ रहे हैं, हालांकि यह बिल्कुल सरल नहीं है - मैंने डॉक्स को देखा, लेकिन भ्रमित था, लेकिन अगर मैंने इसका परीक्षण किया और यह काम किया - ठीक है तो यह काम किया - लेकिन अगर यह तब काम नहीं किया अगर समस्या कुछ विन्यास की कमी के कारण होती है या मेरे हिस्से में कुछ होता है, तो मैं अनिश्चित हो जाता था - अक्सर जब ऐसे सरल प्रश्न पूछते हैं, तो लोग उपयोगी tidbits में फेंक देते हैं जो वास्तव में मदद करते हैं। इसलिए एक सरल "हाँ जो काम करेगा - यदि आप इसे इस तरह करते हैं" या "कोई रास्ता नहीं है", वास्तव में मदद करता है। लेकिन मेरी समझ अब यह है कि कोई रास्ता नहीं है
ymc

97

आप इच्छित वर्ग की वस्तु Class.forName()प्राप्त करने के लिए उपयोग कर सकते हैं Class

फिर getConstructor()इच्छित Constructorवस्तु को खोजने के लिए उपयोग करें ।

अंत में, newInstance()उस वस्तु पर कॉल करके अपना नया उदाहरण प्राप्त करें।

Class<?> c = Class.forName("mypackage.MyClass");
Constructor<?> cons = c.getConstructor(String.class);
Object object = cons.newInstance("MyAttributeValue");

81

आप प्रतिबिंबों का उपयोग कर सकते हैं

return Class.forName(className).getConstructor(String.class).newInstance(arg);

3
यदि डिफॉल्ट कंस्ट्रक्टर का उपयोग किया जाता है, तो String.class पैरामीटर मान को हटाएं जैसे रिटर्न Class.forName (className) .getConstructor ()। NewInstance (arg);
विजय कुमार

21
@ वीजयकुमार मुझे लगता है कि आपका मतलब है Class.forName(className).getConstructor().newInstance();;)
पीटर लॉरी

14

यदि क्लास में केवल एक खाली कंस्ट्रक्टर (जैसे गतिविधि या फ्रैगमेंट आदि, एंड्रॉइड कक्षाएं) हैं:

Class<?> myClass = Class.forName("com.example.MyClass");    
Constructor<?> constructor = myClass.getConstructors()[0];

2
इससे मुझे मदद मिली। Constructor<?> ctor = clazz.getConstructor(String.class)मेरे लिए काम नहीं कर रहा था।
सिंह C हान

8

उपयोग करते समय (यानी) getConstructor(String.lang)कंस्ट्रक्टर को सार्वजनिक घोषित किया जाना चाहिए। नहीं तो एक NoSuchMethodExceptionफेंक दिया जाता है।

यदि आप एक गैर-सार्वजनिक निर्माणकर्ता का उपयोग करना चाहते हैं, तो आपको इसके बजाय (यानी) का उपयोग करना होगा getDeclaredConstructor(String.lang)



4

Class<?>कंस्ट्रक्टर तर्क (नों) पासिंग के साथ जावा में ऑब्जेक्ट बनाने का बहुत सरल तरीका :

केस 1: - यहाँ, इस Mainवर्ग का एक छोटा कोड है :

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class Main {

    public static void main(String args[]) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {

        // Get class name as string.
        String myClassName = Base.class.getName();
        // Create class of type Base.
        Class<?> myClass = Class.forName(myClassName);
        // Create constructor call with argument types.
        Constructor<?> ctr = myClass.getConstructor(String.class);
        // Finally create object of type Base and pass data to constructor.
        String arg1 = "My User Data";
        Object object = ctr.newInstance(new Object[] { arg1 });
        // Type-cast and access the data from class Base.
        Base base = (Base)object;
        System.out.println(base.data);
    }

}

और, यहाँ Baseवर्ग संरचना है:

public class Base {

    public String data = null;

    public Base() 
    {
        data = "default";
        System.out.println("Base()");
    }

    public Base(String arg1) {
        data = arg1;
        System.out.println("Base("+arg1+")");
    }

}

केस 2: - आप, कई तर्क और कॉपी कंस्ट्रक्टर के साथ कंस्ट्रक्टर के लिए कोड कर सकते हैं। उदाहरण के लिए, Baseकंस्ट्रक्टर के लिए पैरामीटर के रूप में 3 तर्कों को पारित करने के लिए कंस्ट्रक्टर को क्लास में बनाने की आवश्यकता होगी और उपरोक्त में एक कोड परिवर्तन होगा:

Constructor<?> ctr = myClass.getConstructor(String.class, String.class, String.class);
Object object = ctr.newInstance(new Object[] { "Arg1", "Arg2", "Arg3" }); 

और यहाँ बेस क्लास किसी तरह दिखना चाहिए:

public class Base {

    public Base(String a, String b, String c){
        // This constructor need to be created in this case.
    }   
}

नोट: - विभिन्न अपवादों को संभालना न भूलें जिन्हें कोड में संभाला जाना आवश्यक है।


एक अन्य तरीका क्लोन () मौजूदा जावा ऑब्जेक्ट द्वारा भी है। यह एक मौजूदा जावा ऑब्जेक्ट की एक प्रति बनाता है। इस मामले के लिए, आपको डीप कॉपी या शेलो कॉपी कॉन्सेप्ट को भी हैंडल करना होगा।
राहुल रैना

2

यदि कोई भी सिंगलटन पैटर्न के बाद वर्ग के बावजूद एक वर्ग का एक उदाहरण बनाने के लिए एक रास्ता खोज रहा है, तो यहां ऐसा करने का एक तरीका है।

// Get Class instance
Class<?> clazz = Class.forName("myPackage.MyClass");

// Get the private constructor.
Constructor<?> cons = clazz.getDeclaredConstructor();

// Since it is private, make it accessible.
cons.setAccessible(true);

// Create new object. 
Object obj = cons.newInstance();

यह केवल उन वर्गों के लिए काम करता है जो एक निजी कंस्ट्रक्टर का उपयोग करके सिंगलटन पैटर्न को लागू करते हैं।


1

आप बनाई गई वस्तु के अंदर तरीकों को भी लागू कर सकते हैं।

आप पहली बाधा को लागू करके ऑब्जेक्ट को तुरंत बना सकते हैं और फिर बनाई गई ऑब्जेक्ट में पहली विधि को लागू कर सकते हैं।

    Class<?> c = Class.forName("mypackage.MyClass");
    Constructor<?> ctor = c.getConstructors()[0];
    Object object=ctor.newInstance(new Object[]{"ContstractorArgs"});
    c.getDeclaredMethods()[0].invoke(object,Object... MethodArgs);

आप कैसे जानेंगे कि बहुत पहले निर्माता Stringएक पैरामीटर के रूप में लेता है ? जब आप कंस्ट्रक्टर ऑर्डर बदलते हैं तो थोड़ा गड़बड़ हो जाता है
फरीद

@ फ़ॉर क्लास डॉक्यूमेंटेशन से
बदावी

फिर भी getConstructor(ClassName.class)बेहतर है, मुझे लगता है। भले ही निर्माणकर्ताओं का क्रम कक्षा में बदल जाए, लेकिन मैन्युअल रूप से स्थिति खोजने की आवश्यकता नहीं है
फ़रीद

@ फ़रिड - c.getDeclaredMethods () [0] .invoke (ऑब्जेक्ट, ऑब्जेक्ट ... MethodArgs); विशेष निर्माता को निर्दिष्ट करता है कुछ मामलों में आपको इसकी आवश्यकता हो सकती है, लेकिन आप सही हैं।
हेटम बदावी

1

एक और मददगार जवाब। मैं getConstructor (params) .newInstance (args) का उपयोग कैसे करूँ?

return Class.forName(**complete classname**)
    .getConstructor(**here pass parameters passed in constructor**)
    .newInstance(**here pass arguments**);

मेरे मामले में, मेरी कक्षा का निर्माता वेबड्राइवर को पैरामीटर के रूप में लेता है, इसलिए नीचे दिए गए कोड का उपयोग किया जाता है:

return Class.forName("com.page.BillablePage")
    .getConstructor(WebDriver.class)
    .newInstance(this.driver);
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.