"Class.forName ()" और "Class.forName ()। NewInstance ()" में क्या अंतर है?


165

बीच क्या अंतर है Class.forName()और Class.forName().newInstance()?

मैं महत्वपूर्ण अंतर नहीं समझता (मैंने उनके बारे में कुछ पढ़ा है!)। कृपया आप मेरी मदद कर सकते हैं?

जवाबों:


247

हो सकता है कि दोनों तरीकों का उपयोग कैसे किया जाए, यह प्रदर्शित करने वाला एक उदाहरण आपको चीजों को बेहतर ढंग से समझने में मदद करेगा। तो, निम्न वर्ग पर विचार करें:

package test;

public class Demo {

    public Demo() {
        System.out.println("Hi!");
    }

    public static void main(String[] args) throws Exception {
        Class clazz = Class.forName("test.Demo");
        Demo demo = (Demo) clazz.newInstance();
    }
}

जैसा कि इसके javadoc में बताया गया है, दिए गए स्ट्रिंग नाम के साथ वर्ग या इंटरफ़ेस से संबंधित ऑब्जेक्ट को कॉल करता है अर्थात यह रिटर्न करता है जो प्रकार के चर पर प्रभावित होता है ।Class.forName(String) Classtest.Demo.classclazzClass

फिर, कॉलिंग इस ऑब्जेक्ट द्वारा दर्शाए गए वर्ग का एक नया उदाहरण बनाता है क्लास को तत्काल किया जाता है जैसे कि एक खाली तर्क सूची के साथ एक अभिव्यक्ति द्वारा दूसरे शब्दों में, यह वास्तव में यहाँ के बराबर है और एक नया उदाहरण देता है ।clazz.newInstance() Classnewnew Demo()Demo

और इस Demoवर्ग को चलाने से निम्न आउटपुट प्रिंट होता है:

Hi!

पारंपरिक के साथ बड़ा अंतर यह newहै कि newInstanceएक वर्ग को तुरंत चलाने की अनुमति देता है जिसे आप रनटाइम तक नहीं जानते हैं, जिससे आपका कोड अधिक गतिशील हो जाता है।

एक विशिष्ट उदाहरण JDBC API है जो रनटाइम के दौरान, कार्य करने के लिए आवश्यक सटीक ड्राइवर को लोड करता है। EJBs कंटेनर, सर्वलेट कंटेनर अन्य अच्छे उदाहरण हैं: वे गतिशील रनटाइम लोडिंग का उपयोग लोड करने और घटकों को बनाने के लिए करते हैं, जो रनटाइम से पहले कुछ भी नहीं जानते हैं।

दरअसल, अगर आप और आगे जाना चाहते हैं, तो टेड न्यूर्ड पेपर अंडरस्टैंडिंग क्लास.forName () पर एक नज़र डालें, जो कि मैं ऊपर दिए गए पैराग्राफ में देख रहा था।

EDIT (टिप्पणी के रूप में पोस्ट किए गए ओपी से एक प्रश्न का उत्तर): जेडीबीसी ड्राइवरों का मामला थोड़ा खास है। जैसा कि JDBC API के साथ आरंभ करने के DriverManager अध्याय में बताया गया है :

(...) एक Driverकक्षा भरी हुई है, और इसलिए DriverManagerदो तरीकों में से एक में स्वचालित रूप से पंजीकृत है:

  1. विधि को बुलाकर Class.forName। यह स्पष्ट रूप से चालक वर्ग को लोड करता है। चूंकि यह किसी भी बाहरी सेटअप पर निर्भर नहीं करता है, ड्राइवर को लोड करने का यह तरीका DriverManager फ्रेमवर्क का उपयोग करने के लिए अनुशंसित है । निम्नलिखित कोड कक्षा को लोड करता है acme.db.Driver:

    Class.forName("acme.db.Driver");

    यदि acme.db.Driverऐसा लिखा गया है, तो इसे लोड करने से एक उदाहरण बनता है और DriverManager.registerDriverउस उदाहरण के साथ पैरामीटर (जैसा कि यह करना चाहिए) के रूप में कॉल किया जाता है, फिर यह DriverManagerड्राइवरों की सूची में है और कनेक्शन बनाने के लिए उपलब्ध है।

  2. (...)

