जावा मुखर खोजशब्द क्या करता है, और इसका उपयोग कब किया जाना चाहिए?


601

कथनों की प्रमुख भूमिका को समझने के लिए कुछ वास्तविक जीवन उदाहरण क्या हैं ?


8
वास्तविक जीवन में आप उन्हें लगभग कभी नहीं देखते हैं। अनुमान: यदि आप तीन राज्यों के बारे में सोचते हैं, तो मुखरता का उपयोग करें: मुखर गुजरता है, मुखर विफल रहता है, मुखर केवल दो के बजाय बंद हो जाता है। और मुखर डिफ़ॉल्ट रूप से बंद हो जाता है, इसलिए यह सबसे अधिक संभावना वाला राज्य है, और यह सुनिश्चित करना कठिन है कि यह आपके कोड के लिए सक्षम है। जो कुछ भी जोड़ता है, वह यह है कि एसेर्ट्स एक समयपूर्व अनुकूलन है जो सीमित उपयोग का होगा। जैसा कि आप @ ब्योर्न के जवाब में देखते हैं, यह एक उपयोग के मामले के साथ आने के लिए भी कठिन है जहां आप हर समय एक मुखर असफल नहीं होना चाहेंगे।
यिशै

35
@Yishai: "आपको इस बारे में सोचना होगा ... जोर लगाना बंद है" यदि आपको ऐसा करने की आवश्यकता है, तो आप इसे गलत कर रहे हैं। "मुखर सीमित उपयोग का एक समय से पहले अनुकूलन है" यह बहुत दूर रेल है। यहाँ इस पर सन की टेक दी गई है: " जावा टेक्नॉलॉजी में एसेसरीज़ का उपयोग करना " और यह पढ़ना भी अच्छा है: "
एसरेज़न्स के

5
@DavidTonhofer, वास्तविक जीवन में आप उन्हें लगभग कभी नहीं देखते। यह सत्य है। अपनी पसंद के अनुसार कई ओपन सोर्स प्रोजेक्ट्स की जाँच करें। मैं यह नहीं कह रहा हूं कि आप अपरिवर्तनीयों को मान्य नहीं करते हैं। यह एक ही बात नहीं है। दूसरे तरीके से रखो। यदि दावे बहुत महत्वपूर्ण हैं, तो वे डिफ़ॉल्ट रूप से बंद क्यों हैं?
यिशै

17
एक संदर्भ, एफडब्ल्यूआईडब्ल्यू: सॉफ्टवेयर सिद्धांतों और कोड की गुणवत्ता के बीच का संबंध : "हम स्रोत बग स्थैतिक विश्लेषण टूल जैसी लोकप्रिय बग ढूंढने की तकनीकों के खिलाफ मुखरता की प्रभावकारिता की तुलना करते हैं। हम अपने मामले के अध्ययन से निरीक्षण करते हैं कि एसेटियन घनत्व में वृद्धि के साथ। एक फ़ाइल में दोष घनत्व में सांख्यिकीय रूप से महत्वपूर्ण कमी है। "
डेविड टोनहोफर

4
@DavidTonhofer डेविड, मुझे लगता है कि मुखरता के लिए आपका प्यार बहुत विशिष्ट प्रकार की प्रोग्रामिंग के लिए है जो आप लोग कर रहे हैं, मेरे क्षेत्र में जो किसी भी कारण से प्रोग्राम से बाहर निकलने वाले वेब एप्लिकेशन के साथ काम करता है वह सबसे बड़ा NO NO है - मैं व्यक्तिगत रूप से कभी नहीं हूं यूनिट /
पूर्णांक

जवाबों:


426

जावा 1.4 में दावे ( मुखर कीवर्ड के माध्यम से) जोड़े गए थे। उनका उपयोग कोड में एक अपरिवर्तनीयता की शुद्धता को सत्यापित करने के लिए किया जाता है। उन्हें उत्पादन कोड में कभी ट्रिगर नहीं किया जाना चाहिए, और एक बग का संकेत है या कोड पथ का दुरुपयोग है। वे कमांड -eaपर विकल्प के माध्यम से रन-टाइम पर सक्रिय हो सकते हैं java, लेकिन डिफ़ॉल्ट रूप से चालू नहीं होते हैं।

एक उदाहरण:

public Foo acquireFoo(int id) {
  Foo result = null;
  if (id > 50) {
    result = fooService.read(id);
  } else {
    result = new Foo(id);
  }
  assert result != null;

  return result;
}

71
वास्तव में, ओरेकल आपको assertसार्वजनिक विधि मापदंडों ( docs.oracle.com/javase/1.4.2/docs/guide/lang/assert.html ) की जांच करने के लिए उपयोग नहीं करने के लिए कहता है । Exceptionइस कार्यक्रम को मारने के बजाय फेंक देना चाहिए ।
एसजुआन76

10
लेकिन आप अभी भी यह नहीं समझाते हैं कि वे क्यों मौजूद हैं। आप एक () जाँच और एक अपवाद क्यों नहीं कर सकते हैं?
एल मैक

7
@ElMac - दावे चक्र के देव / डिबग / परीक्षण भागों के लिए हैं - वे उत्पादन के लिए नहीं हैं। यदि ब्लॉक ठेस में चलता है। सरल दावे बैंक को नहीं तोड़ेंगे, लेकिन जटिल डेटा सत्यापन करने वाले महंगे दावे आपके उत्पादन वातावरण को नीचे ला सकते हैं, यही कारण है कि उन्हें वहां से हटा दिया जाता है।
१०'१६ को हुडैटिकस १

2
@hoodaticus का मतलब पूरी तरह से इस तथ्य से है कि मैं ठेस कोड के लिए सभी दावे को चालू / बंद कर सकता हूं? क्योंकि मैं जटिल डेटा सत्यापन वैसे भी कर सकता हूं और फिर अपवादों के साथ इसे संभाल सकता हूं। यदि मेरे पास उत्पादन कोड है, तो मैं जटिल (और शायद महंगा) दावे को बंद कर सकता हूं, क्योंकि यह काम करना चाहिए और पहले से ही परीक्षण किया गया था? सिद्धांत रूप में, उन्हें कार्यक्रम को नीचे नहीं लाना चाहिए क्योंकि तब आपको किसी भी तरह की समस्या होगी।
एल मैक

