2011-01-26 27 views
6

जावा में अंतिम ब्लॉक है जो ब्लॉक ब्लॉक के बाद कुछ बयानों को निष्पादित करने की अनुमति देता है (अपवाद उठाए जाने पर भी निष्पादित किया जाता है)। उदाहरण:जावा को अंतिम रूप देने के लिए सर्वश्रेष्ठ अभ्यास (2005 या 2012) जावा के बराबर ब्लॉक

try { 
    ... 
} catch (Exception e) { 
    ... 
} finally { 
    ... // any code here 
} 

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

  1. आप एडीए 2005 में इस तरह के अंतिम ब्लॉक को कैसे कार्यान्वित करेंगे (कोड को पठनीय रखने के दौरान)?
  2. क्या एडीए 2012 में किसी भी अंतिमकरण कोड को आसानी से निष्पादित करने की अनुमति देने के लिए योजनाएं हैं?
+1

नियंत्रित ऑब्जेक्ट की 'अंतिमकरण' विधि एक विनाशक की तरह अधिक है। अंतिम रूप से ब्लॉक के साथ इसका कोई समानता नहीं है। –

+0

हां, लेकिन आप इस व्यवहार को किसी भी तरह "अनुकरण" कर सकते हैं लेकिन यह भारी है। – ciceron

+1

यह एक 'अंततः' ब्लॉक है, जिसका 'अंतिमकरण' विधियों को कॉल करने के साथ कुछ लेना देना नहीं है। – Gabe

उत्तर

2

मुझे विश्वास है कि यह कोड आप जो भी पूछेंगे; यह वर्तमान raise या return के साथ सफलतापूर्वक 42 प्रिंट करता है। यह टी.ई.डी. के सुझाव का कार्यान्वयन है।

मैक ओएस एक्स, डार्विन 10.6.0 पर जीसीसी 4.5.0 के साथ परीक्षण किया गया।

with Ada.Finalization; 
package Finally is 

    -- Calls Callee on deletion. 
    type Caller (Callee : not null access procedure) 
     is new Ada.Finalization.Limited_Controlled with private; 

private 

    type Caller (Callee : not null access procedure) 
     is new Ada.Finalization.Limited_Controlled with null record; 

    procedure Finalize (Object : in out Caller); 

end Finally; 


package body Finally is 

    procedure Finalize (Object : in out Caller) 
    is 
    begin 
     Object.Callee.all; 
    end Finalize; 

end Finally; 