इन दोनों मामलों में, यह नव-भारित Driverवर्ग की जिम्मेदारी है कि वह कॉल करके खुद को पंजीकृत करे DriverManager.registerDriver। जैसा कि उल्लेख किया गया है, यह स्वचालित रूप से तब किया जाना चाहिए जब कक्षा लोड हो।

आरंभीकरण के दौरान खुद को पंजीकृत करने के लिए, JDBC ड्राइवर आमतौर पर इस तरह एक स्थैतिक आरंभीकरण ब्लॉक का उपयोग करते हैं:

package acme.db;

public class Driver {

    static {
        java.sql.DriverManager.registerDriver(new Driver());
    }

    ...
}

कॉलिंग कक्षा Class.forName("acme.db.Driver")के आरंभीकरण का कारण बनता है acme.db.Driverऔर इस प्रकार स्थैतिक आरंभीकरण ब्लॉक का निष्पादन होता है। और Class.forName("acme.db.Driver")वास्तव में एक उदाहरण "पैदा" करेगा लेकिन यह सिर्फ एक परिणाम है कि कैसे (अच्छे) JDBC ड्राइवर को लागू किया जाता है।

एक साइड नोट के रूप में, मैं उल्लेख करूंगा कि यह सब अब JDBC 4.0 (जावा 7 के बाद से डिफ़ॉल्ट पैकेज के रूप में जोड़ा गया) और JDBC 4.0 ड्राइवरों के नए ऑटो-लोडिंग फ़ीचर के साथ आवश्यक नहीं है। जावा SE 6 में JDBC 4.0 संवर्द्धन देखें ।


लेकिन अभी भी इस साइट में: java.sun.com/docs/books/tutorial/jdbc/basics/connecting.html
जोहाना

2
उपरोक्त साइट में लिखा गया है कि: "Class.forName को कॉल करना स्वचालित रूप से एक ड्राइवर का एक उदाहरण बनाता है और इसे DriverManager के साथ पंजीकृत करता है, इसलिए आपको कक्षा का एक उदाहरण बनाने की आवश्यकता नहीं है। यदि आप अपना स्वयं का उदाहरण बनाना चाहते थे। , आप एक अनावश्यक डुप्लिकेट बना रहे होंगे, लेकिन इससे कोई नुकसान नहीं होगा। " इसका मतलब है कि Class.forName से आप एक उदाहरण बनायेंगे और यदि आप दूसरा बनाना चाहते हैं तो यह एक अनावश्यक उदाहरण बना देगा इसलिए Calss.forName () और Class.forName () newInstance () दोनों एक उदाहरण बनाएंगे। चालक!!
जोहाना

10
JDBC ड्राइवर "विशेष" हैं, वे एक स्थिर इनिशियलाइज़ेशन ब्लॉक के साथ लिखे गए हैं जहाँ एक उदाहरण बनाया जाता है और पैरामीटर के रूप में पारित किया जाता है DriverManager.registerDriverClass.forNameJDBC ड्राइवर पर कॉल करना इसकी शुरुआत का कारण बनता है और इस प्रकार स्टैटिक ब्लॉक का निष्पादन होता है। उदाहरण के लिए java2s.com/Open-Source/Java-Document/Database-DBMS/… पर एक नज़र डालें । तो यह वास्तव में ड्राइवर इंटर्न के कारण एक विशेष मामला है।
पास्कल थिवेंट

1
मैंने देखा है कि एक अन्य उत्तर में , Class.newInstance () का उपयोग करते हुए दृढ़ता से हतोत्साहित किया जाता है। इसके बदले में Class.getConstructor (), Constructor.newInstance () का उपयोग करने की अनुशंसा की जाती है। यह संभव अपवादों को मास्क करने से बचता है।
एलएस

"newInstance एक ऐसे वर्ग को त्वरित करने की अनुमति देता है जिसे आप रनटाइम तक नहीं जानते हैं" मेरा दिन बना। धन्यवाद।
कोड उत्साही

37