8
This convention is unaffected by the addition of the assert construct. Do not use assertions to check the parameters of a public method. An assert is inappropriate because the method guarantees that it will always enforce the argument checks. It must check its arguments whether or not assertions are enabled. Further, the assert construct does not throw an exception of the specified type. It can throw only an AssertionError. docs.oracle.com/javase/8/docs/technotes/guides/language/…
बख्शी

325

मान लेते हैं कि आप परमाणु ऊर्जा संयंत्र को नियंत्रित करने के लिए एक कार्यक्रम लिखने वाले हैं। यह बहुत स्पष्ट है कि सबसे छोटी गलती के भी भयावह परिणाम हो सकते हैं, इसलिए आपके कोड को बग-मुक्त होना चाहिए (यह मानते हुए कि तर्क के लिए जेवीएम बग रहित है)।

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

यह विचार डिज़ाइन-बाय-कॉन्ट्रैक्ट (DbC) प्रतिमान पर आधारित है : आप पहली बार (गणितीय परिशुद्धता के साथ) परिभाषित करते हैं कि आपकी विधि क्या करने वाली है, और फिर वास्तविक निष्पादन के दौरान परीक्षण करके इसे सत्यापित करें। उदाहरण:

// Calculates the sum of a (int) + b (int) and returns the result (int).
int sum(int a, int b) {
  return a + b;
}

हालांकि यह ठीक काम करने के लिए बहुत स्पष्ट है, अधिकांश प्रोग्रामर इस एक के अंदर छिपे हुए बग को नहीं देखेंगे (संकेत: एरियन वी एक समान बग के कारण दुर्घटनाग्रस्त हो गया)। अब DbC यह परिभाषित करता है कि आपको सही ढंग से काम करने के लिए किसी फ़ंक्शन के इनपुट और आउटपुट को हमेशा जांचना चाहिए । जावा जोर के माध्यम से यह कर सकते हैं:

// Calculates the sum of a (int) + b (int) and returns the result (int).
int sum(int a, int b) {
    assert (Integer.MAX_VALUE - a >= b) : "Value of " + a + " + " + b + " is too large to add.";
  final int result = a + b;
    assert (result - a == b) : "Sum of " + a + " + " + b + " returned wrong sum " + result;
  return result;
}

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

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

यह अभी भी बग-मुक्त कोड के लिए गारंटी नहीं है, लेकिन सामान्य कार्यक्रमों की तुलना में यह बहुत करीब है।


29
मैंने इस उदाहरण को चुना क्योंकि यह बग-मुक्त कोड में छिपे हुए कीड़े को बहुत अच्छी तरह से प्रस्तुत करता है। यदि यह वैसा ही है जैसा किसी और ने प्रस्तुत किया है, तो शायद उनके मन में भी यही विचार था। ;)
दो

8
आप मुखरता का चयन करते हैं क्योंकि यह तब विफल होता है जब अभिकथन गलत होता है। यदि कोई व्यवहार कर सकता है। फ्रिंज मामलों को मारना यूनिट टेस्टिंग का काम है। अनुबंध द्वारा डिजाइन का उपयोग अनुबंध को अच्छी तरह से निर्दिष्ट करता है लेकिन वास्तविक जीवन अनुबंधों के साथ, आपको यह सुनिश्चित करने के लिए नियंत्रण की आवश्यकता है कि वे सम्मानित हैं। कथनों के साथ एक प्रहरी डाला जाता है जो तब होगा जब अनुबंध का अनादर किया जाएगा। इसे एक गलत वकील के रूप में सोचें "गलत" हर बार जब आप कुछ ऐसा करते हैं जो आपके अनुबंध के बाहर या अनुबंध पर होता है और फिर आपको घर भेज देता है ताकि आप काम जारी न रख सकें और अनुबंध को और भंग कर सकें!
एरिक

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

