जावा में दो तर्कों की जाँच करें, या तो दोनों अशक्त नहीं हैं या दोनों अशक्त हैं


161

मैंने ईमेल भेजने के लिए उपयोग किए जाने वाले शेल प्रोजेक्ट को विकसित करने के लिए स्प्रिंग बूट का उपयोग किया, जैसे

sendmail -from foo@bar.com -password  foobar -subject "hello world"  -to aaa@bbb.com

यदि fromऔर passwordतर्क गायब हैं, तो मैं एक डिफ़ॉल्ट प्रेषक और पासवर्ड का उपयोग करता हूं, जैसे noreply@bar.comऔर 123456

इसलिए यदि उपयोगकर्ता fromतर्क पारित करता है तो उन्हें passwordतर्क को पारित करना होगा और इसके विपरीत। यह कहना है, या तो दोनों अशक्त हैं, या दोनों अशक्त हैं।

मैं इस सुरुचिपूर्ण तरीके से कैसे जांच करूं?

अब मेरा रास्ता है

if ((from != null && password == null) || (from == null && password != null)) {
    throw new RuntimeException("from and password either both exist or both not exist");
}

14
एक तरफ के रूप में, ध्यान दें कि व्हाट्सएप का उपयोग सावधानी से कोड को पढ़ने में बहुत आसान बनाता है - बस अपने वर्तमान कोड में ऑपरेटरों के बीच रिक्त स्थान जोड़ने से पठनीयता आईएमओ में काफी वृद्धि होगी।
जॉन स्कीट

8
कृपया "एलिगेंसी" को परिभाषित करें।
रेनाड

आपको SMTP प्रमाणीकरण क्रेडेंशियल और लिफाफा प्रेषक ई-मेल पते के लिए तर्कों का एक अलग सेट चाहिए। Fromई-मेल एड्रेस हमेशा SMTP प्रमाणीकरण नाम नहीं है।
काज

3
यह वास्तव में बहुत अधिक अनुकूलित नहीं हो सकता है, यह पठनीय कोड की एक पंक्ति है और इसे अधिक-अनुकूलित करके कुछ भी प्राप्त नहीं किया जा सकता है।
दिव्यंका

3
साइड नोट: यदि यह एक शेल स्क्रिप्ट है, तो क्या शेल इतिहास में पासवर्ड सहेजे नहीं जाएंगे?
मेरे शरीर को

जवाबों:


331

X^ ( XOR ) ऑपरेटर का उपयोग करने का एक तरीका है :

if (from == null ^ password == null) {
    // Use RuntimeException if you need to
    throw new IllegalArgumentException("message");
}

ifहालत सच हो सकता है अगर केवल एक चर रिक्त है।

लेकिन मुझे लगता है कि आमतौर पर ifविभिन्न अपवाद संदेशों के साथ दो स्थितियों का उपयोग करना बेहतर होता है । आप यह परिभाषित नहीं कर सकते कि किसी एक शर्त का उपयोग करके क्या गलत हुआ।

if ((from == null) && (password != null)) {
    throw new IllegalArgumentException("If from is null, password must be null");
}
if ((from != null) && (password == null)) {
    throw new IllegalArgumentException("If from is not null, password must not be null");
}

यह अधिक पठनीय है और समझने में बहुत आसान है, और यह केवल थोड़ा अतिरिक्त टाइपिंग करता है।


152
क्या एक कारण है कि दो बूल पर एक्सर दो बूल पर बेहतर है !=?
एरिक लिपर्ट

1
वाह, मुझे एहसास नहीं था कि बूलियन पर XOR जैसा ही है !=। होश उड़ जाना। और यह टिप्पणी में बहुत अधिक संख्या है। और, इस टिप्पणी में गुणवत्ता जोड़ने के लिए, हां, मुझे यह भी लगता है कि विभिन्न त्रुटि मामले के लिए अलग-अलग त्रुटि संदेश देना बेहतर है, क्योंकि उपयोगकर्ता को पता चल जाएगा कि त्रुटि को कैसे ठीक किया जाए।
जस्टफुल

1
2 तत्वों के लिए ठीक है। > 2 तत्वों के साथ यह कैसे करें?
अनुश्री जख्मी

