2012-02-10 19 views
15

की रक्षात्मक प्रति एक कैलेंडर ऑब्जेक्ट की रक्षात्मक प्रति बनाने वाली विधि को लागू करने का सबसे अच्छा तरीका खोजने का प्रयास कर रहा था।कैलेंडर

जैसे:

public void setDate(Calendar date) { 
    // What to do.... 
} 

मैं धागे की इंटरलिविंग के बारे में विशेष रूप से चिंतित हूँ जब अशक्त इनपुट के लिए जाँच और प्रतिलिपि बनाने या मैं बहुत स्पष्ट कुछ याद आ रही है?

+1

क्लोन के साथ समस्या क्या है? (मुझे वास्तव में दिलचस्पी है) – zeller

+0

अच्छा बिंदु, हाँ क्लोन अच्छा है अगर ऑब्जेक्ट स्वयं विस्तार योग्य नहीं है, दुर्भाग्यवश कैलेंडर (ग्रेगोरियन कैलेंडर) है, लेकिन अगर मुझे यकीन है कि ऑब्जेक्ट कैलेंडर है और कोई अन्य शरारती सबक्लास नहीं है तो क्लोन का उपयोग किया जा सकता है। असल में मैं उसी वर्ग के गेटटर में क्लोन विधि का उपयोग कर रहा हूं क्योंकि मुझे यकीन है कि मेरा आंतरिक कैलेंडर वास्तव में है। –

+0

मुझे लगता है, आप सही हैं। लेकिन यदि वस्तु उस वर्ग का है जिसे आप समर्थन नहीं देना चाहते हैं तो आप इसकी प्रतिलिपि को रोक सकते हैं, है ना? – zeller

उत्तर

22

(एक अलग दर्शकों को अब लक्ष्य के साथ, मुझे लगता है कि ...)

मैं clone() का प्रयोग करेंगे, तो मैं बिल्कुल (Joda टाइम के बजाय) सब पर Calendar का इस्तेमाल किया था। आप टिप्पणियों में बहस करते हैं कि आप "शरारती उप-वर्ग" के बारे में चिंतित हैं - आप में योजना के आसपास काम करने का प्रस्ताव कैसे देंगे? यदि आप शामिल उप-वर्गों के बारे में कुछ भी नहीं जानते हैं, और उन पर भरोसा नहीं करते हैं, तो आपके पास टाइप-विशिष्ट डेटा को संरक्षित करने का कोई तरीका नहीं है। यदि आप सबक्लास पर भरोसा नहीं करते हैं तो गड़बड़ नहीं करते हैं, तो आपको सामान्य रूप से बड़ी समस्याएं मिलती हैं। तिथि/समय गणना करते समय आपको सही परिणाम देने के लिए आप इस पर भरोसा कैसे करते हैं?

clone() वस्तुओं क्लोनिंग की उम्मीद तरीका है: यह है जहां मैं एक समझदार उपवर्ग किसी भी प्रकार के विशिष्ट व्यवहार यह आवश्यक में हुक करने उम्मीद थी। आपको यह जानने की जरूरत नहीं है कि राज्य के कौन से बिट प्रासंगिक हैं - आप बस उस प्रकार से निपटने दें।

खुद Calendar.getInstance() का उपयोग करने और गुण स्थापित करने से अधिक लाभ:

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

संपादित करें: date पैरामीटर का मूल्य जो कुछ अन्य थ्रेड कर नहीं बदलेगा: "धागा इंटरलिविंग" के बारे में जो मूल प्रश्न चिंताओं के संदर्भ में। हालांकि, यदि आप एक रक्षात्मक प्रतिलिपि लेते समय ऑब्जेक्ट की सामग्री को म्यूट कर रहे हैं, तो बहुत आसानी से समस्याएं पैदा कर सकता है। यदि यह जोखिम है, तो मूल रूप से आपके पास बड़ी समस्याएं हैं।

15

सबसे आसान तरीका होगा:

copy = Calendar.getInstance(original.getTimeZone()); 
copy.setTime(original.getTime()); 

लेकिन मैं दृढ़ता से सुझाव है कि (जब भी संभव हो) आप JodaTime का उपयोग जावा में समय और तारीखें व्यक्त करते हैं। इसमें अपरिवर्तनीय कक्षाएं और उत्परिवर्तनीय हैं।

+2

मुझे लगता है कि यह सुनिश्चित नहीं करेगा कि कैलेंडर एक ही होंगे टाइमज़ोन – zeller

+0

हाँ, मुझे यह पसंद है कि यह कहां जा रहा है, मैं एक शून्य मूल्य की जांच करते समय समवर्ती धागे के बीच अंतःक्रिया के बारे में चिंतित था और इसके परिणामस्वरूप प्रतिलिपि को मूल के टाइमस्टैम्प पर सेट कर रहा था, मुझे लगता है कि यह एक समस्या है जिसे मैं जा रहा हूं साथ रहने के लिए। हाँ, मैंने जोडाटाइम के बारे में बहुत अच्छी बातें सुनी हैं, मुझे स्वीकार करना होगा कि मुझे इसके साथ कोई अनुभव नहीं है :) :) एक नज़र डालेंगे। –

+2

@ ज़ेलर आप समय क्षेत्र के बारे में सही हैं। मैंने उदाहरण संपादित किया है। –

1