4
इसे फिर से जीवित करने के लिए क्षमा करें, लेकिन मेरे पास एक विशिष्ट प्रश्न है। @TwoThe के बीच क्या अंतर है और केवल new IllegalArgumentExceptionसंदेश के साथ फेंकने के लिए मुखर का उपयोग करने के बजाय ? मेरा मतलब है, एक तरफ ओ throwsघोषणा से लेकर विधि घोषणा और कहीं और उस अपवाद को प्रबंधित करने के लिए कोड। assertनए अपवाद को फेंकने का पागलपन क्यों ? या ifइसके बजाय क्यों नहीं assert? वास्तव में यह नहीं मिल सकता है :(
Blueriver

14
-1: अतिप्रवाह के लिए जाँच करने का दावा गलत है अगर aनकारात्मक हो सकता है। दूसरा जोर बेकार है; int मानों के लिए, यह हमेशा ऐसा होता है कि a + b - b == a। यह परीक्षण केवल तभी विफल हो सकता है जब कंप्यूटर मौलिक रूप से टूट गया हो। उस आकस्मिकता से बचाव के लिए, आपको कई सीपीयू में निरंतरता की जांच करनी होगी।
केविन क्लाइन

63

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

void doSomething(Widget widget) {
  if (widget != null) {
    widget.someMethod(); // ...
    ... // do more stuff with this widget
  }
}

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

/**
 * @param Widget widget Should never be null
 */
void doSomething(Widget widget) {
  assert widget != null;
  widget.someMethod(); // ...
    ... // do more stuff with this widget
}

इस तरह, आप इस बग को जल्दी पकड़ना सुनिश्चित करेंगे। (यह अनुबंध में निर्दिष्ट करने के लिए भी उपयोगी है कि यह पैरामीटर कभी भी अशक्त नहीं होना चाहिए।) जब आप विकास के दौरान अपने कोड का परीक्षण करते हैं, तो यह सुनिश्चित करना सुनिश्चित करें। (और अपने सहयोगियों को ऐसा करने के लिए राजी करना भी बहुत मुश्किल है, जो मुझे बहुत कष्टप्रद लगता है।)

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

void doSomething(Widget widget) {
  assert widget != null;
  if (widget != null) {
    widget.someMethod(); // ...
    ... // do more stuff with this widget
  }
}

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

यहाँ एक वास्तविक दुनिया उदाहरण है: मैंने एक बार एक विधि लिखी थी जिसमें समानता के लिए दो मनमाने मूल्यों की तुलना की गई थी, जहाँ या तो मूल्य शून्य हो सकता है:

/**
 * Compare two values using equals(), after checking for null.
 * @param thisValue (may be null)
 * @param otherValue (may be null)
 * @return True if they are both null or if equals() returns true
 */
public static boolean compare(final Object thisValue, final Object otherValue) {
  boolean result;
  if (thisValue == null) {
    result = otherValue == null;
  } else {
    result = thisValue.equals(otherValue);
  }
  return result;
}

यह कोड equals()उस स्थिति में विधि के काम को दर्शाता है जहां यह प्रस्ताव शून्य नहीं है। लेकिन यह equals()विधि को सही ढंग से मानता है equals()एक अशक्त पैरामीटर को ठीक से संभालकर अनुबंध को पूरा करता है ।

एक सहकर्मी ने मेरे कोड पर आपत्ति जताते हुए मुझे बताया कि हमारी कई कक्षाओं में छोटी-छोटी equals()विधियाँ हैं जो अशक्त होने की परीक्षा नहीं देती हैं, इसलिए मुझे उस जाँच को इस विधि में रखना चाहिए। यदि यह समझदारी है, या यदि हमें त्रुटि पर बल देना चाहिए, तो यह बहस योग्य है, इसलिए हम इसे ठीक कर सकते हैं और इसे ठीक कर सकते हैं, लेकिन मैंने अपने सहयोगी को टाल दिया और एक अशक्त जांच में डाल दिया, जिसे मैंने एक टिप्पणी के साथ चिह्नित किया है:

public static boolean compare(final Object thisValue, final Object otherValue) {
  boolean result;
  if (thisValue == null) {
    result = otherValue == null;
  } else {
    result = otherValue != null && thisValue.equals(otherValue); // questionable null check
  }
  return result;
}

यहां अतिरिक्त जांच other != nullकेवल तभी आवश्यक है जब equals()विधि अनुबंध के लिए आवश्यक के रूप में अशक्त के लिए जांच करने में विफल हो।

बग्गी कोड को हमारे कोड बेस में रहने देने के ज्ञान के बारे में अपने सहकर्मी के साथ एक बेकार बहस में संलग्न होने के बजाय, मैंने कोड में केवल दो दावे किए। ये दावे मुझे बताएंगे, विकास के चरण के दौरान, अगर हमारी कोई कक्षा equals()ठीक से लागू नहीं हो पाती है, तो मैं इसे ठीक कर सकता हूं:

public static boolean compare(final Object thisValue, final Object otherValue) {
  boolean result;
  if (thisValue == null) {
    result = otherValue == null;
    assert otherValue == null || otherValue.equals(null) == false;
  } else {
    result = otherValue != null && thisValue.equals(otherValue);
    assert thisValue.equals(null) == false;
  }
  return result;
}

ध्यान रखने योग्य महत्वपूर्ण बिंदु ये हैं:

  1. दावे केवल विकास के चरण के उपकरण हैं।

  2. जोर देने की बात यह है कि आपको पता चल जाए कि क्या बग है, न सिर्फ आपके कोड में, बल्कि आपके कोड बेस में भी । (यहां दावे वास्तव में अन्य वर्गों में झंडे गाड़ देंगे।)

  3. यहां तक ​​कि अगर मेरे सहकर्मी आश्वस्त थे कि हमारी कक्षाएं ठीक से लिखी गई हैं, तो यहां दावे अभी भी उपयोगी होंगे। नई कक्षाएं जोड़ी जाएंगी जो अशक्त के लिए परीक्षण करने में विफल हो सकती हैं, और यह विधि हमारे लिए उन बगों को चिह्नित कर सकती है।

  4. विकास में, आपको हमेशा अभिकथन चालू करना चाहिए, भले ही आपने जो कोड लिखा है वह अभिकथन का उपयोग नहीं करता हो। मेरी IDE हमेशा किसी भी नए निष्पादन योग्य के लिए डिफ़ॉल्ट रूप से ऐसा करने के लिए सेट है।

  5. अभिकथन कोड के व्यवहार को उत्पादन में नहीं बदलते हैं, इसलिए मेरे सहकर्मी खुश हैं कि अशक्त जाँच है, और यह कि equals()विधि छोटी गाड़ी होने पर भी ठीक से निष्पादित होगी । मैं खुश हूं क्योंकि मैं equals()विकास में किसी भी छोटी-मोटी विधि को पकड़ूंगा।

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


"एक बग को छिपाने" के बारे में अच्छे बिंदु और कैसे विकास के दौरान बग को उजागर करता है!
20

इनमें से कोई भी चेक धीमा नहीं है, इसलिए उत्पादन में उन्हें बंद करने का कोई कारण नहीं है। उन्हें लॉगिंग स्टेटमेंट में परिवर्तित किया जाना चाहिए, ताकि आप उन समस्याओं का पता लगा सकें जो आपके "विकास के चरण" में दिखाई नहीं देती हैं। (वास्तव में, विकास चरण के रूप में ऐसी कोई बात नहीं है, वैसे भी। जब आप अपना कोड बनाए रखना बंद करने का निर्णय लेते हैं, तो विकास समाप्त हो जाता है।)
अलेक्सांद्र डबिन्सकी ३०'१

20

assertकीवर्ड क्या करता है, यह बताने के लिए बहुत सारे अच्छे उत्तर हैं , लेकिन कुछ लोग असली सवाल का जवाब देते हैं, " assertवास्तविक जीवन में कीवर्ड का उपयोग कब किया जाना चाहिए ?"

जवाब: लगभग कभी नहीं

अवधारणा के रूप में, विचार अद्भुत हैं। अच्छे कोड में बहुत सारे if (...) throw ...कथन होते हैं (और उनके रिश्तेदार पसंद करते हैं Objects.requireNonNullऔर Math.addExact)। हालाँकि, कुछ डिज़ाइन निर्णयों ने assert कीवर्ड की उपयोगिता को बहुत सीमित कर दिया है।

assertकीवर्ड के पीछे ड्राइविंग विचार समय से पहले का अनुकूलन है, और मुख्य विशेषता आसानी से सभी चेक को बंद करने में सक्षम हो रही है। वास्तव में, assertचेक डिफ़ॉल्ट रूप से बंद हो जाते हैं।

हालांकि, यह गंभीर रूप से महत्वपूर्ण है कि उत्पादन में अनियंत्रित जांचें जारी रहें। ऐसा इसलिए है क्योंकि सही परीक्षण कवरेज असंभव है, और सभी उत्पादन कोड में बग्स होंगे जो अभिकथन को निदान और कम करने में मदद करनी चाहिए।

इसलिए, का उपयोग if (...) throw ...पसंद किया जाना चाहिए, जैसे कि सार्वजनिक तरीकों के पैरामीटर मूल्यों की जांच करने और फेंकने के लिए आवश्यक है IllegalArgumentException

कभी-कभी, एक व्यक्ति को एक अनियंत्रित जांच लिखने के लिए लुभाया जा सकता है जो प्रक्रिया के लिए अवांछनीय रूप से लंबा समय लेता है (और इसे पदार्थ के लिए अक्सर पर्याप्त कहा जाता है)। हालांकि, ऐसे चेक परीक्षण को धीमा कर देंगे जो अवांछनीय भी है। इस तरह के समय लेने वाले चेक को आमतौर पर यूनिट टेस्ट के रूप में लिखा जाता है। फिर भी, यह कभी-कभी assertइस कारण से उपयोग करने के लिए समझ में आता है ।

assertबस का उपयोग न करें क्योंकि यह क्लीनर और प्रीटीयर है if (...) throw ...(और मैं कहता हूं कि बहुत दर्द के साथ, क्योंकि मुझे साफ और सुंदर लगता है)। यदि आप सिर्फ अपनी मदद नहीं कर सकते हैं, और यह नियंत्रित कर सकते हैं कि आपका एप्लिकेशन कैसे लॉन्च किया गया है, तो उपयोग करने के लिए स्वतंत्र महसूस करें assertलेकिन उत्पादन में हमेशा जोर दें। बेशक, यह वही है जो मुझे करना है। मैं एक लुम्बोक एनोटेशन के लिए जोर दे रहा हूं जो assertअधिक कार्य करने का कारण होगा if (...) throw ...इसके लिए यहां वोट करें।

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


2
@aberglas एक पकड़-सभी खंड है catch (Throwable t)। OutOfMemoryError, AssertionError, इत्यादि के जाल, लॉग या रिट्रीट / रिकवरी की कोशिश नहीं करने का कोई कारण नहीं है
Aleksandr Dubinsky

1
मैंने OutOfMemoryError से पकड़ा और बरामद किया है।
मिगेलमुनोज

1
मैं सहमत नहीं हूँ। मेरे एपीआई को सही ढंग से कहा जा रहा है यह सुनिश्चित करने के लिए मेरे कई दावे किए जाते हैं। उदाहरण के लिए, मैं एक निजी विधि लिख सकता हूं जिसे केवल तब बुलाया जाना चाहिए जब कोई वस्तु लॉक रखती है। यदि कोई अन्य डेवलपर उस विधि को उस कोड के हिस्से से कहता है जो ऑब्जेक्ट को लॉक नहीं करता है, तो अभिकथन उन्हें तुरंत बता देगा कि उन्होंने गलती की है। इस तरह की बहुत सारी गलतियाँ हैं, जो निश्चितता के साथ, विकास के चरण में फंस सकती हैं, और इन मामलों में दावे बहुत उपयोगी हैं।
मिगेलमुनोज

2
@MiguelMunoz मैंने अपने उत्तर में कहा कि विचारों का विचार बहुत अच्छा है। यह assertकीवर्ड का कार्यान्वयन खराब है। मैं अपने उत्तर को और अधिक स्पष्ट करने के लिए संपादित करूंगा कि मैं कीवर्ड की बात कर रहा हूं, अवधारणा की नहीं।
अलेक्सांद्र डबिन्स्की

2
मुझे यह पसंद है कि यह एक अपवाद के बजाय एक जोर देता है। बहुत से डेवलपर्स ने अभी भी यह नहीं सीखा है कि वे अपवाद को पकड़ नहीं सकते हैं यदि कोड केवल IOException जैसी चीज को फेंक सकता है। मैं अपने कोड में बग्स पूरी तरह से निगल गया था क्योंकि किसी ने अपवाद पकड़ा। दावे इस जाल में नहीं फंसते। अपवाद उन स्थितियों के लिए हैं जिन्हें आप उत्पादन कोड में देखने की उम्मीद करते हैं। लॉगिंग के लिए, आपको अपनी सभी त्रुटियों को भी लॉग करना चाहिए, भले ही त्रुटियां दुर्लभ हों। उदाहरण के लिए, क्या आप वास्तव में एक लॉग आउट के बिना एक आउटऑममेरीर्रर पास देना चाहते हैं?
मिगेलमुनोज

14

यहां सबसे आम उपयोग मामला है। मान लीजिए कि आप एक एनम मान पर स्विच कर रहे हैं:

switch (fruit) {
  case apple:
    // do something
    break;
  case pear:
    // do something
    break;
  case banana:
    // do something
    break;
}

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

switch (fruit) {
  case apple:
    // do something
    break;
  case pear:
    // do something
    break;
  case banana:
    // do something
    break;
  default:
    assert false : "Missing enum value: " + fruit;
}

4
इसलिए आपको चेतावनियाँ सक्षम होनी चाहिए और चेतावनियाँ त्रुटियों के रूप में मानी जानी चाहिए। कोई भी आधा सभ्य संकलक आपको बताने में सक्षम है, अगर केवल आप ही आपको यह बताने की अनुमति देते हैं, कि आप एक एनम चेक को याद कर रहे हैं, और यह संकलन समय पर ऐसा करेगा, जो संभवतः (शायद, एक दिन) से बेहतर है। भागो समय
माइक नाकिस

9
किसी प्रकार के अपवाद के बजाय यहां एक दावे का उपयोग क्यों करें, उदाहरण के लिए, एक गैरकानूनीकरण?
liltitus27

4
AssertionErrorयदि जोर दिया जाता है तो यह फेंक देगा ( -ea)। उत्पादन में वांछित व्यवहार क्या है? निष्पादन में बाद में एक मूक नो-ऑप और संभावित आपदा? शायद ऩही। मैं एक स्पष्ट सुझाव दूंगा throw new AssertionError("Missing enum value: " + fruit);
एरियोबे

1
सिर्फ एक जोर देने के लिए एक अच्छा तर्क दिया जाना चाहिए। उत्पादन में उचित व्यवहार के लिए, अभिकथन का पूरा बिंदु उत्पादन में ऐसा होने से रोकना है। दावे बग को पकड़ने के लिए एक विकास चरण उपकरण है, जिसे आसानी से उत्पादन कोड से हटाया जा सकता है। इस स्थिति में, इसे उत्पादन कोड से हटाने का कोई कारण नहीं है। लेकिन कई मामलों में, अखंडता परीक्षण चीजों को धीमा कर सकते हैं। इन परीक्षणों को अभिकथन के अंदर रखकर, जिनका उपयोग उत्पादन कोड में नहीं किया जाता है, आप पूरी तरह से परीक्षण लिखने के लिए स्वतंत्र हैं, बिना इस चिंता के कि वे आपके उत्पादन कोड को धीमा कर देंगे।
मिगेलमुनोज

यह गलत लगता है। IMHO का आपको उपयोग नहीं करना चाहिए defaultताकि संकलक आपको लापता मामलों पर चेतावनी दे सके। आप returnइसके बजाय break(यह विधि निकालने की आवश्यकता हो सकती है) और फिर स्विच के बाद लापता मामले को संभाल सकते हैं। इस तरह आपको चेतावनी और अवसर दोनों मिलते हैं assert
Maaartinus

12

पूर्व-स्थितियों की जांच करने के लिए दावे का उपयोग किया जाता है और "पूर्व स्थितियों में" कभी असफल नहीं होना चाहिए। सही कोड को कभी भी असफल नहीं होना चाहिए; जब वे ट्रिगर करते हैं, तो उन्हें एक बग इंगित करना चाहिए (उम्मीद है कि ऐसी जगह पर जहां समस्या का वास्तविक नियंत्रण रेखा के करीब है)।

एक अभिकथन का एक उदाहरण यह देखना होगा कि तरीकों में से एक विशेष समूह के सही क्रम (जैसे, कि में कहा जाता है हो सकता है hasNext()इससे पहले कि कहा जाता है next()एक में Iterator)।


1
आपको अगले () से पहले hasNext () को कॉल करने की आवश्यकता नहीं है।
DJClayworth

6
@DJClayworth: आपको या तो जोर देने से बचने की आवश्यकता नहीं है। :-)
डोनाल्ड फेलो

