2010-11-17 20 views
35

मैंने अभी java.sql package के बारे में सीखा। DriverManager तक फैले ड्राइवर को गतिशील रूप से लोड करने के लिए यह Class.forName() का उपयोग करता है। फिर हमें DriverManager.getConnection() विधि का उपयोग करके कनेक्शन मिलता है।कक्षा.forनाम() कैसे काम करता है?

तो कैसे पूरी बात काम करता है?
ड्राइवर प्रबंधक वर्ग कैसे जानता है कि वास्तविक ड्राइवर के वर्ग नाम का उपयोग किए बिना कनेक्शन कैसे प्राप्त करें।

इसके अलावा हम कस्टम अनुप्रयोगों के लिए Class.forName() का उपयोग कर सकते हैं ... अगर यह एक उदाहरण मैं बहुत खुश होंगे साथ समझाया गया है।

class Foo { 
    static { 
     System.out.println("Foo initializing"); 
    } 
} 

public class Test { 
    public static void main(String [] args) throws Exception { 
     Class.forName("Foo"); 
    } 
} 

सभी प्रक्रिया के बारे में आप बात कर रहे हैं के बाकी JDBC-विशिष्ट है:

+0

इसके अलावा http://stackoverflow.com/a/8053125/632951 – Pacerier

उत्तर

51

Class.forName बस इस तरह अपनी स्थिर initializers चल रहा है, सहित एक वर्ग है, लोड करता है। चालक - जो Driver लागू करता है, यह DriverManager का विस्तार नहीं करता है - DriverManager.registerDriver का उपयोग करके बस एक उचित उदाहरण पंजीकृत करता है। फिर जब DriverManager को किसी विशेष कनेक्शन स्ट्रिंग के लिए ड्राइवर ढूंढने की आवश्यकता होती है, तो यह प्रत्येक पंजीकृत ड्राइवर पर acceptsURL को तब तक कॉल करता है जब तक कोई कहता है, "हाँ, मैं उस कनेक्शन के लिए ड्राइवर बन सकता हूं।"

ध्यान दें कि ड्राइवरों को पंजीकृत करने का यह तरीका उचित रूप से पुराना है - डेटा स्रोत पर जाने के अधिक आधुनिक तरीकों के लिए DriverManager के दस्तावेज़ों को देखें।

+0

मेरी क्वेरी देखना 1 लाइन से हल आप श्रीमान का जवाब के लिए है। – Simmant

+2

@ जोन अच्छा उदाहरण है, लेकिन 'class.forysame (" com.mysql.jdbc.Driver ") के लिए' com.mysql.jdbc.Driver' क्लास कहां है; 'जैसा कि मैंने com.mysql.jdbc.Driver आयात करने की कोशिश की 'अभी भी काम नहीं करता – UnKnown

+2

@UnKown: यह MySQL जार फ़ाइल में है। लेकिन आपको इसे आयात करने की आवश्यकता नहीं है - आप आमतौर पर जेडीबीसी को इसे सीधे शुरू करने देते हैं, और आप केवल अपने कोड में जेडीबीसी कक्षाओं का उल्लेख करते हैं। –

12