Class.forName () आपको क्लास ऑब्जेक्ट देता है, जो प्रतिबिंब के लिए उपयोगी है। जिन तरीकों से इस ऑब्जेक्ट को जावा द्वारा परिभाषित किया गया है, न कि प्रोग्रामर द्वारा कक्षा लिखने से। वे हर वर्ग के लिए समान हैं। उस पर newInstance () कॉल करना आपको उस वर्ग का एक उदाहरण देता है (अर्थात कॉलिंग कॉलिंग के Class.forName("ExampleClass").newInstance()बराबर है new ExampleClass()), जिस पर आप उन तरीकों को कॉल कर सकते हैं जिन्हें क्लास परिभाषित करता है, दृश्यमान फ़ील्ड एक्सेस करता है आदि।


29

JDBC दुनिया में, सामान्य अभ्यास (JDBC API के अनुसार) यह है कि आप Class#forName()JDBC ड्राइवर को लोड करने के लिए उपयोग करते हैं। JDBC ड्राइवर को DriverManagerस्थैतिक ब्लॉक के अंदर खुद को पंजीकृत करना चाहिए :

package com.dbvendor.jdbc;

import java.sql.Driver;
import java.sql.DriverManager;

public class MyDriver implements Driver {

    static {
        DriverManager.registerDriver(new MyDriver());
    }

    public MyDriver() {
        //
    }

}

लागू Class#forName()सभी निष्पादित करेंगे स्थिर initializers । इस तरह DriverManagerसे कनेक्शनधारी URL के द्वारा पंजीकृत ड्राइवरों के बीच संबंधित ड्राइवर को खोजा जा सकता है, getConnection()जिसके दौरान लगभग निम्न प्रकार दिखाई देते हैं:

public static Connection getConnection(String url) throws SQLException {
    for (Driver driver : registeredDrivers) {
        if (driver.acceptsURL(url)) {
            return driver.connect(url);
        }
    }
    throw new SQLException("No suitable driver");
}

लेकिन बग्गी JDBC ड्राइवर भी थे org.gjt.mm.mysql.Driver, जो पहले से ही ज्ञात उदाहरण के साथ शुरू होते हैं , जो एक स्थिर ब्लॉक के बजाय कंस्ट्रक्टर के अंदर गलत तरीके से पंजीकृत होता है :

package com.dbvendor.jdbc;

import java.sql.Driver;
import java.sql.DriverManager;

public class BadDriver implements Driver {

    public BadDriver() {
        DriverManager.registerDriver(this);
    }

}

इसे गतिशील रूप से काम करने का एकमात्र तरीका newInstance()बाद में कॉल करना है! अन्यथा आप पहली नज़र में अस्पष्टनीय "SQLException: no उपयुक्त ड्राइवर" का सामना करेंगे। एक बार फिर, यह JDBC ड्राइवर में एक बग है, आपके अपने कोड में नहीं। आजकल, किसी भी JDBC ड्राइवर को इस बग को शामिल नहीं करना चाहिए। तो आप कर सकते हैं (और चाहिए) newInstance()दूर छोड़ दें ।


17

1: यदि आप केवल क्लास के स्टैटिक ब्लॉक में रुचि रखते हैं, तो क्लास को लोड करना ही होगा, और स्टैटिक ब्लॉक को निष्पादित करेगा, इसके बाद आपको बस जरूरत है:

Class.forName("Somthing");

2: यदि आप कक्षा को लोड करने में रुचि रखते हैं, तो इसके स्टैटिक ब्लॉक को निष्पादित करें और इसके नॉन स्टैटिक भाग को एक्सेस करना चाहते हैं, तो आपको एक उदाहरण की आवश्यकता है और फिर आपको इसकी आवश्यकता है:

Class.forName("Somthing").newInstance();

बहुत बढ़िया जवाब! स्पष्ट और संक्षिप्त!
गौरव

6

Class.forName () को Class का संदर्भ मिलता है, Class.forName ()। NewInstance () क्लास के लिए नो-आर्ग कंस्ट्रक्टर का उपयोग करके एक नया उदाहरण लौटाने की कोशिश करता है।


3

"Class.forName ()" दिए गए नाम के लिए क्लास-प्रकार लौटाता है। "newInstance ()" इस वर्ग का एक उदाहरण देता है।