मैं चाहता हूं कि कोई त्रुटि संदेश दिखाई दे अगर कोई भी तत्व है> 0. डिफ़ॉल्ट रूप से सभी को 0 पर सेट किया गया है। यदि सभी हैं> 0 एक वैध परिदृश्य है। यह कैसे करना है?
अनुश्री अचरी जूल

यह एक निफ्टी साक्षात्कार प्रश्न होगा। मुझे आश्चर्य है कि कितने% प्रोग्रामर इसे जानते हैं। लेकिन मैं इस बात से सहमत नहीं हूं कि यह स्पष्ट नहीं है और 2 ifखंडों में विभाजित वारंट - अपवाद दस्तावेजों में यह संदेश अच्छी तरह से (मैंने प्रश्न को संपादित किया, लेकिन यह तब तक प्रकट नहीं होगा)
एडम

286

ठीक है, ऐसा लगता है कि आप यह जांचने की कोशिश कर रहे हैं कि दोनों की "अशक्तता" स्थिति समान है या नहीं। आप उपयोग कर सकते हैं:

if ((from == null) != (password == null))
{
    ...
}

या सहायक चर के साथ इसे और अधिक स्पष्ट करें:

boolean gotFrom = from != null;
boolean gotPassword = password != null;
if (gotFrom != gotPassword)
{
    ...
}

18
आप मेरे SO हेरोस @Kaz में से एक हैं, लेकिन कुछ भी 'या तो यह या वह नहीं कहता है, लेकिन दोनों समान नहीं ^है। ' :-)
डेविड

6
@ डेविडविब्लॉक: जब यह बूलियन की बात आती है, तो कुछ भी नहीं कहता है "या तो यह या वह नहीं लेकिन दोनों एक ही" जैसे ... "दोनों एक ही नहीं"; XOR है Booleans पर "नहीं के बराबर है" समारोह के लिए सिर्फ एक और नाम।
कज़

5
@ काज यह सिर्फ इतना है ^कि "अरे, मेरे ऑपरेंड बुलियन हैं" इस तरह से !=नहीं है। (हालांकि यह प्रभाव दुर्भाग्य से "मेरे ऑपरेंड्स संख्यात्मक हो सकते हैं, और मैं इस समय इस मामले में एक रिलेशनल ऑपरेटर नहीं हो सकता हूं", जिसे मैं अनुदान देता हूं एक नुकसान है। आपका नायक का दर्जा कम हो गया, मेरे साथ असहमत होने के बावजूद :-)
डेविड बुलक

3
समस्या की आवश्यकताओं को पढ़ने के बाद, फिर आपका समाधान, कोड समझ में आता है और पठनीय है। लेकिन 4 साल (अभी भी स्कूल में) के एक डेवलपर के रूप में, इस कोड को पढ़ने के बाद यह पता लगाने की कोशिश की जा रही है कि "व्यापार की आवश्यकता" क्या थी, यह एक सिरदर्द होगा। इस कोड से, मुझे तुरंत समझ नहीं आया " fromऔर passwordदोनों को अशक्त होना चाहिए या दोनों अशक्त नहीं होना चाहिए"। शायद यह सिर्फ मैं और मेरी अनुभवहीनता है, लेकिन मैं @ stig-hemmer के उत्तर के रूप में अधिक पठनीय समाधान पसंद करता हूं, भले ही इसमें कोड की अन्य 3 पंक्तियां हों। मुझे लगता है कि मैं अभी तुरंत नहीं मिलता bool != bool - यह सहज नहीं है।
क्रिस क्रेफ़िस

2
@DavidBullock ^ऑपरेटर एक बिटवाइज़ ऑपरेटर है; यह वास्तव में इसका मतलब यह नहीं है कि इसके ऑपरेंड बूलियन हैं। बूलियन एक्सर ऑपरेटर है xor
Brilliand

222

व्यक्तिगत रूप से, मैं सुरुचिपूर्ण के लिए पठनीय पसंद करता हूं।

if (from != null && password == null) {
    throw new RuntimeException("-from given without -password");
}
if (from == null && password != null) {
    throw new RuntimeException("-password given without -from");
}

