2012-09-03 7 views
6

मैं जावा में नया हूं। एक बात मुझे भ्रमित करती है कि क्यों कुछ कक्षाओं को तत्काल करने के लिए new की आवश्यकता है, और क्यों कुछ अन्य को तत्काल करने के लिए new की आवश्यकता नहीं है।क्यों कुछ कक्षाओं को इसके उदाहरण बनाते समय "नया" शब्द की आवश्यकता नहीं है?

उदाहरण के लिए, मैं log4j को देख रहा हूं, इसे new की आवश्यकता नहीं है।

कुछ अन्य वर्गों को नए क्यों चाहिए? उदाहरण के लिए, एक कर्मचारी वर्ग:

Employee X = new Employee (John); 
X.getwork(); 

आदि आदि

हम क्यों नहीं कहा, Logger logger = new Logger(...);? और हम इसे new के बिना भी उपयोग करने में सक्षम थे, जैसे logger.setLevel(), आदि

+3

[फैक्टरी विधि पैटर्न] (http://en.wikipedia.org/wiki/Factory_method_pattern) – oldrinb

+0

'Logger.getLogger' आंतरिक रूप से 'नया लॉगर' कॉल करता है। हमेशा एक कन्स्ट्रक्टर कॉल हमेशा होता है - बस * आपके * कोड में नहीं। – Blorgbeard

+0

वाह इस समय बहुत कम जवाब में बहुत सारे जवाब हैं ... – Doorknob

उत्तर

0

आपके उदाहरण में आपको अलग-अलग मामलों का उपयोग करना होगा: स्थैतिक विधि जो ऑब्जेक्ट और वास्तविक कन्स्ट्रक्टर कॉल देता है।

स्थिर विधि एक विधि है कि एक वस्तु पर कॉल करने की आवश्यकता नहीं है, यहाँ यह भीतरी तंत्र एक वस्तु का दृष्टांत और यह futur उपयोग के लिए लौटने के लिए, इस विधि में कठिनाई हो सकती है, वहाँ एक फोन है करने के लिए 'नई' लेकिन ऑब्जेक्ट को कॉन्फ़िगर किया जा सकता है, या वापस आने से पहले कैश से पुनर्प्राप्त किया जा सकता है। इस कॉल

Logger logger = Logger.getLogger("com.foo"); 

वास्तविक निर्माता कॉल (जो नए का उपयोग करें) है नई वस्तु बनाने के लिए सामान्य तरीके से इस तरह का है।

1

क्योंकि Logger.getLogger()Logger ऑब्जेक्ट देता है। new Logger() कन्स्ट्रक्टर को कॉल करता है जो Logger भी देता है। यह भी एक तरह से new भी उपयोग करता है, क्योंकि Logger वर्ग के अंदर शायद की तरह कुछ है:

public class Logger { 
    public static Logger getLogger() { 
     return new Logger("foo", "bar"); 
    } 
} 
0

आप तकनीकी रूप से लॉगर वर्ग का उपयोग नहीं कर रहे थे, लेकिन एक विधि का उपयोग कर रहे थे। आप लॉगर क्लास को तकनीकी रूप से तत्काल नहीं कर रहे थे, न ही Logger logger = new Logger() के साथ सीधे इसका संदर्भ रखते थे। इसके बजाय, आप जो कर रहे हैं वह लौटा हुआ उदाहरण वापस पाने के लिए एक विधि तक पहुंच रहा है। वर्ग परिभाषा देखना अच्छा लगेगा। हालांकि, आपके पास जो भी है, उससे अधिक कक्षा के अंदर एक स्थिर विधि है। और कक्षा एक निजी निर्माता के साथ परिभाषित की तुलना में अधिक है। यह वर्ग को तत्काल किए बिना विधियों तक पहुंचा जा सकता है। आप यहां जावा और स्थिर में एक अच्छी व्याख्या देख सकते हैं: https://stackoverflow.com/a/1844388/1026459

+0

वह लॉगर क्लास का उपयोग कर रहा था, बस कन्स्ट्रक्टर (सीधे) को कॉल नहीं कर रहा था। – Blorgbeard

+0

@ ब्लॉगरबीर्ड - मुझे इसे फिर से बदलना चाहिए। –

7

जावा में एक नई वस्तु बनाने का एकमात्र तरीका new [1] के साथ है। हालांकि, कुछ कक्षाओं में, आपको अपने लिए new कहने की अनुमति नहीं है, आपको फ़ैक्टरी विधि को कॉल करना होगा, जो स्थिर हो सकता है (जैसा कि आपके लॉगर उदाहरण के साथ) या नहीं। एक वर्ग के लेखक ने इसे रचनाकारों को public के अलावा एक्सेस करने के द्वारा सेट अप किया है।

यह भी ध्यान रखें कि आपके उदाहरण में एक नई वस्तु शामिल नहीं हो सकती है। वह Logger फ़ंक्शन एक पुरानी वस्तु को वापस कर रहा है, न कि नया।

ओग्डेन नैश द्वारा निम्नलिखित कविता धुँधली-सी प्रासंगिक लगता है:

This morning I went to the zoo 
In order to look at the gnu. 
But the old gnu was dead, 
and the new gnu, they said, 
Was too new a new gnu to view. 

[1] जब तक आप निम्न स्तर के प्रतिबिंब में शामिल हो सकते हैं, या Object.clone()

+0

नए ऑपरेटर के विकल्प हैं: http://stackoverflow.com/questions/95419/what-are-all-the- अलग-ways-to-create-an-object-in-java – maba

1

उदाहरण के लिए, कुछ वर्गों से रोक सकता है आवेदन में एक से अधिक वस्तुएं बनाना। यह मामला आपको लॉगर को तुरंत चालू करने के लिए कुछ विधि कॉल करने की आवश्यकता है, जैसे Logger.getLogger()। GetLogger() में इस तरह का कोड हो सकता है:

if(uniqueInstance == null) { 
    uniqueInstance = new Logger(); 
} 

return uniqueInstance; 

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

कक्षा को तुरंत चालू नहीं करने का कोई अन्य तरीका यह है कि कक्षा को स्थैतिक के रूप में परिभाषित किया जाता है।

कक्षाएं जिनके पास सार्वजनिक निर्माता हैं और नए कीवर्ड के साथ तत्काल आवश्यकता नहीं है।

0

कुछ वर्गों को स्वयं के बाहर तत्काल नहीं किया जा सकता है (उदाहरण के लिए Math कक्षा, इन वर्गों में गैर-सार्वजनिक निर्माता हैं)। उन वर्गों में से कुछ कुछ ऐसे तरीके प्रदान करते हैं जो कक्षा के उदाहरण लौटाते हैं (उदा। InetAddress कक्षा)। इन्हें कारखाने के तरीके कहा जाता है। वे static विधियां हैं जो कक्षा के उदाहरण लौटाती हैं, इसलिए new कीवर्ड का उपयोग नहीं किया जाना चाहिए (इसे फ़ैक्टरी विधियों के अंदर उपयोग किया जाता है)। उदाहरण के लिए:

public class A { 
    private A() {} 
    public A createAnA() { return new A(); } 
} 

यहां, createAnA() फैक्ट्री विधि है।

3

इस मामले में, हम फैक्ट्री विधियों से निपट रहे हैं, जैसा कि मैंने my comment में कहा था।

नाम पैरामीटर का मान के अनुसार नाम एक लकड़हारा पुनः प्राप्त Logger

पर प्रासंगिक एपीआई विनिर्देश देखें। यदि नामित लॉगर पहले से मौजूद है, तो मौजूदा उदाहरण वापस कर दिया जाएगा। अन्यथा, एक नया उदाहरण बनाया गया है।

डिफ़ॉल्ट रूप से, लॉगर्स के पास सेट स्तर नहीं होता है लेकिन इसे अपने पूर्ववर्ती पूर्वजों से सेट स्तर के साथ प्राप्त होता है। यह log4j की केंद्रीय विशेषताओं में से एक है।

factory method pattern एक creational डिज़ाइन पैटर्न है, और, विकिपीडिया के अनुसार, अक्सर निम्न स्थितियों में उपयोगी है:

कारखाने पैटर्न इस्तेमाल किया जा सकता है जब:

  • निर्माण किसी ऑब्जेक्ट का कोड के महत्वपूर्ण डुप्लिकेशन के बिना इसका पुन: उपयोग रोकता है।
  • किसी ऑब्जेक्ट के निर्माण के लिए ऐसी जानकारी या संसाधनों तक पहुंच की आवश्यकता होती है जो रचना कक्षा में शामिल नहीं होनी चाहिए।
  • जेनरेट की गई वस्तुओं के आजीवन प्रबंधन को एप्लिकेशन के भीतर लगातार व्यवहार सुनिश्चित करने के लिए केंद्रीकृत किया जाना चाहिए।

इन तीनों यहाँ लागू होते हैं ... कौन जानता है किस तरह का काम सही लकड़हारा खोजने में चला जाता है? जब भी आप एक का उपयोग करना चाहते हैं, तो आप वास्तव में एक नया नया लॉगर बनाने में रूचि नहीं रखते हैं ... इसके बजाय, आपका ध्यान मुख्य रूप से केवल एक का उपयोग करें।

  • कुछ भाषाओं (जैसे कि जावा) अनुमति नहीं देते:

    क्रिएटिव कॉमन्स विकी भी एक relevant article,

    फैक्टरी तरीकों कभी कभी कई कारणों में से किसी के लिए निर्माताओं के स्थान पर उपयोग किया जाता है है उपयोगी नाम रखने के लिए रचनाकार

  • कुछ भाषाओं (जैसे जावा) रचनाकारों को अलग-अलग नाम रखने की अनुमति नहीं देते हैं (यदि आवश्यक हो तो यदि आप दो रचनाकारों के लिए एक ही विधि हस्ताक्षर का उपयोग करना चाहते हैं)
  • एक ही उदाहरण के बजाय पुन: उपयोग किया जा करने के लिए निर्मित हर बार यह आवश्यक है अनुमति देने के लिए (FlyweightPattern देख)

मुझे लगता है कि तीसरा विकल्प शायद यहाँ सबसे लागू है। एक नए Logger के मैन्युअल निर्माण का उपयोग करके, आप उन्हें पर्याप्त रूप से साझा करने में असमर्थ हैं। getLogger मुखौटा का उपयोग करके पारदर्शी रूप से ऐसा करने में सक्षम बनाता है।

सब कुछ, फैक्ट्री विधियों का उपयोग आम तौर पर उस काम को उजागर किए बिना क्लीनर को अधिक सीधे-आगे कोड सक्षम करने के लिए सक्षम करता है, जिसकी आपको आवश्यकता नहीं है।

1

वैसे जो आप पूछ रहे हैं वह डिजाइन पैटर्न से अधिक संबंधित है। लॉगर क्लास सिंगलटन पैटर्न का पालन कर रहा है।

मान लीजिए कि आप चाहते हैं कि आपकी कक्षा का केवल एक ही उदाहरण एप्लिकेशन में बनाया गया हो, तो आप अपने कन्स्ट्रक्टर को निजी बना सकते हैं और एक स्थिर विधि प्रदान कर सकते हैं जो पहली बार आमंत्रित होने पर आपकी कक्षा के ऑब्जेक्ट को बनाता और संग्रहीत करता है।

सार्वजनिक वर्ग SingletonPattern {

 private static SingletonPattern instance; 

    private SingletonPattern(){} 

    public static synchronized SingletonPattern getInstance(){ 
     if (instance == null){ 
      instance = new SingletonPattern(); 
     } 
     return instance; 
    } 
} 

इस तरह से आप अपने वर्ग सीमित कर सकते हैं में केवल एक बार instantiated किया जाना है।

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