8

जावा में मुखर कीवर्ड क्या करता है?

आइए संकलित बायटेकोड को देखें।

हम यह निष्कर्ष निकालेंगे:

public class Assert {
    public static void main(String[] args) {
        assert System.currentTimeMillis() == 0L;
    }
}

के रूप में लगभग एक ही bytecode उत्पन्न करता है:

public class Assert {
    static final boolean $assertionsDisabled =
        !Assert.class.desiredAssertionStatus();
    public static void main(String[] args) {
        if (!$assertionsDisabled) {
            if (System.currentTimeMillis() != 0L) {
                throw new AssertionError();
            }
        }
    }
}

कहाँ पे Assert.class.desiredAssertionStatus() है trueजब -eaकमांड लाइन पर पारित किया जाता है, और अन्यथा गलत।

हम प्रयोग करते हैं System.currentTimeMillis() यह सुनिश्चित करने के लिए करते हैं कि यह दूर (अनुकूलित assert true;) नहीं होगा ।

सिंथेटिक क्षेत्र उत्पन्न होता है ताकि जावा को केवल Assert.class.desiredAssertionStatus()लोड समय पर एक बार कॉल करने की आवश्यकता हो , और इसके बाद वहां परिणाम प्राप्त हो। यह सभी देखें: "स्थिर सिंथेटिक" का क्या अर्थ है?