बस अपने कैलेंडर ऑब्जेक्ट को थ्रेडलोकल में लपेटें। यह गारंटी देगा कि कैलेंडर का प्रत्येक उदाहरण केवल एक थ्रेड द्वारा उपयोग किया जाता है। कुछ ऐसा:

public class ThreadLocalCalendar 
{ 
    private final static ThreadLocal <Calendar> CALENDAR = 
     new ThreadLocal <Calendar>() 
     { 
      @Override 
      protected Calendar initialValue() 
      { 
       GregorianCalendar calendar = new GregorianCalendar(); 

       // Configure calendar here. Set time zone etc. 

       return calendar; 
      } 
     }; 

    // Called from multiple threads in parallel 
    public void foo() 
    { 
     Calendar calendar = CALENDAR.get(); 

     calendar.setTime (new Date()); 
     // Use calendar here safely, because it belongs to current thread 
    } 
} 
0

यह गारंटी देना असंभव है!

थ्रेड सुरक्षा: तब तक सुनिश्चित नहीं किया जा सकता जब तक आप उस पार्टी द्वारा लागू सुरक्षा योजना के बारे में नहीं जानते जहां से आपको संदर्भ मिला। वह पार्टी आपको एक नया संदर्भ दे सकती थी जिस स्थिति में आप बस संदर्भ का उपयोग कर सकते हैं। वह पार्टी उस कैलेंडर संदर्भ के संबंध में अपनी सुरक्षा योजना प्रकाशित कर सकती थी, इस मामले में आप गैर-शून्य संदर्भों की जांच करने के लिए एक ही योजना का पालन कर सकते हैं (कभी-कभी संभव नहीं होगा), फिर getInstance() का उपयोग करके रक्षात्मक रूप से प्रतिलिपि बनाएँ । इन्हें जानने के बिना, मुझे लगता है कि थ्रेड सुरक्षा सुनिश्चित करना असंभव है।

कैलेंडर की रक्षात्मक प्रतिलिपि: क्लोनिंग एक विकल्प नहीं है यदि आप उस स्थान पर भरोसा नहीं करते जहां से आपको संदर्भ मिला है! कैलेंडर किसी भी कन्स्ट्रक्टर का समर्थन नहीं करता है जो मौजूदा कैलेंडर ऑब्जेक्ट लेता है और एक नया बनाता है!

संक्षेप में, आपकी समस्या को हल करने का कोई तरीका नहीं है। जोडाटाइम आगे का सबसे अच्छा तरीका है।

-2

मैं यहां "सिंक्रनाइज़ ब्लॉक" के उपयोग का सुझाव दूंगा।

+0

सिंक्रनाइज़ेशन रक्षात्मक प्रतिलिपि लेने के बारे में कुछ भी नहीं करेगा। –

2

मुझे पता है कि यह पुराना है लेकिन मैंने सोचा कि मैं अपने दो सेंट डाल दूंगा।

यदि आप अनुबंध द्वारा प्रोग्राम करते हैं, तो ऑब्जेक्ट किसी अन्य ऑब्जेक्ट की गलतियों के लिए ज़िम्मेदार नहीं है। कैलेंडर क्लोनेबल लागू करता है, जिसका अर्थ है उप-वर्ग भी करते हैं! यदि कैलेंडर का उप-वर्ग क्लोनेबल अनुबंध तोड़ता है, तो यह सबक्लास है जिसे क्लास कॉलिंग क्लोन नहीं किया जाना चाहिए।

ओओ प्रोग्रामिंग में, किसी ऑब्जेक्ट को केवल & अनुबंधों के साथ इसमें शामिल होना चाहिए। यह कारकों द्वारा डिजाइन को बहुत जटिल बनाता है, जब आप पूछते हैं कि "क्या सबक्लास इसे तोड़ देता है?" जब भी कोई ऑब्जेक्ट किसी ऑब्जेक्ट को पैरामीटर के रूप में लेता है, तब ऑब्जेक्ट हमेशा उप-वर्ग होता है और सब कुछ तोड़ देता है। जब आप getX() को कॉल करते हैं तो क्या आप रक्षात्मक रूप से प्रोग्राम करते हैं कि यह सबक्लास के लिए अंकगणित अपवाद अपवाद नहीं फेंकता है?

जॉन स्कीट ने मेरे से भी बेहतर जवाब दिया, लेकिन मैंने सोचा कि इस प्रश्न पर संभावित स्टम्बलर को 'डिजाइन द्वारा अनुबंध' के मामूली बिट को सुनने से फायदा हो सकता है। जबकि दृष्टिकोण मृत के पास है, पद्धति ने मेरे डिजाइनों को बहुत शांत करने में मदद की है।

0

नीचे के बारे में क्या?

public synchronized void setDate(Calendar date) { 
    // What to do.... 
    Calendar anotherCalendar = Calendar.getInstance(); 
    anotherCalendar.setTimeInMillis(date.getTimeInMillis()); 
} 

सिंक्रनाइज़ किए गए कोड में सही उपयोग आपके उपयोग के मामले पर निर्भर करता है।

+0

भी काम कर सकता है, मैं क्लोन जवाब पसंद करता हूं, हालांकि, एक अपरिवर्तनीय प्रकार के साथ एक परिपूर्ण दुनिया में - क्लोन मुझे अनुमान लगाने का तरीका होगा, लेकिन आपका उत्तर एक वैध प्रयास भी है –

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