52
बेहतर संदेशों के लिए +1। यह है महत्वपूर्ण है, कोई भी नहीं पसंद handwaving "कुछ गलत हो गया" -त्रुटि संदेश, इसलिए कोई भी चाहिए कारण इस तरह के संदेशों। हालांकि, व्यवहार में, किसी को अधिक विशिष्ट अपवाद (विशेष रूप से, IllegalArgumentExceptionएक नंगे के बजाय RuntimeException) को पसंद करना चाहिए
Marco13

6
@ यह ऐसा लगता है कि आपकी आलोचना कोड के साथ नहीं है, बल्कि अपवादों के पाठ के साथ है। लेकिन मुझे लगता है कि इस उत्तर की योग्यता यदि त्रुटि संदेश की सामग्री में नहीं, तो बयानों की संरचना में निहित है। यह सबसे अच्छा जवाब है क्योंकि यह कार्यक्षमता में सुधार करता है; ओपी आसानी से अपवाद ग्रंथों के लिए वे जो भी तार पसंद करते हैं, उसे स्थानापन्न कर सकते हैं।
डैन हेंडरसन

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

4
@DanHenderson> यह कहना अच्छा नहीं है कि "आपने इनमें से एक काम को गलत किया है।" मैं असहमत हूं। पासवर्ड / यूजरनेम यह सुरक्षित है कि उपयोगकर्ता नाम और पासवर्ड का मिलान न हो।
मैट

2
@DanHenderson सुरक्षा के दृष्टिकोण से यह बेहतर हो सकता है कि मामले में अंतर न करें जहां उपयोगकर्ता नाम निर्देशिका में है या नहीं अन्यथा एक हमलावर को वैध उपयोगकर्ता नाम पता चल सकता है। हालाँकि, null / not null को मिक्स करना (इस मामले में) हमेशा एक उपयोग त्रुटि है और अधिक विस्तृत त्रुटि संदेश दिखाने से पहली जगह में दिए गए उपयोगकर्ता की तुलना में कोई और जानकारी लीक नहीं होती है।
सियगी

16

हस्ताक्षर के साथ उस कार्यक्षमता को 2 तर्क पद्धति में रखें:

void assertBothNullOrBothNotNull(Object a, Object b) throws RuntimeException

यह उस वास्तविक विधि में स्थान बचाता है जिसमें आप रुचि रखते हैं और इसे अधिक पठनीय बनाते हैं। थोड़ा वर्बोज़ विधि नामों के साथ कुछ भी गलत नहीं है और बहुत कम तरीकों के साथ कुछ भी गलत नहीं है।


14
कोई स्थान नहीं बचा बनाम ((from == null) != (password == null))जो बहुत सरल है। उपयोगी तरीकों के साथ कुछ गड़बड़ है।
edc65

3
इफ स्टेटमेंट के लिए एक लाइन है, थ्रो स्टेटमेंट के लिए दूसरी लाइन और क्लोजिंग ब्रेस के लिए तीसरी लाइन है: ऑल इन वन लाइन। यदि आप समापन ब्रेसिज़ को एक नई पंक्ति देते हैं, तो एक और पंक्ति सहेजी जाती है!
त्रुबेनफुच्स

10
कोड को पढ़ते समय आपके पास एक विधि का नाम होता है जिसे आपको शर्त शर्त से समझने की आवश्यकता होती है।
त्रुबेनफुच्स

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

1
यदि आप यहां कुछ वर्णनात्मक अपवाद संदेश चाहते हैं तो आप अनावश्यक परेशानी में चले जाएंगे।
होन्जा ब्रेबेक

11

एक Objects.isNull(Object)स्थैतिक आयात मानते हुए, जावा 8 समाधान का उपयोग करना होगा :

if (isNull(from) != isNull(password)) {
    throw ...;
}

जावा <8 के लिए (या यदि आपको उपयोग करना पसंद नहीं है Objects.isNull()), तो आप आसानी से अपनी isNull()विधि लिख सकते हैं ।