हम इसे सत्यापित कर सकते हैं:

javac Assert.java
javap -c -constants -private -verbose Assert.class

Oracle JDK 1.8.0_45 के साथ, एक सिंथेटिक स्थैतिक क्षेत्र उत्पन्न हुआ (यह भी देखें: "स्थैतिक सिंथेटिक" का अर्थ क्या है:? )

static final boolean $assertionsDisabled;
  descriptor: Z
  flags: ACC_STATIC, ACC_FINAL, ACC_SYNTHETIC

एक साथ एक स्थिर इनिशियलाइज़र:

 0: ldc           #6                  // class Assert
 2: invokevirtual #7                  // Method java/lang Class.desiredAssertionStatus:()Z
 5: ifne          12
 8: iconst_1
 9: goto          13
12: iconst_0
13: putstatic     #2                  // Field $assertionsDisabled:Z
16: return

और मुख्य विधि है:

 0: getstatic     #2                  // Field $assertionsDisabled:Z
 3: ifne          22
 6: invokestatic  #3                  // Method java/lang/System.currentTimeMillis:()J
 9: lconst_0
10: lcmp
11: ifeq          22
14: new           #4                  // class java/lang/AssertionError
17: dup
18: invokespecial #5                  // Method java/lang/AssertionError."<init>":()V
21: athrow
22: return

