कथनों की प्रमुख भूमिका को समझने के लिए कुछ वास्तविक जीवन उदाहरण क्या हैं ?
कथनों की प्रमुख भूमिका को समझने के लिए कुछ वास्तविक जीवन उदाहरण क्या हैं ?
जवाबों:
जावा 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;
}
assertसार्वजनिक विधि मापदंडों ( docs.oracle.com/javase/1.4.2/docs/guide/lang/assert.html ) की जांच करने के लिए उपयोग नहीं करने के लिए कहता है । Exceptionइस कार्यक्रम को मारने के बजाय फेंक देना चाहिए ।
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/…
मान लेते हैं कि आप परमाणु ऊर्जा संयंत्र को नियंत्रित करने के लिए एक कार्यक्रम लिखने वाले हैं। यह बहुत स्पष्ट है कि सबसे छोटी गलती के भी भयावह परिणाम हो सकते हैं, इसलिए आपके कोड को बग-मुक्त होना चाहिए (यह मानते हुए कि तर्क के लिए जेवीएम बग रहित है)।
जावा एक सत्यापन योग्य भाषा नहीं है, जिसका अर्थ है: आप गणना नहीं कर सकते कि आपके ऑपरेशन का परिणाम एकदम सही होगा। इसका मुख्य कारण संकेत हैं: वे कहीं भी या कहीं भी इंगित कर सकते हैं, इसलिए उनकी गणना इस सटीक मान से नहीं की जा सकती है, कम से कम कोड की उचित अवधि के भीतर नहीं। इस समस्या को देखते हुए, यह साबित करने का कोई तरीका नहीं है कि आपका कोड संपूर्ण है। लेकिन आप क्या कर सकते हैं यह साबित करने के लिए कि आप कम से कम हर बग को ढूंढते हैं जब ऐसा होता है।
यह विचार डिज़ाइन-बाय-कॉन्ट्रैक्ट (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;
}
क्या यह फ़ंक्शन अब कभी विफल हो जाएगा, आप इसे नोटिस करेंगे। आपको पता चल जाएगा कि आपके कोड में कोई समस्या है, आप जानते हैं कि यह कहां है और आप जानते हैं कि इसका कारण क्या था (अपवादों के समान)। और जो भी अधिक महत्वपूर्ण है: आप सही निष्पादन करना बंद कर देते हैं जब ऐसा होता है कि गलत मूल्यों के साथ काम करने के लिए किसी भी आगे के कोड को रोकने और संभावित रूप से जो कुछ भी आपके नियंत्रण को नुकसान पहुंचाता है।
जावा अपवाद एक समान अवधारणा है, लेकिन वे सब कुछ सत्यापित करने में विफल रहते हैं। यदि आप और भी अधिक जाँच करना चाहते हैं (निष्पादन की गति पर) आपको अभिकथन का उपयोग करने की आवश्यकता है। ऐसा करने से आपका कोड फूल जाएगा, लेकिन आप अंत में एक उत्पाद को आश्चर्यजनक रूप से कम विकास के समय पर वितरित कर सकते हैं (पहले आप बग को ठीक करते हैं, कम लागत)। और इसके अलावा: यदि आपके कोड के अंदर कोई बग है, तो आप इसका पता लगा लेंगे। बग फिसलने का कोई तरीका नहीं है और बाद में मुद्दों का कारण बनता है।
यह अभी भी बग-मुक्त कोड के लिए गारंटी नहीं है, लेकिन सामान्य कार्यक्रमों की तुलना में यह बहुत करीब है।
new IllegalArgumentExceptionसंदेश के साथ फेंकने के लिए मुखर का उपयोग करने के बजाय ? मेरा मतलब है, एक तरफ ओ throwsघोषणा से लेकर विधि घोषणा और कहीं और उस अपवाद को प्रबंधित करने के लिए कोड। assertनए अपवाद को फेंकने का पागलपन क्यों ? या ifइसके बजाय क्यों नहीं assert? वास्तव में यह नहीं मिल सकता है :(
aनकारात्मक हो सकता है। दूसरा जोर बेकार है; int मानों के लिए, यह हमेशा ऐसा होता है कि a + b - b == a। यह परीक्षण केवल तभी विफल हो सकता है जब कंप्यूटर मौलिक रूप से टूट गया हो। उस आकस्मिकता से बचाव के लिए, आपको कई सीपीयू में निरंतरता की जांच करनी होगी।
अपने कोड में बग्स को पकड़ने के लिए अभिकथन एक विकास-चरण उपकरण है। वे आसानी से हटाए जाने के लिए डिज़ाइन किए गए हैं, इसलिए वे उत्पादन कोड में मौजूद नहीं होंगे। इसलिए दावे "समाधान" का हिस्सा नहीं हैं जो आप ग्राहक को देते हैं। वे यह सुनिश्चित करने के लिए आंतरिक जांच कर रहे हैं कि आप जो धारणा बना रहे हैं वह सही है। सबसे आम उदाहरण अशक्त के लिए परीक्षण करना है। कई विधियाँ इस प्रकार लिखी जाती हैं:
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;
}
ध्यान रखने योग्य महत्वपूर्ण बिंदु ये हैं:
दावे केवल विकास के चरण के उपकरण हैं।
जोर देने की बात यह है कि आपको पता चल जाए कि क्या बग है, न सिर्फ आपके कोड में, बल्कि आपके कोड बेस में भी । (यहां दावे वास्तव में अन्य वर्गों में झंडे गाड़ देंगे।)
यहां तक कि अगर मेरे सहकर्मी आश्वस्त थे कि हमारी कक्षाएं ठीक से लिखी गई हैं, तो यहां दावे अभी भी उपयोगी होंगे। नई कक्षाएं जोड़ी जाएंगी जो अशक्त के लिए परीक्षण करने में विफल हो सकती हैं, और यह विधि हमारे लिए उन बगों को चिह्नित कर सकती है।
विकास में, आपको हमेशा अभिकथन चालू करना चाहिए, भले ही आपने जो कोड लिखा है वह अभिकथन का उपयोग नहीं करता हो। मेरी IDE हमेशा किसी भी नए निष्पादन योग्य के लिए डिफ़ॉल्ट रूप से ऐसा करने के लिए सेट है।
अभिकथन कोड के व्यवहार को उत्पादन में नहीं बदलते हैं, इसलिए मेरे सहकर्मी खुश हैं कि अशक्त जाँच है, और यह कि equals()विधि छोटी गाड़ी होने पर भी ठीक से निष्पादित होगी । मैं खुश हूं क्योंकि मैं equals()विकास में किसी भी छोटी-मोटी विधि को पकड़ूंगा।
इसके अलावा, आपको एक अस्थायी दावे में डालकर अपनी मुखर नीति का परीक्षण करना चाहिए जो विफल हो जाएगा, इसलिए आप निश्चित हो सकते हैं कि आपको सूचित किया जाता है, या तो लॉग फ़ाइल या आउटपुट स्ट्रीम में स्टैक ट्रेस के माध्यम से।
assertकीवर्ड क्या करता है, यह बताने के लिए बहुत सारे अच्छे उत्तर हैं , लेकिन कुछ लोग असली सवाल का जवाब देते हैं, " assertवास्तविक जीवन में कीवर्ड का उपयोग कब किया जाना चाहिए ?"
जवाब: लगभग कभी नहीं ।
अवधारणा के रूप में, विचार अद्भुत हैं। अच्छे कोड में बहुत सारे if (...) throw ...कथन होते हैं (और उनके रिश्तेदार पसंद करते हैं Objects.requireNonNullऔर Math.addExact)। हालाँकि, कुछ डिज़ाइन निर्णयों ने assert कीवर्ड की उपयोगिता को बहुत सीमित कर दिया है।
assertकीवर्ड के पीछे ड्राइविंग विचार समय से पहले का अनुकूलन है, और मुख्य विशेषता आसानी से सभी चेक को बंद करने में सक्षम हो रही है। वास्तव में, assertचेक डिफ़ॉल्ट रूप से बंद हो जाते हैं।
हालांकि, यह गंभीर रूप से महत्वपूर्ण है कि उत्पादन में अनियंत्रित जांचें जारी रहें। ऐसा इसलिए है क्योंकि सही परीक्षण कवरेज असंभव है, और सभी उत्पादन कोड में बग्स होंगे जो अभिकथन को निदान और कम करने में मदद करनी चाहिए।
इसलिए, का उपयोग if (...) throw ...पसंद किया जाना चाहिए, जैसे कि सार्वजनिक तरीकों के पैरामीटर मूल्यों की जांच करने और फेंकने के लिए आवश्यक है IllegalArgumentException।
कभी-कभी, एक व्यक्ति को एक अनियंत्रित जांच लिखने के लिए लुभाया जा सकता है जो प्रक्रिया के लिए अवांछनीय रूप से लंबा समय लेता है (और इसे पदार्थ के लिए अक्सर पर्याप्त कहा जाता है)। हालांकि, ऐसे चेक परीक्षण को धीमा कर देंगे जो अवांछनीय भी है। इस तरह के समय लेने वाले चेक को आमतौर पर यूनिट टेस्ट के रूप में लिखा जाता है। फिर भी, यह कभी-कभी assertइस कारण से उपयोग करने के लिए समझ में आता है ।
assertबस का उपयोग न करें क्योंकि यह क्लीनर और प्रीटीयर है if (...) throw ...(और मैं कहता हूं कि बहुत दर्द के साथ, क्योंकि मुझे साफ और सुंदर लगता है)। यदि आप सिर्फ अपनी मदद नहीं कर सकते हैं, और यह नियंत्रित कर सकते हैं कि आपका एप्लिकेशन कैसे लॉन्च किया गया है, तो उपयोग करने के लिए स्वतंत्र महसूस करें assertलेकिन उत्पादन में हमेशा जोर दें। बेशक, यह वही है जो मुझे करना है। मैं एक लुम्बोक एनोटेशन के लिए जोर दे रहा हूं जो assertअधिक कार्य करने का कारण होगा if (...) throw ...। इसके लिए यहां वोट करें।
(रैंट: JVM देवता भयानक, समय से पहले कोडर्स को अनुकूलित करने का एक समूह थे। यही कारण है कि आप जावा प्लगइन और JVM में सुरक्षा के कई मुद्दों के बारे में सुनते हैं। उन्होंने उत्पादन कोड में बुनियादी जाँच और दावे शामिल करने से इनकार कर दिया और हम इसे जारी रख रहे हैं। मूल्य चुकायें।)
catch (Throwable t)। OutOfMemoryError, AssertionError, इत्यादि के जाल, लॉग या रिट्रीट / रिकवरी की कोशिश नहीं करने का कोई कारण नहीं है
assertकीवर्ड का कार्यान्वयन खराब है। मैं अपने उत्तर को और अधिक स्पष्ट करने के लिए संपादित करूंगा कि मैं कीवर्ड की बात कर रहा हूं, अवधारणा की नहीं।
यहां सबसे आम उपयोग मामला है। मान लीजिए कि आप एक एनम मान पर स्विच कर रहे हैं:
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;
}
AssertionErrorयदि जोर दिया जाता है तो यह फेंक देगा ( -ea)। उत्पादन में वांछित व्यवहार क्या है? निष्पादन में बाद में एक मूक नो-ऑप और संभावित आपदा? शायद ऩही। मैं एक स्पष्ट सुझाव दूंगा throw new AssertionError("Missing enum value: " + fruit);।
defaultताकि संकलक आपको लापता मामलों पर चेतावनी दे सके। आप returnइसके बजाय break(यह विधि निकालने की आवश्यकता हो सकती है) और फिर स्विच के बाद लापता मामले को संभाल सकते हैं। इस तरह आपको चेतावनी और अवसर दोनों मिलते हैं assert।
पूर्व-स्थितियों की जांच करने के लिए दावे का उपयोग किया जाता है और "पूर्व स्थितियों में" कभी असफल नहीं होना चाहिए। सही कोड को कभी भी असफल नहीं होना चाहिए; जब वे ट्रिगर करते हैं, तो उन्हें एक बग इंगित करना चाहिए (उम्मीद है कि ऐसी जगह पर जहां समस्या का वास्तविक नियंत्रण रेखा के करीब है)।
एक अभिकथन का एक उदाहरण यह देखना होगा कि तरीकों में से एक विशेष समूह के सही क्रम (जैसे, कि में कहा जाता है हो सकता है hasNext()इससे पहले कि कहा जाता है next()एक में Iterator)।
जावा में मुखर कीवर्ड क्या करता है?
आइए संकलित बायटेकोड को देखें।
हम यह निष्कर्ष निकालेंगे:
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()।catch (Throwable t)क्लॉज भी उल्लंघनों के उल्लंघन को पकड़ने में सक्षम है? मेरे लिए यह उनकी उपयोगिता को केवल उस स्थिति तक सीमित करता है जहां मुखरता का शरीर समय लेने वाला है, जो दुर्लभ है।
AssertionErrorपहले को पकड़ सकते हैं और इसे वापस ला सकते हैं ।
एक वास्तविक दुनिया उदाहरण, एक स्टैक-क्लास से ( जावा लेख में जोर से )
public int pop() {
// precondition
assert !isEmpty() : "Stack is empty";
return stack[--num];
}
एक जोर कोड में दोषों का पता लगाने के लिए अनुमति देता है। जब आपका प्रोग्राम उत्पादन में हो तो आप उन्हें छोड़ते समय परीक्षण और डिबगिंग के लिए जोर लगा सकते हैं।
जब आप जानते हैं कि यह सच है तो कुछ क्यों कहना? यह तभी सही है जब सब कुछ ठीक से काम कर रहा हो। यदि कार्यक्रम में दोष है, तो यह वास्तव में सच नहीं हो सकता है। इस प्रक्रिया में पहले पता लगाने से आपको पता चल जाता है कि कुछ गड़बड़ है।
एक assertबयान में एक वैकल्पिक Stringसंदेश के साथ यह कथन शामिल है ।
मुखर कथन के लिए वाक्य रचना के दो रूप हैं:
assert boolean_expression;
assert boolean_expression: error_message;
यहां कुछ बुनियादी नियम हैं जो शासित करते हैं कि किस स्थान पर उपयोग किया जाना चाहिए और कहां उनका उपयोग नहीं किया जाना चाहिए। के लिए उपयोग किया जाना चाहिए :
एक निजी पद्धति के इनपुट मापदंडों को मान्य करना। सार्वजनिक तरीकों के लिए नहीं । publicखराब मापदंडों को पारित करने पर तरीकों को नियमित अपवादों को फेंक देना चाहिए।
कार्यक्रम में कहीं भी एक तथ्य की वैधता सुनिश्चित करने के लिए जो लगभग निश्चित रूप से सच है।
उदाहरण के लिए, यदि आप सुनिश्चित हैं कि यह केवल 1 या 2 होगा, तो आप इस तरह का उपयोग कर सकते हैं:
...
if (i == 1) {
...
}
else if (i == 2) {
...
} else {
assert false : "cannot happen. i is " + i;
}
...
के लिए उपयोग नहीं किया जाना चाहिए :
एक सार्वजनिक विधि के इनपुट मापदंडों को मान्य करना। चूंकि कथनों को हमेशा निष्पादित नहीं किया जा सकता है, इसलिए नियमित अपवाद तंत्र का उपयोग किया जाना चाहिए।
उपयोगकर्ता द्वारा इनपुट किए गए किसी चीज़ पर अवरोध उत्पन्न करना। ऊपर की तरह।
साइड इफेक्ट के लिए इस्तेमाल नहीं किया जाना चाहिए।
उदाहरण के लिए यह एक उचित उपयोग नहीं है क्योंकि यहाँ 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");
}
यहां दिए गए सभी शानदार उत्तरों के अलावा, आधिकारिक जावा एसई 7 प्रोग्रामिंग गाइड का उपयोग करने पर एक सुंदर संक्षिप्त मैनुअल है assert; जब यह एक अच्छा (और महत्वपूर्ण रूप से, बुरा) विचारों का उपयोग करने के लिए कई स्पॉट-ऑन उदाहरणों के साथ, और यह अपवादों को फेंकने से अलग कैसे है।
विकासशील होने पर जोर बहुत उपयोगी है। आप इसका उपयोग तब करते हैं जब कुछ नहीं कर सकता अगर आपके कोड सही ढंग से काम कर रहा है होता है। इसका उपयोग करना आसान है, और हमेशा के लिए कोड में रह सकते हैं, क्योंकि यह वास्तविक जीवन में बंद हो जाएगा।
यदि कोई भी मौका है कि स्थिति वास्तविक जीवन में हो सकती है, तो आपको इसे संभालना होगा।
मुझे यह पसंद है, लेकिन यह नहीं पता कि इसे ग्रहण / एंड्रॉइड / एडीटी में कैसे चालू किया जाए। यह डिबगिंग के दौरान भी बंद लगता है। (इस पर एक सूत्र है, लेकिन यह 'जावा vm' को संदर्भित करता है, जो ADT रन कॉन्फ़िगरेशन में प्रकट नहीं होता है)।
यहाँ एक हाइबरनेट / SQL प्रोजेक्ट के लिए एक सर्वर में लिखा गया है। एक इकाई बीन में दो प्रभावी रूप से बूलियन गुण होते हैं, जिन्हें आइएक्टिव और आइसडेफ़ॉल्ट कहा जाता है। प्रत्येक में "Y" या "N" या नल का मान हो सकता है, जिसे "N" माना जाता था। हम यह सुनिश्चित करना चाहते हैं कि ब्राउज़र क्लाइंट इन तीन मूल्यों तक सीमित है। इसलिए, इन दो संपत्तियों के लिए अपने निपटान में, मैंने इस दावे को जोड़ा:
assert new HashSet<String>(Arrays.asList("Y", "N", null)).contains(value) : value;
निम्नलिखित पर ध्यान दें।
यह दावा केवल विकास के चरण के लिए है। यदि ग्राहक एक बुरा मूल्य भेजता है, तो हम उसे जल्दी पकड़ लेंगे और उसे ठीक कर देंगे, जब तक कि हम उत्पादन तक नहीं पहुंच जाते। दावे उन दोषों के लिए हैं जिन्हें आप जल्दी पकड़ सकते हैं।
यह दावा धीमा और अक्षम है। वह ठीक है। दावे धीमे होने के लिए स्वतंत्र हैं। हमें परवाह नहीं है क्योंकि वे केवल विकास के उपकरण हैं। यह उत्पादन कोड को धीमा नहीं करेगा क्योंकि दावे अक्षम होंगे। (इस बिंदु पर कुछ असहमति है, जो मुझे बाद में पता चलेगी।) यह मेरे अगले बिंदु की ओर जाता है।
इस दावे का कोई दुष्प्रभाव नहीं है। मैं एक मूल्यहीन स्थिर अंतिम सेट के खिलाफ अपने मूल्य का परीक्षण कर सकता था, लेकिन यह सेट उत्पादन में चारों ओर रहता था, जहां इसका उपयोग कभी नहीं होता।
यह दावा क्लाइंट के उचित संचालन को सत्यापित करने के लिए मौजूद है। इसलिए जब तक हम उत्पादन तक पहुंचते हैं, तब तक हम यह सुनिश्चित करेंगे कि ग्राहक ठीक से काम कर रहा है, इसलिए हम सुरक्षित रूप से दावे को बंद कर सकते हैं।
कुछ लोग यह पूछते हैं: यदि उत्पादन में अभिकथन की आवश्यकता नहीं है, तो जब आप काम पूरा कर लेते हैं, तो उन्हें क्यों नहीं निकालते? क्योंकि जब आप अगले संस्करण पर काम करना शुरू करेंगे, तब भी आपको उनकी आवश्यकता होगी।
कुछ लोगों ने तर्क दिया है कि आपको कभी भी अभिकथन का उपयोग नहीं करना चाहिए, क्योंकि आप कभी भी यह सुनिश्चित नहीं कर सकते हैं कि सभी कीड़े चले गए हैं, इसलिए आपको उन्हें उत्पादन में भी रखने की आवश्यकता है। और इसलिए मुखर कथन का उपयोग करने का कोई मतलब नहीं है, क्योंकि मुखर करने का एकमात्र लाभ यह है कि आप उन्हें बंद कर सकते हैं। इसलिए, इस सोच के अनुसार, आपको (लगभग) कभी भी जोर नहीं लगाना चाहिए। मैं असहमत हूं। यह निश्चित रूप से सच है कि यदि कोई परीक्षण उत्पादन में है, तो आपको एक मुखर का उपयोग नहीं करना चाहिए। लेकिन यह परीक्षण नहीं करता है उत्पादन में । यह एक बग को पकड़ने के लिए है जो कभी भी उत्पादन तक पहुंचने की संभावना नहीं है, इसलिए जब आप काम करते हैं तो यह सुरक्षित रूप से बंद हो सकता है।
BTW, मैं इसे इस तरह लिख सकता था:
assert value == null || value.equals("Y") || value.equals("N") : value;
यह केवल तीन मूल्यों के लिए ठीक है, लेकिन यदि संभावित मूल्यों की संख्या अधिक हो जाती है, तो हैशसेट संस्करण अधिक सुविधाजनक हो जाता है। मैंने दक्षता के बारे में अपनी बात बनाने के लिए हैशसेट संस्करण को चुना।
HashSetपर कोई गति लाभ होता है ArrayList। इसके अलावा, सेट और सूची क्रिएशन लुकअप टाइम पर हावी हैं। स्थिरांक का उपयोग करते समय वे ठीक होते हैं। उस सब ने कहा, +1।
दावे का उपयोग मूल रूप से अनुप्रयोग को डीबग करने के लिए किया जाता है या किसी एप्लिकेशन की वैधता की जांच के लिए कुछ एप्लिकेशन के अपवाद हैंडलिंग के प्रतिस्थापन में इसका उपयोग किया जाता है।
अभिकथन रन टाइम पर काम करता है। एक सरल उदाहरण, जो पूरी अवधारणा को बहुत सरलता से समझा सकता है, यह है - जावा में एसर कीवर्ड क्या करता है? (WikiAnswers)।
डिफ़ॉल्ट रूप से दावे अक्षम हैं। उन्हें सक्षम करने के लिए हमें -eaविकल्प के साथ कार्यक्रम चलाना चाहिए (बारीकता विविध हो सकती है)। उदाहरण के लिए, java -ea AssertionsDemo।
दावे का उपयोग करने के लिए दो प्रारूप हैं:
assert 1==2; // This will raise an AssertionError।assert 1==2: "no way.. 1 is not equal to 2";
यह एक AsserionError को बढ़ाए गए संदेश के साथ प्रदर्शित करेगा और इस तरह बेहतर है। हालाँकि वास्तविक वाक्यविन्यास वह है assert expr1:expr2जहाँ expr2 किसी भी मूल्य को लौटाने वाली कोई भी अभिव्यक्ति हो सकती है, मैंने इसका उपयोग अधिक बार केवल एक संदेश को प्रिंट करने के लिए किया है।पुनर्कथन करने के लिए (और यह सिर्फ जावा ही नहीं कई भाषाओं के लिए भी सच है):
"मुखर" मुख्य रूप से डिबगिंग प्रक्रिया के दौरान सॉफ़्टवेयर डेवलपर्स द्वारा डिबगिंग सहायता के रूप में उपयोग किया जाता है। मुखर-संदेश कभी प्रकट नहीं होने चाहिए। कई भाषाएं एक संकलन-समय विकल्प प्रदान करती हैं जो "उत्पादन" कोड को उत्पन्न करने में उपयोग के लिए सभी "जोर" को अनदेखा कर देगी।
"अपवाद" सभी प्रकार की त्रुटि स्थितियों को संभालने का एक आसान तरीका है, चाहे वे तर्क त्रुटियों का प्रतिनिधित्व करते हों या नहीं, क्योंकि, यदि आप एक त्रुटि-स्थिति में चलते हैं जैसे कि आप जारी नहीं रख सकते, तो आप बस उन्हें हवा में फेंक सकते हैं, "जहां से भी आप हैं, वहां से किसी और को उम्मीद है कि आप उन्हें पकड़ने" के लिए तैयार रहें। नियंत्रण एक चरण में स्थानांतरित किया जाता है, सीधे उस कोड से, जो अपवाद को फेंक देता है, सीधे पकड़ने वाले के मिट्ट में। (और पकड़ने वाला कॉल के पूर्ण बैकट्रेस को देख सकता है जो हुआ था।)
इसके अलावा, उस सबरूटीन के कॉल करने वालों को यह देखने के लिए जांचने की ज़रूरत नहीं है कि क्या सबरूटिन सफल हो गया है: "अगर हम अभी यहाँ हैं, तो यह सफल रहा होगा, क्योंकि अन्यथा यह एक अपवाद होता और हम अब यहाँ नहीं होते!" यह सरल रणनीति कोड-डिज़ाइन और डिबगिंग को बहुत आसान बनाती है।
अपवाद आसानी से घातक-त्रुटि की स्थिति की अनुमति देते हैं कि वे क्या हैं: "नियम के अपवाद।" और, उनके लिए एक कोड-पाथ द्वारा संभाला जा सकता है जो "नियम का अपवाद भी है ... " फ्लाई बॉल!
दावे चेक हैं जो बंद हो सकते हैं। वे शायद ही कभी इस्तेमाल किया जाता है। क्यों?
result != nullकि चेक बहुत तेज हैं और बचाने के लिए शायद ही कुछ है।तो, क्या बचा है? शर्तों के लिए महंगी जाँच वास्तव में सही होने की उम्मीद है। एक अच्छा उदाहरण आरबी-ट्री जैसे डेटा संरचना के आक्रमणकारी होंगे। वास्तव में, ConcurrentHashMapJDK8 में, के लिए कुछ ऐसे सार्थक मुखर हैं TreeNodes।
कभी-कभी, चेक वास्तव में महंगा नहीं है, लेकिन एक ही समय में, आप बहुत आश्वस्त हैं, यह पास हो जाएगा। मेरे कोड में, उदाहरण के लिए,
assert Sets.newHashSet(userIds).size() == userIds.size();
जहाँ मुझे पूरा यकीन है कि मैंने जो सूची बनाई है उसमें अद्वितीय तत्व हैं, लेकिन मैं इसे दस्तावेज़ बनाना और जांचना चाहता था।
असल में, "अस्सिटेंट ट्रू" पास हो जाएगा और "अस्सिटेंट असत्य" असफल हो जाएगा। आइए देखें कि यह कैसे काम करेगा:
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;
}
}
assertएक कीवर्ड है। इसे JDK 1.4 में पेश किया गया था। assertएस दो प्रकार के होते हैं
assertकथनassertकथन।डिफ़ॉल्ट रूप से सभी assertकथनों को निष्पादित नहीं किया जाएगा। यदि कोई assertकथन गलत है, तो यह स्वतः ही एक त्रुटि को बढ़ा देगा।