6
यह पसंद नहीं है। from == null != password == nullयह सब स्टैक के एक ही फ्रेम पर रहता है, लेकिन Objects.isNull(Object)अनावश्यक रूप से धक्का और दो फ्रेम का उपयोग करता है। Objects.isNull (ऑब्जेक्ट) वहाँ है क्योंकि 'यह विधि एक प्रेडिकेट के रूप में इस्तेमाल होने के लिए मौजूद है' (अर्थात, धाराओं में)।
डेविड बुलॉक

5
इस तरह की एक सरल विधि आम तौर पर जेआईटी द्वारा जल्दी से इनलाइन की जाएगी ताकि प्रदर्शन प्रभाव सबसे अधिक नगण्य हो। हम वास्तव में इसके उपयोग पर बहस Objects.isNull()कर सकते हैं - यदि आप चाहें तो आप अपना स्वयं का लिख ​​सकते हैं - लेकिन जहाँ तक पठनीयता का संबंध है, मुझे लगता है कि इसका उपयोग isNull()करना बेहतर है। इसके अलावा आपको सरल अभिव्यक्ति को संकलित करने के लिए अतिरिक्त कोष्ठक की आवश्यकता है from == null != (password == null):।
डिडिएर एल

2
मैं JIT'ing के बारे में सहमत हूं (और संचालन का क्रम ... मैं आलसी था)। फिर भी, (val == null)इतना है बहुत प्रदान की सुविधा अशक्त के साथ तुलना के प्रयोजन के लिए, मैं यह मुश्किल दो बड़े वसा विधि आमंत्रण से अधिक प्राप्त करने के लिए मुझे चेहरे में घूर लगता है, भले ही विधि काफी कार्यात्मक है, इन-lineable, और अच्छी तरह से नाम दिया है। हालांकि यह सिर्फ मुझे है। मैंने हाल ही में फैसला किया है कि मैं हल्का अजीब हूं।
डेविड बुलॉक

4
ईमानदारी से, एक एकल स्टैक फ्रेम के बारे में कौन परवाह करता है? स्टैक केवल कभी एक समस्या है यदि आप (संभवतः अनंत) पुनरावृत्ति के साथ काम कर रहे हैं, या यदि आपके पास ऑब्जेक्ट ग्राफ के साथ 1000-tiered अनुप्रयोग है, तो सहारा रेगिस्तान का आकार।
सारा

9

यहां किसी भी प्रकार की अशक्त जांच के लिए एक सामान्य समाधान दिया गया है

public static int nulls(Object... objs)
{
    int n = 0;
    for(Object obj : objs) if(obj == null) n++;
    return n;
}

public static void main (String[] args) throws java.lang.Exception
{
    String a = null;
    String b = "";
    String c = "Test";

    System.out.println (" "+nulls(a,b,c));
}

उपयोग

// equivalent to (a==null & !(b==null|c==null) | .. | c==null & !(a==null|b==null))
if (nulls(a,b,c) == 1) { .. }

// equivalent to (a==null | b==null | c==null)
if (nulls(a,b,c) >= 1) { .. }

// equivalent to (a!=null | b!=null | c!=null)
if (nulls(a,b,c) < 3) { .. }

// equivalent to (a==null & b==null & c==null)
if (nulls(a,b,c) == 3) { .. }

// equivalent to (a!=null & b!=null & c!=null)
if (nulls(a,b,c) == 0) { .. }

2
अच्छा तरीका है, लेकिन आपकी पहली "टिप्पणी के बराबर" बुरी तरह से गलत है (सभी टिप्पणियों में मौजूद वर्तनी की गलती से परे)
बेन वोइगट

@BenVoigt ने नोटिस के लिए धन्यवाद, अब तय किया
खालिद.क

9

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

// use defaults if neither is provided
if ((from == null) && (password == null)) {
    from = DEFAULT_SENDER;
    password = DEFAULT_PASSWORD;
}

// we should have a sender and a password now
if (from == null) {
    throw new MissingSenderException();
}
if (password == null) {
    throw new MissingPasswordException();
}

एक अतिरिक्त लाभ यह है कि, आपकी किसी भी चूक को शून्य होना चाहिए, इसका भी पता लगाया जाएगा।