हम यह निष्कर्ष निकालते हैं:

  • इसके लिए कोई बाइटकोड स्तर का समर्थन नहीं है assert: यह एक जावा भाषा अवधारणा है
  • assertकमांड लाइन पर -Pcom.me.assert=trueबदलने के लिए सिस्टम गुणों के साथ बहुत अच्छी तरह से अनुकरण किया जा सकता है -ea, और ए throw new AssertionError()

2
तो catch (Throwable t)क्लॉज भी उल्लंघनों के उल्लंघन को पकड़ने में सक्षम है? मेरे लिए यह उनकी उपयोगिता को केवल उस स्थिति तक सीमित करता है जहां मुखरता का शरीर समय लेने वाला है, जो दुर्लभ है।
इवगेनी सर्गेव

1
मुझे यकीन नहीं है कि यह दावे की उपयोगिता को सीमित करता है। बहुत दुर्लभ मामलों को छोड़कर आपको कभी भी थ्रोबल नहीं पकड़ना चाहिए। यदि आपको थ्रोबेबल को पकड़ने की आवश्यकता है, लेकिन चाहते हैं कि यह जोर न पकड़े, तो आप बस AssertionErrorपहले को पकड़ सकते हैं और इसे वापस ला सकते हैं ।
मिगेलमुनोज़

7

एक वास्तविक दुनिया उदाहरण, एक स्टैक-क्लास से ( जावा लेख में जोर से )

public int pop() {
   // precondition
   assert !isEmpty() : "Stack is empty";
   return stack[--num];
}

80
यह C पर डूब जाएगा: एक जोर कुछ ऐसा है जो वास्तव में कभी भी होना चाहिए - खाली स्टैक को पॉप करने से NoElementsException या रेखाओं के साथ कुछ फेंकना चाहिए। देखिए डोनल का जवाब
कोनरक

4
मैं सहमत हूँ। हालांकि यह एक आधिकारिक ट्यूटोरियल से लिया गया है, यह एक बुरा उदाहरण है।
डीजेकेवर्थ

4
यह फेंक चाहिए docs.oracle.com/javase/6/docs/api/java/util/... में के रूप में docs.oracle.com/javase/6/docs/api/java/util/...
अराम Kocharyan

7
वहाँ शायद एक स्मृति रिसाव है। आपको स्टैक [संख्या] = शून्य सेट करना चाहिए; जीसी के लिए अपना काम ठीक से करने के लिए।
एच। रैबीई

3
मुझे लगता है कि एक निजी पद्धति में, एक दावे का उपयोग करना सही होगा, क्योंकि किसी वर्ग या विधि की खराबी के लिए अपवाद होना अजीब होगा। एक सार्वजनिक विधि में, इसे कहीं बाहर से बुलाकर, आप वास्तव में यह नहीं बता सकते कि दूसरा कोड इसका उपयोग कैसे करता है। क्या यह वास्तव में जांच करता है कि ईएमटीपी () है या नहीं? तुम्हें पता नहीं है।
वलसेक

7

एक जोर कोड में दोषों का पता लगाने के लिए अनुमति देता है। जब आपका प्रोग्राम उत्पादन में हो तो आप उन्हें छोड़ते समय परीक्षण और डिबगिंग के लिए जोर लगा सकते हैं।

जब आप जानते हैं कि यह सच है तो कुछ क्यों कहना? यह तभी सही है जब सब कुछ ठीक से काम कर रहा हो। यदि कार्यक्रम में दोष है, तो यह वास्तव में सच नहीं हो सकता है। इस प्रक्रिया में पहले पता लगाने से आपको पता चल जाता है कि कुछ गड़बड़ है।

एक assertबयान में एक वैकल्पिक Stringसंदेश के साथ यह कथन शामिल है ।

मुखर कथन के लिए वाक्य रचना के दो रूप हैं:

assert boolean_expression;
assert boolean_expression: error_message;

यहां कुछ बुनियादी नियम हैं जो शासित करते हैं कि किस स्थान पर उपयोग किया जाना चाहिए और कहां उनका उपयोग नहीं किया जाना चाहिए। के लिए उपयोग किया जाना चाहिए :

  1. एक निजी पद्धति के इनपुट मापदंडों को मान्य करना। सार्वजनिक तरीकों के लिए नहींpublicखराब मापदंडों को पारित करने पर तरीकों को नियमित अपवादों को फेंक देना चाहिए।

  2. कार्यक्रम में कहीं भी एक तथ्य की वैधता सुनिश्चित करने के लिए जो लगभग निश्चित रूप से सच है।

उदाहरण के लिए, यदि आप सुनिश्चित हैं कि यह केवल 1 या 2 होगा, तो आप इस तरह का उपयोग कर सकते हैं:

...
if (i == 1)    {
    ...
}
else if (i == 2)    {
    ...
} else {
    assert false : "cannot happen. i is " + i;
}
...
  1. किसी भी विधि के अंत में पोस्ट की स्थिति को मान्य करना। इसका मतलब है, व्यापार तर्क को निष्पादित करने के बाद, आप यह सुनिश्चित करने के लिए अभिकथन का उपयोग कर सकते हैं कि आपके चर या परिणामों की आंतरिक स्थिति आपके द्वारा अपेक्षित के अनुरूप है। उदाहरण के लिए, सॉकेट या फ़ाइल खोलने वाली एक विधि अंत में एक सॉर्ट का उपयोग कर सकती है ताकि यह सुनिश्चित हो सके कि सॉकेट या फ़ाइल वास्तव में खोली गई है।

के लिए उपयोग नहीं किया जाना चाहिए :

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

  2. उपयोगकर्ता द्वारा इनपुट किए गए किसी चीज़ पर अवरोध उत्पन्न करना। ऊपर की तरह।

  3. साइड इफेक्ट के लिए इस्तेमाल नहीं किया जाना चाहिए।

