क्या सिंटैक्स बैड प्रैक्टिस को संतुष्ट करने के लिए रिटर्न स्टेटमेंट है?


82

निम्नलिखित कोड पर विचार करें:

public Object getClone(Cloneable a) throws TotallyFooException {

    if (a == null) {
        throw new TotallyFooException();
    }
    else {
        try {
            return a.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
    }
    //cant be reached, in for syntax
    return null;
}

यह return null;आवश्यक है क्योंकि एक अपवाद को पकड़ा जा सकता है, हालांकि इस तरह के मामले में जब से हम पहले से ही जाँच कर चुके हैं कि क्या यह अशक्त था (और हमें लगता है कि हम उस वर्ग को जानते हैं जिसे हम क्लोनिंग का समर्थन कहते हैं) तो हम जानते हैं कि कोशिश कथन कभी विफल नहीं होगा।

क्या सिंटैक्स को संतुष्ट करने और संकलन त्रुटियों से बचने के लिए अंत में अतिरिक्त रिटर्न स्टेटमेंट में डालना बुरा व्यवहार है (एक टिप्पणी के साथ यह समझा नहीं जा सकेगा), या इस तरह से कुछ कोड करने का एक बेहतर तरीका है ताकि अतिरिक्त रिटर्न स्टेटमेंट अनावश्यक है


25
आपका तरीका एक Objectपैरामीटर लेता है । यदि aवह वर्ग नहीं है जो cloneविधि का समर्थन करता है (या यह परिभाषित किया गया है Object?) या यदि cloneविधि के दौरान कोई त्रुटि होती है (या कोई अन्य गलती जो मैं अभी नहीं सोच सकता हूं), तो एक अपवाद फेंका जा सकता है और आप पहुंच जाएंगे वापसी विवरण।
आर्क

26
आपकी धारणा है कि अंतिम रिटर्न तक नहीं पहुंचा जा सकता गलत है। यह पूरी तरह से उस वर्ग के लिए मान्य है जो Cloneableफेंकने के लिए लागू करता है CloneNotSupportedException। स्रोत: javadocs
Cephalopod

20
जिस कोड पर आपने टिप्पणी की है, वह "कैंट नहीं पहुँचा जा सकता है" तक पहुँचा जा सकता है। जैसा कि ऊपर उल्लेख किया गया है कि इस पंक्ति के CloneNotSupportedException से एक कोड पथ है।
डेविड वाटरवर्थ

7
यहां मूल प्रश्न: यदि आप उस वर्ग को मान रहे हैं जिसे आप क्लोनिंग का समर्थन करते हैं, तो आप अपवाद को क्यों पकड़ रहे हैं? अपवादों को असाधारण व्यवहार के लिए फेंक दिया जाना चाहिए
डेवॉर्ड

3
@ के AssertionErrorबजाय मैं के लिए जाना होगा InternalError। बाद में विशेष उपयोग के लिए लगता है अगर JVM में कुछ गलत हो जाता है। और आप मूल रूप से जोर देते हैं कि कोड नहीं पहुंचा है।
kap

जवाबों:


134

अतिरिक्त रिटर्न स्टेटमेंट के बिना एक स्पष्ट तरीका इस प्रकार है। मैं CloneNotSupportedExceptionया तो पकड़ नहीं सकता, लेकिन यह फोन करने वाले को जाने दो।

if (a != null) {
    try {
        return a.clone();
    } catch (CloneNotSupportedException e) {
        e.printStackTrace();
    }
}
throw new TotallyFooException();

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


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

3
@BillK: इस कोड के अलग-अलग शब्दार्थ हैं, जैसा कि Maroun Maroun द्वारा बताया गया है।
डेडुप्लिकेटर

5
AssertionErrorएक बिल्ट-इन क्लास है, जिसका उद्देश्य समान है TotallyFooException(जो वास्तव में मौजूद नहीं है)।
user253751

5
@ बलीक: "यदि आप अपने आप को जावा की आवश्यकताओं से लड़ते हुए पाते हैं तो इसका आम तौर पर अर्थ है कि आप सब-इष्टतम तरीके से कुछ करने की कोशिश कर रहे हैं।" या कि जावा ने एक ऐसी सुविधा का समर्थन नहीं करने का फैसला किया है जो आपके जीवन को आसान बनाता है।
user541686

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

101

जरूर पहुंचा जा सकता है। ध्यान दें कि आप केवल catchखंड में स्टैकट्रेस प्रिंट कर रहे हैं ।

जहां परिदृश्य में a != nullऔर वहाँ जाएगा एक अपवाद हो,return null होगा पहुँचा जा। आप उस स्टेटमेंट को हटा सकते हैं और उसे बदल सकते हैं throw new TotallyFooException();

सामान्य तौर पर * , अगर nullएक है वैध एक विधि का परिणाम (यानी उपयोगकर्ता की उम्मीद है यह और यह कुछ का मतलब है) तो के लिए "डेटा नहीं मिला" या अपवाद हुआ है एक संकेत के रूप में यह लौटने नहीं एक अच्छा विचार है। अन्यथा, मुझे कोई समस्या नहीं दिखाई देती है कि आपको क्यों नहीं लौटना चाहिए null

उदाहरण के लिए लें Scanner#ioException विधि :

IOExceptionइस स्कैनर के अंतर्निहित पठनीय द्वारा अंतिम फेंक दिया गया रिटर्न । इस विधि रिटर्न अशक्त अगर ऐसी कोई अपवाद जरूर है

इस मामले में, लौटे मूल्य nullका एक स्पष्ट अर्थ है, जब मैं विधि का उपयोग करता हूं तो मुझे यकीन हो सकता है कि मुझे nullकेवल इसलिए मिला क्योंकि ऐसा कोई अपवाद नहीं था और इसलिए नहीं कि विधि ने कुछ करने की कोशिश की और यह विफल रही।

* ध्यान दें कि कभी-कभी आप nullतब भी लौटना चाहते हैं जब अर्थ अस्पष्ट हो। उदाहरण के लिए HashMap#get:

नल का एक वापसी मूल्य जरूरी नहीं दर्शाता है कि नक्शे में कुंजी के लिए कोई मैपिंग नहीं है; यह भी संभव है कि मानचित्र स्पष्ट रूप से नल की कुंजी को दर्शाता होcontainsKeyआपरेशन इन दो मामलों भेद करने के लिए इस्तेमाल किया जा सकता है।

इस मामले में nullसंकेत कर सकते हैं कि मूल्य null पाया गया था और वापस लौटा, या हैशमैप में अनुरोधित कुंजी शामिल नहीं है।


4
यद्यपि आपके बिंदु वैध हैं, मैं यह इंगित करना चाहूंगा कि यह केवल भद्दा एपीआई डिज़ाइन है। दोनों विधियों को क्रमशः Optional<Throwable>या Optional<TValue>, वापस आना चाहिए । नोट: यह आपके जवाब की आलोचना नहीं है, बल्कि उन दो तरीकों के एपीआई डिजाइन की है। (हालांकि, यह एक सामान्य डिजाइन की गलती है, जो न केवल संपूर्ण जावा एपीआई, बल्कि .NET के रूप में अच्छी तरह से व्याप्त है।)
जॉर्ग डब्ल्यू मित्तग

4
"गंदे" बल्कि कठोर है यदि आपको नहीं पता कि जावा 8 सुविधाओं का उपयोग किया जा सकता है या नहीं।
थोरबजोरन रावन एंडरसन

2
लेकिन जब वैध रिटर्न वैल्यू नहीं होती nullहै , तो रिटर्निंग और भी बुरा विचार होता है। दूसरे शब्दों में, अप्रत्याशित स्थिति के लिए वापस लौटना कभी अच्छा विचार नहीं है। nullnull
होल्गर

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

1
वह बिंदु है: "उपयोगकर्ता को पता होना चाहिए कि इस स्थिति को कैसे संभालना है" तात्पर्य है कि आपको यह निर्दिष्ट करना होगा कि nullएक संभावित वापसी मूल्य है जिसे कॉल करने वाले को निपटना होगा। यह इसे एक वैध मूल्य बनाता है, और हमारे पास "मान्य" की समान समझ है, जैसा कि आप "वैध" का वर्णन करते हैं, जैसा कि "उपयोगकर्ता यह उम्मीद करता है और इसका अर्थ है"। लेकिन यहां, स्थिति वैसे भी अलग है। ओपी प्रति कोड टिप्पणी करता है कि वह दावा करता है कि return null;"केंट नहीं पहुंचा जा सकता" जिसका अर्थ है कि वापस लौटना nullगलत है। इसके throw new AssertionError();बजाय होना चाहिए ...
होल्गर

26

क्या सिंटैक्स को संतुष्ट करने और संकलन त्रुटियों से बचने के लिए अंत में अतिरिक्त रिटर्न स्टेटमेंट में डालना बुरा व्यवहार है (एक टिप्पणी के साथ यह समझा नहीं जाएगा)

मुझे लगता return nullहै कि एक अप्राप्य शाखा के टर्मिनस के लिए बुरा अभ्यास है। RuntimeException( AssertionErrorयह भी स्वीकार्य होगा) फेंकने के लिए बेहतर है क्योंकि उस रेखा को प्राप्त करने के लिए कुछ बहुत गलत हो गया है और आवेदन अज्ञात स्थिति में है। ज्यादातर यह पसंद है (ऊपर की तरह) क्योंकि डेवलपर ने कुछ याद किया है (ऑब्जेक्ट कोई भी नहीं हो सकता है-शून्य और गैर-क्लोन करने योग्य)।

InternalErrorजब तक मुझे बहुत यकीन नहीं होता कि मैं कोड का उपयोग नहीं कर पा रहा हूँ (उदाहरण के बाद a System.exit()) के रूप में इसका उपयोग करने की संभावना नहीं है क्योंकि यह अधिक संभावना है कि मैं VM से गलती करता हूँ।

मैं केवल एक कस्टम अपवाद का उपयोग करता हूं (जैसे कि TotallyFooException) यदि उस "अगम्य रेखा" पर पहुंचने का अर्थ है कि आप उस अपवाद को फेंकने के अलावा कहीं और भी हैं।


3
जैसा कि टिप्पणियों में कहीं और उल्लेख किया गया है, AssertionErrorएक "ऐसा नहीं हो सकता" घटना में फेंकने के लिए एक उचित विकल्प भी हो सकता है ।
इल्मरी करोनें

2
व्यक्तिगत रूप से मैं एक फेंक देंगे SomeJerkImplementedClonableAndStillThrewACloneNotSupportedExceptionException। यह RuntimeExceptionस्पष्ट रूप से विस्तारित होगा ।
w25r

@ w25r मैं ऊपर दिए गए कोड का उपयोग नहीं कर रहा हूं, लेकिन अंतर्निहित प्रश्न का उत्तर दे रहा हूं। यह देखते हुए Cloneableकि एक सार्वजनिक clone()पद्धति लागू नहीं होती है और clone()वस्तु protectedवास्तव में ऊपर का कोड संकलित नहीं होता है।
माइकल लॉयड ली mlk

मैं एक निष्क्रिय-आक्रामक अपवाद का उपयोग नहीं करूंगा बस अगर यह बच गया (जैसा कि हमारे ग्राहकों में से एक के लिए यह उतना ही मज़ेदार होगा JerkException, मुझे नहीं लगता कि इसकी सराहना की जाएगी)।
माइकल लॉयड ली mlk

14

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


12

मैं Objects.requireNonNull()जांचने के लिए उपयोग करना पसंद करूंगा कि क्या पैरामीटर एक अशक्त नहीं है। इसलिए यह स्पष्ट है जब आप कोड पढ़ते हैं कि पैरामीटर शून्य नहीं होना चाहिए।

और जाँच अपवाद से बचने के लिए मैं CloneNotSupportedExceptionएक के रूप में फेंकना होगा RuntimeException

दोनों के लिए आप इस उद्देश्य के साथ अच्छा पाठ जोड़ सकते हैं कि ऐसा क्यों नहीं होना चाहिए या ऐसा नहीं होना चाहिए।

public Object getClone(Object a) {

    Objects.requireNonNull(a);

    try {
        return a.clone();
    } catch (CloneNotSupportedException e) {
        throw new IllegalArgumentException(e);
    }

}

7

इस तरह की स्थिति में मैं लिखूंगा

public Object getClone(SomeInterface a) throws TotallyFooException {
    // Precondition: "a" should be null or should have a someMethod method that
    // does not throw a SomeException.
    if (a == null) {
        throw new TotallyFooException() ; }
    else {
        try {
            return a.someMethod(); }
        catch (SomeException e) {
            throw new IllegalArgumentException(e) ; } }
}

दिलचस्प रूप से आप कहते हैं कि "कोशिश बयान कभी विफल नहीं होगा", लेकिन आपने अभी भी एक बयान लिखने के लिए परेशानी उठाई है e.printStackTrace();कि आप दावा करते हैं कि कभी भी निष्पादित नहीं किया जाएगा। क्यों?

शायद आपका विश्वास ऐसा नहीं है जो दृढ़ता से आयोजित किया गया हो। यह अच्छा है (मेरी राय में), चूंकि आपका विश्वास आपके द्वारा लिखे गए कोड पर आधारित नहीं है, बल्कि इस अपेक्षा पर है कि आपका क्लाइंट पूर्व शर्त का उल्लंघन नहीं करेगा। सार्वजनिक तौर पर रक्षात्मक तरीके से कार्यक्रम करना बेहतर है।

वैसे, आपका कोड मेरे लिए संकलन नहीं करेगा। आप कॉल नहीं कर सकते हैं a.clone(), भले ही के प्रकार aहै Cloneable। कम से कम ग्रहण का कंपाइलर ऐसा कहता है। अभिव्यक्ति a.clone()त्रुटि देती है

विधि क्लोन () क्लोन करने योग्य प्रकार के लिए अपरिभाषित है

आपके विशिष्ट मामले के लिए मैं क्या करूंगा

public Object getClone(PubliclyCloneable a) throws TotallyFooException {
    if (a == null) {
        throw new TotallyFooException(); }
    else {
        return a.clone(); }
}

कहाँ PubliclyCloneableसे परिभाषित किया गया है

interface PubliclyCloneable {
    public Object clone() ;
}

या, यदि आपको पूरी तरह से पैरामीटर प्रकार की आवश्यकता है Cloneable, तो निम्नलिखित कम से कम संकलित करता है।

public static Object getClone(Cloneable a) throws TotallyFooException {
//  Precondition: "a" should be null or point to an object that can be cloned without
// throwing any checked exception.
    if (a == null) {
        throw new TotallyFooException(); }
    else {
        try {
            return a.getClass().getMethod("clone").invoke(a) ; }
        catch( IllegalAccessException e ) {
            throw new AssertionError(null, e) ; }
        catch( InvocationTargetException e ) {
            Throwable t = e.getTargetException() ;
            if( t instanceof Error ) {
                // Unchecked exceptions are bubbled
                throw (Error) t ; }
            else if( t instanceof RuntimeException ) {
                // Unchecked exceptions are bubbled
                throw (RuntimeException) t ; }
            else {
                // Checked exceptions indicate a precondition violation.
                throw new IllegalArgumentException(t) ; } }
        catch( NoSuchMethodException e ) {
            throw new AssertionError(null, e) ; } }
}

संकलन-समय की त्रुटि मुझे यह सोचने के लिए मिली कि सार्वजनिक विधि के रूप में Cloneableघोषित क्यों नहीं किया cloneगया है जो किसी भी जाँच अपवाद को नहीं फेंकता है। Bugs.java.com/view_bug.do?bug_id=4098033
थियोडोर

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

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

6

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

public Object getClone(Cloneable a) throws CloneNotSupportedException {
    return a.clone();
}

aयह देखने के लिए जाँच करने के लिए कोई लाभ नहीं है कि क्या यह अशक्त है। यह एनपीई के लिए जा रहा है। स्टैक ट्रेस प्रिंट करना भी उपयोगी नहीं है। स्टैक ट्रेस एक ही है, भले ही इसे संभाला जाए।

कोड को अनहेल्दी नल टेस्ट और अनहेल्फ़ अपवाद अपवाद हैंडलिंग के साथ जोड़ देने का कोई लाभ नहीं है। कबाड़ को हटाकर, वापसी मुद्दा मूक है।

(ध्यान दें कि ओपी में अपवाद हैंडलिंग में एक बग शामिल है; इस कारण रिटर्न की आवश्यकता थी। ओपी ने मेरे द्वारा प्रस्तावित विधि को गलत नहीं माना होगा।)


5

क्या सिंटैक्स बैड प्रैक्टिस को संतुष्ट करने के लिए रिटर्न स्टेटमेंट है?

जैसा कि दूसरों ने उल्लेख किया है, आपके मामले में यह वास्तव में लागू नहीं होता है।

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

    switch (var)
   {
     case A:
       break;
     default:
       return;
       break;    // Unreachable code.  Coding standard violation?
   }

एक ने शिकायत की कि ब्रेक न होना एक मानक मानक उल्लंघन था। अन्य कि शिकायत की हो रही यह है क्योंकि यह पहुँच योग्य नहीं कोड था।

मैंने इस पर ध्यान दिया क्योंकि दो अलग-अलग प्रोग्रामर ने कोड को ब्रेक के साथ जोड़कर फिर से चेक किया, फिर हटा दिया गया, फिर जोड़ा गया, जिसके आधार पर उस दिन वे किस कोड एनालाइज़र पर निर्भर थे।

यदि आप इस स्थिति में समाप्त होते हैं, तो एक को चुनें और विसंगति पर टिप्पणी करें, जो आपके द्वारा दिखाया गया अच्छा रूप है। यह सबसे अच्छा और सबसे महत्वपूर्ण takeaway है।


5

यह 'सिंटैक्स को संतुष्ट करने के लिए' नहीं है। यह भाषा की एक शब्द्यात्मक आवश्यकता है कि हर कोड पथ एक वापसी या एक फेंक की ओर जाता है। यह कोड अनुपालन नहीं करता है। यदि अपवाद पकड़ा जाता है तो निम्नलिखित रिटर्न की आवश्यकता होती है।

इसके बारे में कोई 'बुरा अभ्यास' या सामान्य तौर पर संकलक को संतुष्ट करने के बारे में नहीं।

किसी भी मामले में, सिंटैक्स या सिमेंटिक, आपके पास इसके बारे में कोई विकल्प नहीं है।


2

मैं इसे फिर से लिखने के लिए लिखूंगा। स्यूडोकोड:

if a == null throw ...
// else not needed, if this is reached, a is not null
Object b
try {
  b = a.clone
}
catch ...

return b

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

2

यहाँ अभी तक किसी ने इसका उल्लेख नहीं किया है:

public static final Object ERROR_OBJECT = ...

//...

public Object getClone(Cloneable a) throws TotallyFooException {
Object ret;

if (a == null) 
    throw new TotallyFooException();

//no need for else here
try {
    ret = a.clone();
} catch (CloneNotSupportedException e) {
    e.printStackTrace();
    //something went wrong! ERROR_OBJECT could also be null
    ret = ERROR_OBJECT; 
}

return ret;

}

मैं उसी कारण से ब्लॉकों के returnअंदर नापसंद करता हूं try


2

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

यदि आप ऐसे विवरणों के बारे में जानकारी जानते हैं, जिसमें आप जानते हैं कि tryकथन कभी भी विफल नहीं हो सकता है, तो इसके होने का क्या मतलब है? tryयदि आप जानते हैं कि आप हमेशा सफल होने जा रहे हैं (हालांकि यह दुर्लभ है कि आप अपने कोडबेस के पूरे जीवनकाल के लिए बिल्कुल सुनिश्चित हो सकते हैं) से बचें ।

किसी भी मामले में, संकलक दुर्भाग्य से एक मन पाठक नहीं है। यह फ़ंक्शन और इसके इनपुट को देखता है, और इसके पास जो जानकारी है, उसे देखते हुए, इसे returnनीचे दिए गए विवरण की आवश्यकता है जैसा कि आपके पास है।

क्या सिंटैक्स को संतुष्ट करने और संकलन त्रुटियों से बचने के लिए अंत में अतिरिक्त रिटर्न स्टेटमेंट में डालना बुरा व्यवहार है (एक टिप्पणी के साथ यह समझा नहीं जा सकेगा), या क्या इस तरह से कुछ कोड करने का एक बेहतर तरीका है ताकि अतिरिक्त रिटर्न स्टेटमेंट अनावश्यक है

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

इस भाग के बारे में विशेष रूप से कहा:

try {
    return a.clone();
} catch (CloneNotSupportedException e) {
   e.printStackTrace();
}
...
//cant be reached, in for syntax
return null;

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

आप try/catchएक लेनदेन तंत्र के रूप में सोच सकते हैं । tryये परिवर्तन करते हुए, यदि वे विफल होते हैं और हम catchब्लॉक में शाखा करते हैं , तो catchरोलबैक और रिकवरी प्रक्रिया के हिस्से के रूप में ऐसा करें (जो भी ब्लॉक में है)।

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

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

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


0

आपका उदाहरण आपके प्रश्न को स्पष्ट करने के लिए आदर्श नहीं है जैसा कि अंतिम पैराग्राफ में कहा गया है:

क्या सिंटैक्स को संतुष्ट करने और संकलन त्रुटियों से बचने के लिए अंत में अतिरिक्त रिटर्न स्टेटमेंट में डालना बुरा व्यवहार है (एक टिप्पणी के साथ यह समझा नहीं जा सकेगा), या क्या इस तरह से कुछ कोड करने का एक बेहतर तरीका है ताकि अतिरिक्त रिटर्न स्टेटमेंट अनावश्यक है

एक बेहतर उदाहरण क्लोन के कार्यान्वयन का ही होगा:

 public class A implements Cloneable {
      public Object clone() {
           try {
               return super.clone() ;
           } catch (CloneNotSupportedException e) {
               throw new InternalError(e) ; // vm bug.
           }
      }
 }

यहां कैच क्लॉज को कभी दर्ज नहीं करना चाहिए । अभी भी वाक्यविन्यास को या तो कुछ फेंकने या एक मूल्य वापस करने की आवश्यकता है। चूंकि कुछ वापस करने का कोई मतलब नहीं है, InternalErrorएक गंभीर वीएम स्थिति को इंगित करने के लिए उपयोग किया जाता है।


5
सुपर क्लास एक फेंक CloneNotSupportedExceptionहै नहीं एक "वी एम बग" - यह पूरी तरह कानूनी है एक के लिए Cloneableयह फेंकने के लिए। यह आपके कोड और / या सुपरक्लास में एक बग का गठन कर सकता है , जिस स्थिति में इसे RuntimeExceptionया संभवतः AssertionError(लेकिन नहीं InternalError) में लपेटना उचित हो सकता है। या आप केवल अपवाद को डक कर सकते हैं - यदि आपका सुपरक्लास क्लोनिंग का समर्थन नहीं करता है, तो न तो आप करते हैं, इसलिए CloneNotSupportedExceptionशब्दार्थ उपयुक्त है।
इल्मरी करोनें

@IlmariKaronen आप ओरेकल को यह सलाह भेजना चाहते हैं ताकि वे JDK के भीतर सभी क्लोन तरीकों को सही कर सकें जो एक आंतरिक
Error को फेंकते हैं

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