यह कहते हुए कि, सामान्य तौर पर मुझे लगता है कि XOR का उपयोग तब स्वीकार्य होना चाहिए जब वह ऑपरेटर हो जिसकी आपको आवश्यकता है। यह भाषा का एक हिस्सा है, न कि केवल कुछ ट्रिक जो आर्कन कंपाइलर-बग की वजह से काम करती है।
मेरे पास एक बार एक गाय-भक्षक था जो टर्नरी ऑपरेटर को भी उपयोग करने के लिए भ्रमित कर रहा था ...


1
डाउनवोट किया गया क्योंकि मैंने आपके उत्तरों में से एक का नमूना लेने के लिए एक यादृच्छिक पिक बनाई थी और वादा किए गए xkcd लिंक को नहीं खोज सका! तुम्हे शर्म आनी चाहिए!
डेहिन

@Zaibis मेरे बचाव में, यह केवल एक शौक है, पूर्णकालिक नौकरी नहीं। लेकिन मैं देखूंगा कि क्या मुझे एक मिल सकता है ...
SQB

8

मैं एक और विकल्प सुझाना चाहूंगा कि मैं वास्तव में इस कोड को कैसे लिखूंगा:

if( from != null )
{
    if( password == null )
        error( "password required for " + from );
}
else
{
    if( password != null )
        warn( "the given password will not be used" );
}

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

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


मैं कुछ हद तक संवैधानिक रूप से टिप्पणी करता हूं, इसलिए मैं "// हमारे पास एक अशक्त" है। उदाहरण की संक्षिप्तता इसे वास्तव में मामूली बनाती है। मुझे तर्क की स्पष्टता और इस प्रस्तुत करने वाले परीक्षणों को कम करना पसंद है।
नैट

यह पूरी तरह से अच्छी तरह से काम करता है, लेकिन अगर बयान कम स्पष्ट और अधिक मुझे लगता है कि घोंसले के शिकार है। हालांकि, यह सिर्फ व्यक्तिगत राय है, इसलिए मुझे खुशी है कि यह जवाब यहां एक और विकल्प के रूप में है
केविन वेल्स

जहाँ तक लालित्य जाता है, यह शायद ऐसा करने के लिए कम से कम सुरुचिपूर्ण तरीकों में से एक है।
7

7

मुझे लगता है कि इसे संभालने का एक सही तरीका तीन स्थितियों पर विचार करना है: 'से' और 'पासवर्ड' दोनों प्रदान किए जाते हैं, न ही प्रदान किए जाते हैं, दोनों का मिश्रण प्रदान किया जाता है।

if(from != null && password != null){
    //use the provided values
} else if(from == null && password == null){
    //both values are null use the default values
} else{
   //throw an exception because the input is not correct.
}

ऐसा लगता है कि मूल प्रश्न प्रवाह को तोड़ना चाहता है यदि यह गलत इनपुट है, लेकिन फिर उन्हें बाद में कुछ तर्क दोहराना होगा। शायद एक अच्छा फेंक बयान हो सकता है:

throw new IllegalArgumentException("form of " + form + 
    " cannot be used with a "
    + (password==null?"null":"not null") +  
    " password. Either provide a value for both, or no value for both"
);

2
यह कोड गलत है क्योंकि यह काम नहीं करता है, क्योंकि यह समझना बहुत कठिन है। उस तरह का कोड डीबग करना, जो किसी और द्वारा लिखा गया है, सिर्फ एक बुरा सपना है।
NO

2
@NO_NAME मैं यह नहीं देखता कि इसे समझना कठिन क्यों है। ओपी ने तीन मामलों को प्रदान किया: जब फॉर्म और पासवर्ड दोनों प्रदान किए जाते हैं, जब कोई भी प्रदान नहीं किया जाता है, और मिश्रित मामला जो अपवाद को फेंकना चाहिए। क्या आप मध्य सशर्त का उल्लेख करने के लिए जाँच कर रहे हैं कि क्या वे दोनों अशक्त हैं?
मैट