उदाहरण के लिए यह एक उचित उपयोग नहीं है क्योंकि यहाँ doSomething()विधि के कॉलिंग के दुष्प्रभाव के लिए दावे का उपयोग किया जाता है ।

public boolean doSomething() {
...    
}
public void someMethod() {       
assert doSomething(); 
}

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

boolean enabled = false;    
assert enabled = true;    
if (enabled) {
    System.out.println("Assertions are enabled");
} else {
    System.out.println("Assertions are disabled");
}

5

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

संपर्क


1
मैं सहमत हूँ। लेख के कई उत्कृष्ट उदाहरण हैं। मुझे विशेष रूप से पसंद है यह सुनिश्चित करने के लिए कि एक विधि केवल तभी कॉल की जाती है जब ऑब्जेक्ट लॉक होता है।
मिगेलमुनोज

4

विकासशील होने पर जोर बहुत उपयोगी है। आप इसका उपयोग तब करते हैं जब कुछ नहीं कर सकता अगर आपके कोड सही ढंग से काम कर रहा है होता है। इसका उपयोग करना आसान है, और हमेशा के लिए कोड में रह सकते हैं, क्योंकि यह वास्तविक जीवन में बंद हो जाएगा।

यदि कोई भी मौका है कि स्थिति वास्तविक जीवन में हो सकती है, तो आपको इसे संभालना होगा।

मुझे यह पसंद है, लेकिन यह नहीं पता कि इसे ग्रहण / एंड्रॉइड / एडीटी में कैसे चालू किया जाए। यह डिबगिंग के दौरान भी बंद लगता है। (इस पर एक सूत्र है, लेकिन यह 'जावा vm' को संदर्भित करता है, जो ADT रन कॉन्फ़िगरेशन में प्रकट नहीं होता है)।


1
ग्रहण आईडीई में मुखरता को सक्षम करने के लिए, कृपया tutoringcenter.cs.usfca.edu/resources/…
Ayaz Pasha

मुझे नहीं लगता कि एंड्रॉइड में जोर लगाने का कोई तरीका है। यह बहुत निराशाजनक है।
मिगेलमुनोज

3

यहाँ एक हाइबरनेट / SQL प्रोजेक्ट के लिए एक सर्वर में लिखा गया है। एक इकाई बीन में दो प्रभावी रूप से बूलियन गुण होते हैं, जिन्हें आइएक्टिव और आइसडेफ़ॉल्ट कहा जाता है। प्रत्येक में "Y" या "N" या नल का मान हो सकता है, जिसे "N" माना जाता था। हम यह सुनिश्चित करना चाहते हैं कि ब्राउज़र क्लाइंट इन तीन मूल्यों तक सीमित है। इसलिए, इन दो संपत्तियों के लिए अपने निपटान में, मैंने इस दावे को जोड़ा:

assert new HashSet<String>(Arrays.asList("Y", "N", null)).contains(value) : value;

निम्नलिखित पर ध्यान दें।

  1. यह दावा केवल विकास के चरण के लिए है। यदि ग्राहक एक बुरा मूल्य भेजता है, तो हम उसे जल्दी पकड़ लेंगे और उसे ठीक कर देंगे, जब तक कि हम उत्पादन तक नहीं पहुंच जाते। दावे उन दोषों के लिए हैं जिन्हें आप जल्दी पकड़ सकते हैं।

  2. यह दावा धीमा और अक्षम है। वह ठीक है। दावे धीमे होने के लिए स्वतंत्र हैं। हमें परवाह नहीं है क्योंकि वे केवल विकास के उपकरण हैं। यह उत्पादन कोड को धीमा नहीं करेगा क्योंकि दावे अक्षम होंगे। (इस बिंदु पर कुछ असहमति है, जो मुझे बाद में पता चलेगी।) यह मेरे अगले बिंदु की ओर जाता है।

  3. इस दावे का कोई दुष्प्रभाव नहीं है। मैं एक मूल्यहीन स्थिर अंतिम सेट के खिलाफ अपने मूल्य का परीक्षण कर सकता था, लेकिन यह सेट उत्पादन में चारों ओर रहता था, जहां इसका उपयोग कभी नहीं होता।

  4. यह दावा क्लाइंट के उचित संचालन को सत्यापित करने के लिए मौजूद है। इसलिए जब तक हम उत्पादन तक पहुंचते हैं, तब तक हम यह सुनिश्चित करेंगे कि ग्राहक ठीक से काम कर रहा है, इसलिए हम सुरक्षित रूप से दावे को बंद कर सकते हैं।

  5. कुछ लोग यह पूछते हैं: यदि उत्पादन में अभिकथन की आवश्यकता नहीं है, तो जब आप काम पूरा कर लेते हैं, तो उन्हें क्यों नहीं निकालते? क्योंकि जब आप अगले संस्करण पर काम करना शुरू करेंगे, तब भी आपको उनकी आवश्यकता होगी।

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

BTW, मैं इसे इस तरह लिख सकता था:

assert value == null || value.equals("Y") || value.equals("N") : value;

यह केवल तीन मूल्यों के लिए ठीक है, लेकिन यदि संभावित मूल्यों की संख्या अधिक हो जाती है, तो हैशसेट संस्करण अधिक सुविधाजनक हो जाता है। मैंने दक्षता के बारे में अपनी बात बनाने के लिए हैशसेट संस्करण को चुना।


मुझे दृढ़ता से संदेह है कि इस तरह के एक छोटे से प्रयोग से एक HashSetपर कोई गति लाभ होता है ArrayList। इसके अलावा, सेट और सूची क्रिएशन लुकअप टाइम पर हावी हैं। स्थिरांक का उपयोग करते समय वे ठीक होते हैं। उस सब ने कहा, +1।
maaartinus

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

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

2

दावे का उपयोग मूल रूप से अनुप्रयोग को डीबग करने के लिए किया जाता है या किसी एप्लिकेशन की वैधता की जांच के लिए कुछ एप्लिकेशन के अपवाद हैंडलिंग के प्रतिस्थापन में इसका उपयोग किया जाता है।