Class.forName(..) भार और लक्ष्य वर्ग initializes। । बदले में इसका मतलब है कि स्थिर प्रारंभकर्ता ब्लॉक लागू कर रहे हैं (कोड, static { .. } में परिभाषित

उदाहरण के लिए आप को देखो, तो MySQL के ड्राइवर, कि स्थिर ब्लॉक में चालक खुद को पंजीकृत किया गया है: DriverManager.registerDriver(new Driver());

आप छोड़ सकते हैं Class.forName(..) और ड्राइवर रजिस्टर अपने आप को अगर आप MySQL के ड्राइवर पर संकलन समय निर्भरता "बर्दाश्त" कर सकते हैं।

कहा यही कारण है, यह शायद ही कभी Class.forName(..) उपयोग करने के लिए आपके आवेदन से कक्षाएं प्रारंभ करने में प्रासंगिक हो जाएगा, क्योंकि संकलन समय निर्भरता है वहां कोई मुद्दा नहीं है।

यह भी ध्यान दें कि Class.forName(..)is no longer required संस्करण 4 के बाद से जेडीबीसी के लिए। service provider तंत्र का उपयोग करके आप ड्राइवर प्रबंधक को सिस्टम प्रॉपर्टी द्वारा लोड करने के लिए निर्देश दे सकते हैं।

3

कारण है कि Class.forName() अक्सर एसक्यूएल उदाहरण में बताया गया है, क्योंकि वहाँ JDBC DriverManager बताने के लिए कैसे कोई वास्तविक चालक को प्रदान की जाती JDBC यूआरएल मैप करने के लिए कोई जादू था।

उदा। "mysql" को किसी दिए गए MySQL क्लास, "पतली" मानचित्रों को ओरेकल क्लास, "as400" मानचित्रों को डीबी 2/400 वर्ग में मैप करना चाहिए।

स्पष्ट रूप से वर्ग लोड हो रहा है से, यह अनुमति वर्ग DriverManager साथ ही पंजीकरण के भीतर कोड चलाने के लिए।

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

4

जब हम नए ऑपरेटर का उपयोग एक वर्ग का एक instace बनाने के लिए, यह दो बातें

  1. लोड वर्ग स्मृति करने के लिए, अगर यह लोड नहीं है करता है - जो वर्ग के नि: स्मृति प्रतिनिधित्व बनाने का मतलब .class फ़ाइल से ताकि एक उदाहरण इसे से बनाया जा सके। इसमें स्थैतिक चर प्रारंभ करना (उस वर्ग का समाधान)
  2. उस वर्ग का एक उदाहरण बनाएं और चर के संदर्भ को संग्रहीत करें।

Class.forName केवल पहली चीज करता है। यह कक्षा को स्मृति में लोड करता है और कक्षा के उदाहरण के रूप में उस संदर्भ को वापस करता है। अगर हम एक उदाहरण बनाना चाहते हैं, तो हम उस वर्ग की नई इंस्टेंस विधि को कॉल कर सकते हैं। जो डिफ़ॉल्ट कन्स्ट्रक्टर (कोई तर्क कन्स्ट्रक्टर) का आह्वान करेगा। ध्यान दें कि यदि डिफ़ॉल्ट कन्स्ट्रक्टर पहुंच योग्य नहीं है, तो नया इंस्टेंस विधि IllegalAccessException फेंक देगा। और यदि कक्षा एक अमूर्त वर्ग या इंटरफ़ेस है या इसमें डिफ़ॉल्ट कन्स्ट्रक्टर नहीं है, तो यह InstantiationException फेंक देगा। यदि उस वर्ग के समाधान के दौरान कोई अपवाद उत्पन्न होता है, तो यह ExceptionInInitializerError फेंक देगा।

यदि डिफ़ॉल्ट कन्स्ट्रक्टर परिभाषित नहीं किया गया है, तो हमें प्रतिबिंब API का उपयोग करके डिफेंडर कन्स्ट्रक्टर का आह्वान करना होगा।

लेकिन Class.forName के साथ मुख्य लाभ यह है कि यह वर्ग नाम को स्ट्रिंग तर्क के रूप में स्वीकार कर सकता है। तो हम गतिशील रूप से कक्षा का नाम पारित कर सकते हैं। लेकिन अगर हम नए ऑपरेटर का उपयोग करके कक्षा का उदाहरण बनाते हैं, तो कक्षा का नाम गतिशील रूप से बदला नहीं जा सकता है।

Class.forName() घुमाव कॉलर क्लासलोडर के लोड क्लास विधि को कॉल करेगा (कक्षा के क्लासलोडर जहां से Class.forName लागू किया गया है)।

डिफ़ॉल्ट रूप से, Class.forName() उस कक्षा को हल करता है। जिसका अर्थ है, उस वर्ग के अंदर सभी स्थैतिक चर शुरू करें। ही Class.forName(String name,boolean initialize,ClassLoader loader)

का उपयोग कर Class.forName() है लोड हो रहा है JDBC ड्राइवर के लिए मुख्य कारण के अतिभारित पद्धति का उपयोग करके बदला जा सकता है, ड्राइवर गतिशील रूप से परिवर्तित कर सकते हैं। स्थिर ब्लॉक में सभी ड्राइवर्स स्वयं का एक उदाहरण बनाएंगे और DriverManager.registerDriver() विधि का उपयोग कर DriverManager के साथ उस श्रेणी को पंजीकृत करेंगे। डिफ़ॉल्ट रूप से Class.forName(String className) कक्षा को हल करने के बाद से, यह स्थिर प्रारंभकर्ता प्रारंभ करेगा। तो जब हम Class.forName("com.sun.jdbc.odbc.JdbcOdbcDriver") फोन, ड्राइवर वर्ग लोड किया जाएगा, instanciated और

DriverManager

साथ पंजीकृत तो अगर आप नए ऑपरेटर आप है प्रयोग कर रहे हैं निम्नलिखित बातें करने के लिए।
कोड:

Driver drv = new com.sun.jdbc.odbc.JdbcOdbcDriver(); 
DriverManager.registerDriver(drv); 
संबंधित मुद्दे