2
मैं @NO_NAME से सहमत हूं, उस मध्य मामले को नज़र अंदाज़ करने में बहुत अधिक निराशा हो रही है। जब तक आप शीर्ष पंक्ति को पार्स नहीं करते हैं, तब तक आपको यह नहीं मिलता है कि मध्य के साथ कुछ भी नहीं है। उस मामले में से और पासवर्ड की समानता वास्तव में अशक्त न होने का केवल एक साइड-इफेक्ट है।
--१०११

1
@ jimm101 हाँ, मैं देख सकता था कि एक मुद्दा है। अधिक वर्बोज़ समाधान के लिए प्रदर्शन लाभ न्यूनतम / गैर-डिटेक्टेबल होगा। मुझे यकीन नहीं है कि अगर यह मुद्दा है, तो क्या होगा। इसे अपडेट करें।
मैट

2
@matt प्रदर्शन लाभ नहीं हो सकता है - यह स्पष्ट नहीं है कि कंपाइलर क्या करेगा, और चिप इस मामले में मेमोरी से क्या खींचेगा। बहुत सारे प्रोग्रामर साइकिल को उन अनुकूलन पर जलाया जा सकता है जो वास्तव में कुछ भी नहीं देते हैं।
जीमां १०१

6

यहाँ एक अपेक्षाकृत सीधा-आगे का रास्ता है जिसमें कोई Xor og और ify शामिल नहीं है। हालाँकि, इसके लिए आपको थोड़ा और क्रिया करने की आवश्यकता होती है, लेकिन उल्टा, आप कस्टम अपवादों का उपयोग कर सकते हैं, जिनके बारे में मैंने एक और सार्थक त्रुटि संदेश प्राप्त करने का सुझाव दिया है।

private void validatePasswordExists(Parameters params) {
   if (!params.hasKey("password")){
      throw new PasswordMissingException("Password missing");
   }
}

private void validateFromExists(Parameters params) {
   if (!params.hasKey("from")){
      throw new FromEmailMissingException("From-email missing");
   }
}

private void validateParams(Parameters params) {

  if (params.hasKey("from") || params.hasKey("password")){
     validateFromExists(params);
     validatePasswordExists(params);
  }
}

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

1
@anphu नहीं, बस नहीं। अपवादों का उपयोग करने से कोड की पठनीयता बढ़ जाती है क्योंकि यह अगर-और क्लॉस से छुटकारा पाता है और कोड फ्लो को स्पष्ट करता है। docs.oracle.com/javase/tutorial/essential/exception/…
अर्नब दत्ता

1
मुझे लगता है कि आप कुछ भ्रमित कर रहे हैं जो वास्तव में असाधारण बनाम कुछ ऐसा है जो नियमित रूप से होता है और इसे सामान्य निष्पादन का हिस्सा माना जा सकता है। जावा डॉक ऐसे उदाहरणों का उपयोग करता है जो फ़ाइल पढ़ते समय असाधारण यानी मेमोरी से बाहर हैं; अमान्य पैरामिक्स का सामना करना असाधारण नहीं है। "नियंत्रण के सामान्य प्रवाह के अपवादों का उपयोग न करें।" - blogs.msdn.com/b/kcwalina/archive/2005/03/16/396787.aspx
एक फू

ठीक है, पहले: यदि अनुपलब्ध / उचित तर्क असाधारण नहीं है, तो IllegalArgumentException तब भी मौजूद क्यों है? दूसरा: यदि आप वास्तव में मानते हैं कि अमान्य तर्क असाधारण नहीं हैं, तो इसका सत्यापन भी नहीं होना चाहिए। दूसरे शब्दों में, बस कार्रवाई करने की कोशिश करें और जब कुछ गलत हो जाए, तो एक अपवाद फेंक दें। यह दृष्टिकोण ठीक है, लेकिन आप जिस प्रदर्शन के दंड की बात कर रहे हैं, वह यहाँ किया गया है, मेरे द्वारा सुझाए गए दृष्टिकोण में नहीं। फेंके जाने पर जावा अपवाद धीमा नहीं होता है; यह स्टैक्ट्रेस है जिसे ठीक होने में समय लगता है।
अर्नब दत्ता