अभिकथन रन टाइम पर काम करता है। एक सरल उदाहरण, जो पूरी अवधारणा को बहुत सरलता से समझा सकता है, यह है - जावा में एसर कीवर्ड क्या करता है? (WikiAnswers)।


2

डिफ़ॉल्ट रूप से दावे अक्षम हैं। उन्हें सक्षम करने के लिए हमें -eaविकल्प के साथ कार्यक्रम चलाना चाहिए (बारीकता विविध हो सकती है)। उदाहरण के लिए, java -ea AssertionsDemo

दावे का उपयोग करने के लिए दो प्रारूप हैं:

  1. सरल: उदाहरण के लिए। assert 1==2; // This will raise an AssertionError
  2. बेहतर: assert 1==2: "no way.. 1 is not equal to 2"; यह एक AsserionError को बढ़ाए गए संदेश के साथ प्रदर्शित करेगा और इस तरह बेहतर है। हालाँकि वास्तविक वाक्यविन्यास वह है assert expr1:expr2जहाँ expr2 किसी भी मूल्य को लौटाने वाली कोई भी अभिव्यक्ति हो सकती है, मैंने इसका उपयोग अधिक बार केवल एक संदेश को प्रिंट करने के लिए किया है।

1

पुनर्कथन करने के लिए (और यह सिर्फ जावा ही नहीं कई भाषाओं के लिए भी सच है):

"मुखर" मुख्य रूप से डिबगिंग प्रक्रिया के दौरान सॉफ़्टवेयर डेवलपर्स द्वारा डिबगिंग सहायता के रूप में उपयोग किया जाता है। मुखर-संदेश कभी प्रकट नहीं होने चाहिए। कई भाषाएं एक संकलन-समय विकल्प प्रदान करती हैं जो "उत्पादन" कोड को उत्पन्न करने में उपयोग के लिए सभी "जोर" को अनदेखा कर देगी।

"अपवाद" सभी प्रकार की त्रुटि स्थितियों को संभालने का एक आसान तरीका है, चाहे वे तर्क त्रुटियों का प्रतिनिधित्व करते हों या नहीं, क्योंकि, यदि आप एक त्रुटि-स्थिति में चलते हैं जैसे कि आप जारी नहीं रख सकते, तो आप बस उन्हें हवा में फेंक सकते हैं, "जहां से भी आप हैं, वहां से किसी और को उम्मीद है कि आप उन्हें पकड़ने" के लिए तैयार रहें। नियंत्रण एक चरण में स्थानांतरित किया जाता है, सीधे उस कोड से, जो अपवाद को फेंक देता है, सीधे पकड़ने वाले के मिट्ट में। (और पकड़ने वाला कॉल के पूर्ण बैकट्रेस को देख सकता है जो हुआ था।)

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

अपवाद आसानी से घातक-त्रुटि की स्थिति की अनुमति देते हैं कि वे क्या हैं: "नियम के अपवाद।" और, उनके लिए एक कोड-पाथ द्वारा संभाला जा सकता है जो "नियम का अपवाद भी है ... " फ्लाई बॉल!


1

दावे चेक हैं जो बंद हो सकते हैं। वे शायद ही कभी इस्तेमाल किया जाता है। क्यों?

  • सार्वजनिक पद्धति के तर्कों की जाँच के लिए उनका उपयोग नहीं किया जाना चाहिए क्योंकि आपके पास उन पर कोई नियंत्रण नहीं है।
  • उन्हें साधारण जांच के लिए उपयोग नहीं किया जाना चाहिए जैसे result != nullकि चेक बहुत तेज हैं और बचाने के लिए शायद ही कुछ है।

तो, क्या बचा है? शर्तों के लिए महंगी जाँच वास्तव में सही होने की उम्मीद है। एक अच्छा उदाहरण आरबी-ट्री जैसे डेटा संरचना के आक्रमणकारी होंगे। वास्तव में, ConcurrentHashMapJDK8 में, के लिए कुछ ऐसे सार्थक मुखर हैं TreeNodes

  • आप वास्तव में उन्हें उत्पादन में बदलना नहीं चाहते हैं क्योंकि वे आसानी से रन समय पर हावी हो सकते हैं।
  • आप परीक्षणों के दौरान उन्हें चालू या बंद करना चाह सकते हैं।
  • कोड पर काम करते समय आप निश्चित रूप से उन्हें स्विच करना चाहते हैं।

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

assert Sets.newHashSet(userIds).size() == userIds.size();

जहाँ मुझे पूरा यकीन है कि मैंने जो सूची बनाई है उसमें अद्वितीय तत्व हैं, लेकिन मैं इसे दस्तावेज़ बनाना और जांचना चाहता था।


0

असल में, "अस्सिटेंट ट्रू" पास हो जाएगा और "अस्सिटेंट असत्य" असफल हो जाएगा। आइए देखें कि यह कैसे काम करेगा:

public static void main(String[] args)
{
    String s1 = "Hello";
    assert checkInteger(s1);
}

private static boolean checkInteger(String s)
{
    try {
        Integer.parseInt(s);
        return true;
    }
    catch(Exception e)
    {
        return false;
    }
}

-8

assertएक कीवर्ड है। इसे JDK 1.4 में पेश किया गया था। assertएस दो प्रकार के होते हैं

  1. बहुत ही सरल assertकथन
  2. सरल assertकथन।

डिफ़ॉल्ट रूप से सभी assertकथनों को निष्पादित नहीं किया जाएगा। यदि कोई assertकथन गलत है, तो यह स्वतः ही एक त्रुटि को बढ़ा देगा।


1
यह कोई वास्तविक जीवन उदाहरण प्रदान नहीं करता है, जो कि प्रश्न का उद्देश्य है
rubenafo

1
क्या आपने अभी से पेस्ट कॉपी किया है: amazon.com/Programmer-Study-1Z0-803-1Z0-804-Certification/dp/… ?
कोरे तुगे
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.