प्रकार पर आप सीधे किसी भी उदाहरण के तरीकों को नहीं कह सकते, लेकिन केवल कक्षा के लिए प्रतिबिंब का उपयोग कर सकते हैं। यदि आप कक्षा के किसी ऑब्जेक्ट के साथ काम करना चाहते हैं, तो आपको इसका एक उदाहरण बनाना होगा (उसी तरह "नए MyClass ()") को कॉल करना।

"Class.forName ()" के लिए उदाहरण

Class myClass = Class.forName("test.MyClass");
System.out.println("Number of public methods: " + myClass.getMethods().length);

उदाहरण के लिए "Class.forName ()। newInstance ()"

MyClass myClass = (MyClass) Class.forName("test.MyClass").newInstance();
System.out.println("String representation of MyClass instance: " + myClass.toString());

3

उपरोक्त उत्तरों को जोड़ने पर, जब हमारे पास एक स्थिर कोड (यानी कोड ब्लॉक स्वतंत्र है), जिसे मेमोरी में मौजूद रहने की आवश्यकता है, तो हम कक्षा में वापस आ सकते हैं इसलिए हम Class.forname ("someName") का उपयोग करेंगे यदि हम स्टैटिक कोड न होने के कारण हम Class.forname ()। newInstance ("someName") के लिए जा सकते हैं क्योंकि यह ऑब्जेक्ट लेवल कोड ब्लॉक (नॉन स्टैटिक) को मेमोरी में लोड करेगा


1

कोई फर्क नहीं पड़ता कि आप कितनी बार Class.forName () पद्धति को कॉल करते हैं, केवल एक बार स्थिर ब्लॉक निष्पादित होने पर कई बार नहीं:

पैकेज forNameMethodDemo;

सार्वजनिक वर्ग मेनक्लास {

    public static void main(String[] args) throws Exception {
        Class.forName("forNameMethodDemo.DemoClass");
        Class.forName("forNameMethodDemo.DemoClass");
        Class.forName("forNameMethodDemo.DemoClass");
        DemoClass demoClass = (DemoClass)Class.forName("forNameMethodDemo.DemoClass").newInstance();
    }

}

पब्लिक क्लास डेमोक्लास {

static {
    System.out.println("in Static block");
}

{
    System.out.println("in Instance block");
}

}

आउटपुट होगा:

in Static block in Instance block

यह in Static blockकथन केवल एक बार नहीं तीन बार छपा है।


0

Class.forName () -> forName () क्लास क्लास की स्टैटिक विधि है, जो क्लास क्लास ऑब्जेक्ट को रिफ्लेक्ट करती है, न कि क्लास क्लास ऑब्जेक्ट का इस्तेमाल किया जाता है, इसलिए आप केवल क्लास क्लास के तरीकों को इस पर कॉल कर सकते हैं जैसे getMethods (), getConstructors () आदि।

यदि आप अपने (केवल रनटाइम) वर्ग के स्थिर ब्लॉक को चलाने के बारे में परवाह करते हैं और केवल अपनी कक्षा के तरीकों, निर्माणकर्ताओं, संशोधक आदि की जानकारी प्राप्त कर रहे हैं, तो आप इस ऑब्जेक्ट के साथ कर सकते हैं जिसे आप Class.forName () का उपयोग करके प्राप्त करते हैं

लेकिन अगर आप अपने क्लास मेथड (उस क्लास की क्लास को एक्सेस या कॉल करना चाहते हैं जो आपने रनटाइम में दी है) तो आपको उसकी ऑब्जेक्ट की जरूरत है इसलिए क्लास क्लास का न्यू इनस्टेंस मेथड आपके लिए है। यह क्लास का नया इंस्टेंस बनाएं और उसे आपको लौटा दें। .आपको इसे अपनी कक्षा में टाइप करने की जरूरत है।

ex-: मान लीजिए कि कर्मचारी आपकी कक्षा का है

कक्षा a = Class.forName (args [0]);

// args [0] = रनटाइम पर क्लास देने के लिए cmd लाइन तर्क।

कर्मचारी ob1 = a.newInstance ();

a.newInstance () नए कर्मचारी () का उपयोग करके ऑब्जेक्ट बनाने के समान है।

अब आप अपने सभी कक्षा दृश्य क्षेत्रों और विधियों का उपयोग कर सकते हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.