प्रसंग प्रमुख है। ओपी के संदर्भ में (सेंडमेल ऐप), उपयोगकर्ता नाम और पासवर्ड भूल जाना आम और अपेक्षित है। एक मिसाइल मार्गदर्शन में, एक अशक्त समन्वय परम को एक अपवाद फेंकना चाहिए। मैंने नहीं कहा कि परमों को मान्य मत करो। ओपी के संदर्भ में, मैंने कहा कि एप्लिकेशन लॉजिक को चलाने के लिए अपवाद का उपयोग न करें। स्टैकट्रेस को अनसुना करने से मैं जिस हिट के बारे में बात कर रहा हूं, वह सही है। अपने दृष्टिकोण का उपयोग करते हुए, अंत में आप या तो PasswordMissingException / FromEmailMissingException को पकड़ते हैं, यानी खोलना, या इससे भी बदतर, इसे अनहेल्दी होने देना। ।
एक फु

6

किसी को भी टेरीनेरी ऑपरेटर का उल्लेख नहीं लगता है :

if (a==null? b!=null:b==null)

इस विशेष स्थिति की जाँच के लिए अच्छी तरह से काम करता है, लेकिन पिछले दो चर को सामान्य नहीं करता है।


1
दिखता है अच्छा है, लेकिन कठिन से समझने के लिए ^, !=दो bools या दो के साथ ifरों
Coolguy

@coolguy मेरा अनुमान है कि टर्नरी ऑपरेटर XOR ऑपरेटर की तुलना में कहीं अधिक सामान्य है (हर बार जब आप XOR को कोड में नहीं देखते हैं तो 'मानसिक आश्चर्य' का उल्लेख नहीं होता है), और यह सूत्रीकरण कट से बचने के लिए होता है। और त्रुटियों को चिपकाएँ जो डबल प्लेग करते हैं यदि।
1930 पर गॉबनर

सिफारिश नहीं की गई। यह (a! = Null && b == null) और (a == n & && b! = Null) के बीच अंतर नहीं होगा। यदि आप टर्नरी ऑपरेटर का उपयोग करने जा रहे हैं:a == null ? (b == null? "both null" : "a null while b is not") : (b ==null? "b null while a is not")
अर्नब दत्ता

5

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

छद्म में लिखा इस तरह होना चाहिए:

if (from == null) { // form is null, ignore given password here
    // use your own defaults
} else if (password == null) { // form is given but password is not
    // throw exception
} else { // both arguments are given
    // use given arguments
}

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

4

मुझे आश्चर्य है कि किसी ने वर्ग के क्षेत्रों को बनाने fromऔर passwordउस वर्ग के उदाहरण के संदर्भ में दिए गए सरल समाधान का उल्लेख नहीं किया है :

class Account {
    final String name, password;
    Account(String name, String password) {
        this.name = Objects.requireNonNull(name, "name");
        this.password = Objects.requireNonNull(password, "password");
    }
}

// the code that requires an account
Account from;
// do stuff

यहाँ from अशक्त या गैर-अशक्त हो सकता है और यदि यह गैर-अशक्त है, तो इसके दोनों क्षेत्रों में गैर-शून्य मान हैं।

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

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


यह अपेक्षा के अनुरूप काम नहीं करता है क्योंकि new Account(null, null)NPE फेंकने के बाद भी खाता नाम और पासवर्ड दोनों के साथ मान्य है।
हियुथ

यदि नाम और पासवर्ड शून्य हैं, तो यह विचार करना है कि वास्तविक दुनिया में आप खाते के अस्तित्व में हैं या नहीं।
मोनिका

ओपी से मुझे जो मिलता है, वह यह है कि या तो दोनों गैर-अशक्त हैं, या दोनों अशक्त हैं। मैं बस सोच रहा था कि आप नाम और पासवर्ड दोनों अशक्त के साथ एक खाता ऑब्जेक्ट कैसे बना सकते हैं?
हियुहेट

@HieuHT क्षमा करें मेरी अंतिम टिप्पणी अस्पष्ट थी। यदि नाम और पासवर्ड शून्य हैं, तो आप nullइसके बजाय उपयोग करेंगे Account। आप पास नहीं होगा nullकरने के लिए Accountनिर्माता।
मोनिका
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.