with Ada.Text_IO; use Ada.Text_IO; 
with Finally; 
procedure Finally_Demo is 
begin 

    declare 

     X : Integer := 21; 

     -- The cleanup procedure, to be executed when this block is left 
     procedure F 
     is 
     begin 
     Put_Line ("X is " & Integer'Image (X)); 
     end F; 

     -- The controlled object, whose deletion will execute F 
     F_Caller : Finally.Caller (F'Access); 

    begin 

     X := 42; 

     raise Constraint_Error; 

    end; 

end Finally_Demo; 
+0

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

+0

'अंतिमकरण' के दौरान अपवाद बढ़ाने के लिए यह 'Program_Error' है, शायद इसे संभालने के लिए कुछ होना चाहिए। दूसरी ओर, यह वास्तव में एक प्रोग्राम त्रुटि है, शायद दुर्घटनाग्रस्त और जला करने के लिए बेहतर! मुझे आश्चर्य है कि जावा 'अंत में' ब्लॉक का अर्थशास्त्र क्या है? –

+0

जावा आपको अंततः ब्लॉक में अपवाद बढ़ाने की अनुमति देता है। वर्तमान अपवाद (यदि कोई है) खो गया है। कई मामलों में, आप इन अपवादों को अनदेखा करने के लिए एक और प्रयास/पकड़ ब्लॉक के साथ समाप्त होते हैं। – ciceron

2

जैसा कि एड्रियान टिप्पणी में उल्लेख करता है, Finalize एक विनाशक के समान है।

का अनुमान करने के लिए एक अपवाद/अंतिम दृश्य आप इन पंक्तियों के साथ कुछ (चेतावनी क्या कर सकते हैं कुछ पाने के लिए, संकलित नहीं, बस एक साथ किसी भी त्रुटि के बाहर काम --we'll :-) भी देखें एडीए की Exceptions section टाइप किया आर एम।

with Ada.Exceptions; use Ada.Exceptions; 

procedure Do_Something is 

    -- Variables and what-not... 

    -- In case you have an exception and want to reraise it after you've done 
    -- the 'final' processing. 
    Exception_Caught : Exception_Occurrence := Null_Occurrence; 

begin 
    -- You can have some statements, like initializations, here that will not 
    -- raise exceptions. But you don't have to, it can all just go in the 
    -- following block. However you want to do it... 

    declare 
     -- If you need to declare some entities local to a block, put those here. 
     -- If not, just omit this declare section. Be aware, though, that if 
     -- you initialize something in here and it raises an exception, the 
     -- block's exception handler will not catch it. Such an exception will 
     -- propagate out of the whole procedure (unless it has an outermost 
     -- exception handler) because you're _not_ in the block's scope yet. 

    begin 
     -- Main processing that might raise an exception 

     ... 

    exception 
     when E : others => 
     -- Handle any exception that's raised. If there are specific 
     -- exceptions that can be raised, they should be explicitly 
     -- handled prior to this catch-all 'others' one. 

     -- Save the exception occurrence, i.e. make a copy of it that can 
     -- be reraised in the 'Final' section if needed. (If you want to 
     -- reraise for a specific exception, do this in those handlers as 
     -- well. 
     Save_Occurrence(Exception_Caught, E); 

    end; 

    -- Final processing. Everything from here to the end of the procedure is 
    -- executed regardless of whether an exception was raised in the above 
    -- block. By it including an others handler, it ensured that no exception 
    -- will propagate out of this procedure without hitting this 'Final' code. 

    -- If an exception was raised and needs to be propagated: 
    if Exception_Caught /= Null_Occurrence then 
     Reraise_Exception(Exception_Caught); 
    end if; 

end Do_Something; 
+0

कोड का उपरोक्त टुकड़ा एडा में अपवादों को संभालने का मानक तरीका है, हालांकि यह 'अंतिमकरण' ब्लॉक को काफी अनुकरण नहीं करता है: आप अपवाद ब्लॉक में अपवाद नहीं बढ़ा सकते हैं या 'अंतिमकरण' कोड निष्पादित नहीं होगा। और यदि आप 'अंतिमकरण' कोड को निष्पादित करने का ख्याल रखते हैं, तो आप उस अपवाद को खो देते हैं जो फेंक दिया गया था, जो बाहरी स्तर पर उस अपवाद को पकड़ने से रोकता है ... –

+0

अच्छा बिंदु। उस अपवाद को बनाए रखने के तरीके को दिखाने के लिए कोड अपडेट किया गया और बाद में वांछित होने पर इसे पुन: उत्पन्न करें। –

+1

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

1

मार्क सी के पास सीधे-रेखा प्रक्रियात्मक कोड में अनुकरण करने का प्रयास करने का सही दृष्टिकोण है।

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

इसलिए मुझे नहीं लगता कि यह बहुत अधिक खिंचाव है कि एडा में उस कार्यक्षमता को प्राप्त करने का उचित तरीका उचित वस्तु बनाना होगा, और अपने ऑब्जेक्ट को Ada.Finalization.Controlled का बच्चा बनाना होगा।

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

2

मान लिया जाये कि आप ada.finalization और जावा में एक को अंतिम रूप देने ब्लॉक के बीच अंतर को समझ लिया है, मैं निम्नलिखित, जो एक ही प्रभाव होना चाहिए करने के लिए कुछ इसी तरह करना होगा।

procedure x is 
begin 

    -- some code 
    begin 
    -- more code (your try) 
    exception 
    -- handle exception if necessary (caught exception) 
    end; 
    -- yet more code which is executed regardless of any exception handling. 

end x; 
+0

बस मार्क सीएस जवाब देखा - मेरा के समान :) – NWS

+0

यूप। वही टिप्पणी यहां भी लागू होती है - एक वापसी कथन आपको "अंतिम" कोड चलाने के बिना सीधे 'x' से बाहर कूदता है, लेकिन शायद यह सबसे अच्छा है जिसे नियंत्रित प्रकारों का उपयोग किए बिना किया जा सकता है। –

+0

अधिक महत्वपूर्ण, यदि कोई अपवाद उठाया गया है, तो इसे प्रचारित नहीं किया जाएगा। मार्क का समाधान उस पर संभालता है। साइमन का प्रस्ताव शायद सबसे अच्छा है क्योंकि यह रिटर्न स्टेटमेंट इश्यू का भी ख्याल रखता है (लेकिन यह काफी भारी है)। – ciceron

1

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

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

procedure Finalized is 
begin 
    declare 
     task Worker is end Worker; 
     task body Worker is begin 
      --// Working code in here. Can throw exceptions or whatever. 
      --// Does not matter. 
     end Worker; 
    begin 
    end; 

    --// If we get here, we know the task finished somehow (for good or ill) 
    --// so the finalization code goes here. 

end Finalized; 

ऐसा लगता है कि संरक्षित वस्तुओं के साथ ऐसा कुछ करने का तरीका भी हो सकता है। मैं इसे दूसरों को समझने के लिए छोड़ दूंगा।