it-swarm.asia

هل يتم تنفيذ الحظر أخيرًا في Java؟

بالنظر إلى هذا الرمز ، هل يمكنني أن أكون متأكدًا تمامًا من أن كتلة finally تنفذ دائمًا ، بغض النظر عن something()؟

try {  
    something();  
    return success;  
}  
catch (Exception e) {   
    return failure;  
}  
finally {  
    System.out.println("I don't know if this will get printed out");
}
2159
jonny five

نعم ، سيتم استدعاء finally بعد تنفيذ الكتل البرمجية try أو catch.

الأوقات الوحيدة التي لن يتم استدعاء finally هي:

  1. إذا قمت باستدعاء System.exit()
  2. إذا تعطل JVM أولا
  3. إذا وصلت JVM إلى حلقة لا نهائية (أو عبارة أخرى غير قابلة للإنقطاع وغير نهائية) في كتلة try أو catch
  4. إذا كان نظام التشغيل ينهي عملية JVM بالقوة ؛ على سبيل المثال ، kill -9 <pid> على UNIX
  5. إذا مات النظام المضيف ؛ على سبيل المثال ، انقطاع التيار الكهربائي ، خطأ في الأجهزة ، ذعر نظام التشغيل ، إلخ
  6. إذا كان سيتم تنفيذ كتلة finally بواسطة خيط خفي وتنتهي كل مؤشرات الترابط غير الخفية قبل استدعاء finally
2415
jodonnell

رمز المثال:

public static void main(String[] args) {
    System.out.println(Test.test());
}

public static int test() {
    try {
        return 0;
    }
    finally {
        System.out.println("finally trumps return.");
    }
}

انتاج:

finally trumps return. 
0
502
Kevin

أيضًا ، على الرغم من أنها ممارسة سيئة ، إذا كان هناك بيان إرجاع داخل الكتلة النهائية ، فسيتم تجاوز أي عائد آخر من الكتلة العادية. وهذا يعني أن الكتلة التالية ستعود إلى خطأ:

try { return true; } finally { return false; }

نفس الشيء مع رمي استثناءات من الكتلة النهائية.

362
MooBob42

إليك الكلمات الرسمية من مواصفات لغة Java.

14.20.2. تنفيذ المحاولة - أخيرًا - تجربة المحاولة

يتم تنفيذ عبارة Atry مع كتلة finally عن طريق تنفيذ الكتلة try أولاً. ثم هناك خيار:

  • إذا تم تنفيذ كتلة try بشكل طبيعي ، [...]
  • إذا تم تنفيذ كتلة try فجأة بسبب throw بقيمة V ، [...]
  • إذا تم تنفيذ حظر try فجأة لأي سبب آخر R ، فسيتم تنفيذ حظر finally. ثم هناك خيار:
    • إذا اكتملت الكتلة أخيرًا بشكل طبيعي ، فسيتم إكمال عبارة try فجأة لسبب R.
    • إذا اكتملت كتلة finally فجأة لسبب S ، فسيتم إكمال عبارة try فجأة لسبب S (والسبب R هو المهملة).

مواصفات return تجعل هذا الأمر صريحًا:

JLS 14.17 بيان الإرجاع

ReturnStatement:
     return Expression(opt) ;

عبارة return مع عدم وجود Expressionمحاولات لنقل التحكم إلى invoker للطريقة أو المُنشئ الذي يحتوي عليها.

عبارة return مع Expressionمحاولات لنقل التحكم إلى invoker للطريقة التي تحتوي عليها ؛ تصبح قيمة Expression هي قيمة استدعاء الأسلوب.

تقول الأوصاف السابقة "محاولات لنقل التحكم" بدلاً من "نقل التحكم" فقط إذا كانت هناك أي عبارات try ضمن الأسلوب أو المُنشئ الذي تحتوي كتله try على عبارة return ، ثم سيتم تنفيذ أي جمل finally من هذه العبارات try ، بالترتيب ، من الأعمق إلى الأبعد ، قبل نقل السيطرة إلى المحتل للطريقة أو المُنشئ. يمكن أن يؤدي الإكمال المفاجئ لفقرة finally إلى تعطيل نقل عنصر التحكم الذي بدأته عبارة return.

249
polygenelubricants

بالإضافة إلى الردود الأخرى ، من المهم الإشارة إلى أن "أخيرًا" لها الحق في تجاوز أي قيمة استثناء/تم إرجاعها بواسطة كتلة try..catch. على سبيل المثال ، ترجع التعليمة البرمجية التالية 12:

public static int getMonthsInYear() {
    try {
        return 10;
    }
    finally {
        return 12;
    }
}

وبالمثل ، فإن الطريقة التالية لا تلقي استثناء:

public static int getMonthsInYear() {
    try {
        throw new RuntimeException();
    }
    finally {
        return 12;
    }
}

في حين أن الطريقة التالية لا رميها:

public static int getMonthsInYear() {
    try {
        return 12;          
    }
    finally {
        throw new RuntimeException();
    }
}
148
Eyal Schneider

حاولت المثال أعلاه مع تعديل طفيف

public static void main(final String[] args) {
    System.out.println(test());
}

public static int test() {
    int i = 0;
    try {
        i = 2;
        return i;
    } finally {
        i = 12;
        System.out.println("finally trumps return.");
    }
}

مخرجات الكود أعلاه:

يتفوق أخيرا العودة.
(2)

هذا لأنه عندما يتم تنفيذ return i;i له قيمة 2. بعد هذا يتم تنفيذ كتلة finally حيث يتم تعيين 12 إلى i ثم يتم System.out الخروج.

بعد تنفيذ الكتلة finally ، ترجع الكتلة try 2 ، بدلاً من إرجاع 12 ، لأنه لم يتم تنفيذ جملة الإرجاع هذه مرة أخرى.

إذا كنت ستقوم بتصحيح هذا الرمز في Eclipse ، فستشعر أنه بعد تنفيذ System.out من finally ، يتم تنفيذ جملة return of try مرة أخرى. ولكن هذا ليس هو الحال. تقوم ببساطة بإرجاع القيمة 2.

109
vibhash

فيما يلي شرح إجابة كيفن . من المهم معرفة أن التعبير المراد إرجاعه يتم تقييمه قبل finally ، حتى إذا تم إرجاعه بعد.

public static void main(String[] args) {
    System.out.println(Test.test());
}

public static int printX() {
    System.out.println("X");
    return 0;
}

public static int test() {
    try {
        return printX();
    }
    finally {
        System.out.println("finally trumps return... sort of");
    }
}

انتاج:

X
finally trumps return... sort of
0
95
WoodenKitty

هذه هي الفكرة الكاملة للكتلة أخيرًا. يتيح لك ذلك التأكد من قيامك بإجراء عمليات تنظيف قد يتم تخطيها لأنك تعود ، من بين أشياء أخرى ، بالطبع.

أخيرًا يتم استدعاء بغض النظر عما يحدث في كتلة المحاولة ( ما لم يمكنك استدعاء System.exit(int) أو تشغيل Java Virtual Machine لسبب آخر).

52
Chris Cooper

طريقة منطقية للتفكير في هذا هي:

  1. يجب تنفيذ التعليمات البرمجية الموضوعة في كتلة أخيرة مهما حدث داخل كتلة المحاولة
  2. لذا ، إذا حاولت التعليمة البرمجية الموجودة في كتلة المحاولة إرجاع قيمة أو رمي استثناء ، فسيتم وضع العنصر "على الرف" حتى يمكن تنفيذ الحظر النهائي
  3. نظرًا لأن الكود الموجود في الكتلة الأخيرة له (بحكم التعريف) أولوية عالية ، يمكنه إرجاع أو إلقاء كل ما يحلو له. في هذه الحالة يتم تجاهل أي شيء متبقٍ "على الرف".
  4. الاستثناء الوحيد لذلك هو إذا كان VM متوقفًا تمامًا أثناء حظر المحاولة ، على سبيل المثال بواسطة 'System.exit'
38
Garth Gilmour

أخيرًا يتم تنفيذها دائمًا ما لم يكن هناك إنهاء غير طبيعي للبرنامج (مثل استدعاء System.exit (0) ..). لذلك ، سوف تحصل المطبوعة النظام الخاص بك

18
shyam

أيضا العودة في النهاية سوف يلقي أي استثناء. http://jamesjava.blogspot.com/2006/03/dont-return-in-finally-clause.html

18
James A. N. Stauffer

يتم تنفيذ الحظر الأخير دائمًا ما لم يكن هناك إنهاء غير طبيعي للبرنامج ، إما بسبب تعطل JVM أو من مكالمة إلى System.exit(0).

علاوةً على ذلك ، فإن أي قيمة يتم إرجاعها من داخل الكتلة الأخيرة ستتجاوز القيمة التي تم إرجاعها قبل تنفيذ الكتلة الأخيرة ، لذا كن حذرًا من التحقق من جميع نقاط الخروج عند استخدام المحاولة أخيرًا.

17
user9189

لا ، ليست دائمًا حالة استثناء واحدة هي // System.exit (0)؛ قبل أن يمنع أخيرا كتلة ليتم تنفيذها.

  class A {
    public static void main(String args[]){
        DataInputStream cin = new DataInputStream(System.in);
        try{
            int i=Integer.parseInt(cin.readLine());
        }catch(ArithmeticException e){
        }catch(Exception e){
           System.exit(0);//Program terminates before executing finally block
        }finally{
            System.out.println("Won't be executed");
            System.out.println("No error");
        }
    }
}
17
Rajendra Jadi

أخيرًا ما يتم تشغيله دائمًا وهذا هو بيت القصيد ، لمجرد أنه يظهر في الكود بعد الإرجاع لا يعني أنه كيف تم تطبيقه. يتحمل وقت تشغيل Java مسؤولية تشغيل هذا الرمز عند الخروج من الكتلة try.

على سبيل المثال إذا كان لديك ما يلي:

int foo() { 
    try {
        return 42;
    }
    finally {
        System.out.println("done");
    }
}

وقت التشغيل سيولد شيئًا كهذا:

int foo() {
    int ret = 42;
    System.out.println("done");
    return 42;
}

إذا تم طرح استثناء غير معلوم ، فسيتم تشغيل الكتلة finally وسيستمر نشر الاستثناء.

12
Motti

هذا لأنك قمت بتعيين قيمة i كـ 12 ، لكنك لم تُرجع قيمة i إلى الوظيفة. الرمز الصحيح هو كما يلي:

public static int test() {
    int i = 0;
    try {
        return i;
    } finally {
        i = 12;
        System.out.println("finally trumps return.");
        return i;
    }
}
10
Wasim

لأنه سيتم دائمًا استدعاء كتلة أخيرًا إلا إذا قمت بالاتصال System.exit() (أو تعطل السلسلة).

9
Jay Riggs

الجواب بسيطنعم.

إدخال:

try{
    int divideByZeroException = 5 / 0;
} catch (Exception e){
    System.out.println("catch");
    return;    // also tried with break; in switch-case, got same output
} finally {
    System.out.println("finally");
}

انتاج:

catch
finally
9
Meet

نعم سوف تحصل على الاتصال. هذا هو بيت القصيد من وجود كلمة رئيسية في النهاية. إذا كان القفز خارج كتلة try/catch يمكن فقط تخطي الكتلة الأخيرة ، فسيكون ذلك هو وضع System.out.println خارج try/catch.

8
Mendelt

نعم ، وأخيرا يتم تنفيذ كتلة دائما. يستخدم معظم المطورين هذه الكتلة لإغلاق اتصال قاعدة البيانات ، وكائن مجموعة النتائج ، وكائن العبارة ، ويستخدم أيضًا في وضع الإسبات في Java لاستعادة المعاملة.

8
Gautam Viradiya

باختصار ، في وثائق Java الرسمية (انقر هنا ) ، تتم كتابة ذلك -

في حالة خروج JVM أثناء تنفيذ رمز try أو catch ، فقد لا يتم تنفيذ الحظر النهائي. وبالمثل ، في حالة مقاطعة مؤشر الترابط الذي ينفذ رمز try أو catch أو قتله ، فقد لا يتم تنفيذ الحظر النهائي على الرغم من استمرار التطبيق ككل.

8
bikz05

نعم. الحالة الوحيدة لن يتم خروج JVM أو تعطلها

7
abhig

نعم. بغض النظر عن ما يحدث في كتلة المحاولة أو الالتقاط ما لم يكن System.exit () يُطلق عليه أو JVM معطلاً. إذا كان هناك أي بيان إرجاع في الكتلة (المجموعات) ، سيتم تنفيذ أخيرًا قبل بيان الإرجاع.

7
Karthikeyan

النظر في البرنامج التالي:

public class SomeTest {

    private static StringBuilder sb = new StringBuilder();

    public static void main(String args[]) {

        System.out.println(someString());
        System.out.println("---AGAIN---");
        System.out.println(someString());
        System.out.println("---PRINT THE RESULT---");
        System.out.println(sb.toString());
    }

    private static String someString() {

        try {
            sb.append("-abc-");
            return sb.toString();

        } finally {
            sb.append("xyz");
        }
    }
}

اعتبارًا من الإصدار 1.8.162 من Java ، توفر مجموعة التعليمات البرمجية أعلاه الإخراج التالي:

-abc-
---AGAIN---
-abc-xyz-abc-
---PRINT THE RESULT---
-abc-xyz-abc-xyz

هذا يعني أن استخدام finally لتحرير الكائنات يعد ممارسة جيدة مثل التعليمات البرمجية التالية:

private static String someString() {

    StringBuilder sb = new StringBuilder();

    try {
        sb.append("abc");
        return sb.toString();

    } finally {
        sb = null; // Just an example, but you can close streams or DB connections this way.
    }
}
7
Samim

حاولت هذا ، فمن الخيوط واحد.

class Test {
    public static void main(String args[]) throws Exception {
       Object obj = new Object();
       try {
            synchronized (obj) {
            obj.wait();
            System.out.println("after wait()");
           }
       } catch (Exception e) {
       } finally {
           System.out.println("finally");
       }
   }
}

سيكون الخيط الرئيسي في حالة الانتظار إلى الأبد ، وبالتالي لن يتم استدعاء

لذلك لن تتم طباعة إخراج وحدة التحكم السلسلة: after wait() أو finally

متفق معStephen C ، المثال أعلاه هو واحد من الحالة الثالثة المذكورة هنا :

إضافة المزيد من هذه الاحتمالات حلقة لانهائية في التعليمات البرمجية التالية:

// import Java.util.concurrent.Semaphore;
class Test {
    public static void main(String[] args) {
        try {
            // Thread.sleep(Long.MAX_VALUE);
            // Thread.currentThread().join();
            // new Semaphore(0).acquire();
            // while (true){}
            System.out.println("after sleep join semaphore exit infinite while loop");
        } catch (Exception e) {
        } finally {
            System.out.println("finally");
        }
    }
}

الحالة 2: إذا تعطل JVM أولاً

import Sun.misc.Unsafe;
import Java.lang.reflect.Field;
class Test {
    public static void main(String args[]) {
        try {
            unsafeMethod();
//            Runtime.getRuntime().halt(123);
            System.out.println("After Jvm Crash!");
        } catch (Exception e) {
        } finally {
            System.out.println("finally");
        }
    }

    private static void unsafeMethod() throws NoSuchFieldException, IllegalAccessException {
        Field f = Unsafe.class.getDeclaredField("theUnsafe");
        f.setAccessible(true);
        Unsafe unsafe = (Unsafe) f.get(null);
        unsafe.putAddress(0, 0);
    }
}

المرجع: كيف تعطل JVM؟

الحالة 6: إذا تم تنفيذ الحظر نهائيًا بواسطة مؤشر ترابط daemon وسيتم إنهاء كافة مؤشرات الترابط غير daemon قبل يتم استدعاء وأخيراً.

class Test {
    public static void main(String args[]) {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                try {
                    printThreads("Daemon Thread printing");
                    // just to ensure this thread will live longer than main thread
                    Thread.sleep(10000);
                } catch (Exception e) {
                } finally {
                    System.out.println("finally");
                }
            }
        };
        Thread daemonThread = new Thread(runnable);
        daemonThread.setDaemon(Boolean.TRUE);
        daemonThread.setName("My Daemon Thread");
        daemonThread.start();
        printThreads("main Thread Printing");
    }

    private static synchronized void printThreads(String str) {
        System.out.println(str);
        int threadCount = 0;
        Set<Thread> threadSet = Thread.getAllStackTraces().keySet();
        for (Thread t : threadSet) {
            if (t.getThreadGroup() == Thread.currentThread().getThreadGroup()) {
                System.out.println("Thread :" + t + ":" + "state:" + t.getState());
                ++threadCount;
            }
        }
        System.out.println("Thread count started by Main thread:" + threadCount);
        System.out.println("-------------------------------------------------");
    }
}

الإخراج: هذا لا يطبع "أخيرًا" الذي يعني "أخيرًا كتلة" في "الخيط الخفي" لم يتم تنفيذ

main Thread Printing  
Thread :Thread[My Daemon Thread,5,main]:state:BLOCKED  
Thread :Thread[main,5,main]:state:RUNNABLE  
Thread :Thread[Monitor Ctrl-Break,5,main]:state:RUNNABLE   
Thread count started by Main thread:3  
-------------------------------------------------  
Daemon Thread printing  
Thread :Thread[My Daemon Thread,5,main]:state:RUNNABLE  
Thread :Thread[Monitor Ctrl-Break,5,main]:state:RUNNABLE  
Thread count started by Main thread:2  
-------------------------------------------------  

Process finished with exit code 0
6
dkb

نعم ، لأن لا يوجد بيان تحكم يمكن أن يمنع تنفيذ finally.

فيما يلي مثال مرجعي ، حيث سيتم تنفيذ جميع مقاطع التعليمات البرمجية:

| x | Current result | Code 
|---|----------------|------ - - -
|   |                |     
|   |                | public static int finallyTest() {
| 3 |                |     int x = 3;
|   |                |     try {
|   |                |        try {
| 4 |                |             x++;
| 4 | return 4       |             return x;
|   |                |         } finally {
| 3 |                |             x--;
| 3 | throw          |             throw new RuntimeException("Ahh!");
|   |                |         }
|   |                |     } catch (RuntimeException e) {
| 4 | return 4       |         return ++x;
|   |                |     } finally {
| 3 |                |         x--;
|   |                |     }
|   |                | }
|   |                |
|---|----------------|------ - - -
|   | Result: 4      |

في البديل أدناه ، سيتم تخطي return x;. النتيجة لا تزال 4:

public static int finallyTest() {
    int x = 3;
    try {
        try {
            x++;
            if (true) throw new RuntimeException("Ahh!");
            return x; // skipped
        } finally {
            x--;
        }
    } catch (RuntimeException e) {
        return ++x;
    } finally {
        x--;
    }
}

المراجع ، بالطبع ، تتبع حالتها. يعرض هذا المثال مرجعًا مع value = 4:

static class IntRef { public int value; }
public static IntRef finallyTest() {
    IntRef x = new IntRef();
    x.value = 3;
    try {
        return x;
    } finally {
        x.value++; // will be tracked even after return
    }
}
6
Dávid Horváth

finally سيتم تنفيذه وهذا أمر مؤكد.

finally لن يتم تنفيذه في الحالات التالية:

حالة 1 :

عندما تقوم بتنفيذ System.exit().

الحالة 2:

عندما تعطل JVM/الموضوع الخاص بك.

الحالة 3:

عندما يتم إيقاف التنفيذ الخاص بك بين يدويا.

6
Utkash Bhatt

try- catch- finally هي الكلمات الأساسية لاستخدام حالة معالجة الاستثناء.
كما شرح طبيعي

try {
     //code statements
     //exception thrown here
     //lines not reached if exception thrown
} catch (Exception e) {
    //lines reached only when exception is thrown
} finally {
    // always executed when the try block is exited
    //independent of an exception thrown or not
}

وأخيرا منع كتلة تنفيذ ...

  • عندما اتصلت System.exit(0);
  • إذا خروج JVM.
  • أخطاء في JVM
6
Poorna Senani Gamage

إذا لم تقم بمعالجة الاستثناء ، قبل إنهاء البرنامج ، ينفذ JVM الحظر أخيرًا. لن يتم تنفيذه إلا إذا فشل التنفيذ العادي للبرنامج في إنهاء البرنامج بسبب هذه الأسباب التالية ..

  1. عن طريق التسبب في خطأ فادح يؤدي إلى إحباط العملية.

  2. إنهاء البرنامج بسبب تلف الذاكرة.

  3. عن طريق استدعاء System.exit ()

  4. إذا ذهب البرنامج إلى حلقة اللانهاية.

6
Vikas Suryawanshi

هذا حقيقي في أي لغة ... أخيرًا ستنفذ دائمًا قبل بيان الإرجاع ، بغض النظر عن مكان الإرجاع في نص الأسلوب. إذا لم يكن الأمر كذلك ، فلن يكون للكتلة الأخيرة معنى كبير.

6
Scott Dorman

إضافة إلى @ vibhash 's الجواب كما لا توجد إجابة أخرى تشرح ما يحدث في حالة كائن قابل للتغيير مثل الكائن أدناه.

public static void main(String[] args) {
    System.out.println(test().toString());
}

public static StringBuffer test() {
    StringBuffer s = new StringBuffer();
    try {
        s.append("sb");
        return s;
    } finally {
        s.append("updated ");
    }
}

سوف الإخراج

sbupdated 
6
Pradeep Kumaresan

نعم ، هو مكتوب هنا

في حالة خروج JVM أثناء تنفيذ رمز try أو catch ، فقد لا يتم تنفيذ الحظر النهائي. وبالمثل ، في حالة مقاطعة مؤشر الترابط الذي ينفذ رمز try أو catch أو قتله ، فقد لا يتم تنفيذ الحظر النهائي على الرغم من استمرار التطبيق ككل.

5
Danail Tsvetanov

بالإضافة إلى النقطة المتعلقة بالإرجاع في النهاية استبدال العائد في كتلة المحاولة ، ينطبق الأمر نفسه على استثناء. أخيرًا ستحل الكتلة التي تطرح استثناءًا عن إرجاع أو استثناء يتم طرحه من داخل كتلة المحاولة.

5
Alex Miller

ليس دائما

توضح مواصفات Java Language كيف تعمل كتل try-catch-وأخيرا و try-catch في 14.20.2
في أي مكان ، تحدد أن الكتلة النهائية يتم تنفيذها دائمًا. ولكن بالنسبة لجميع الحالات التي تكتمل فيها كتل try-catch-وأخيرا و try-final ، فإنها تحدد أنه قبل التنفيذ يجب أن يتم تنفيذها.

try {
  CODE inside the try block
}
finally {
  FIN code inside finally block
}
NEXT code executed after the try-finally block (may be in a different method).

JLS لا تضمن أن يتم تنفيذ {FIN بعد CODE. تضمن JLS أنه إذا تم تنفيذ {CODE و NEXT فسيتم دائمًا تنفيذ {FIN بعد CODE وقبل (next _.

لماذا لا تضمن JLS أن يتم تنفيذ الكتلة النهائية دائمًا بعد كتلة المحاولة؟ لأنه مستحيل. من غير المحتمل ولكن من الممكن أن يتم إحباط JVM (القتل أو التعطل أو انقطاع التيار الكهربائي) مباشرةً بعد إكمال كتلة المحاولة ولكن قبل تنفيذ الحظر النهائي. لا يوجد شيء يمكن لـ JLS فعله لتجنب ذلك.

وبالتالي ، فإن أي برنامج يعتمد في سلوكه الصحيح على أخيرًا يتم تنفيذ الكتل دائمًا بعد أن يتم تجريب كتل المحاولات.

العوائد في كتلة المحاولة غير مرتبطة بهذه المشكلة. إذا وصل التنفيذ إلى التعليمات البرمجية بعد try-catch-وأخيراً ، فمن المؤكد أنه سيتم تنفيذ الحظر الأخير من قبل ، مع أو بدون إرجاع داخل كتلة try.

5
Jose Antonio Dura Olmos

أخيرًا لن يتم استدعاء الكتلة بعد العودة في عدة سيناريوهات فريدة: إذا تم استدعاء System.exit () أولاً ، أو في حالة تعطل JVM.

اسمحوا لي أن أحاول الإجابة على سؤالك بأسهل طريقة ممكنة.

القاعدة 1 : يتم تشغيل الكتلة أخيرًا دائمًا (على الرغم من وجود استثناءات لها. ولكن دعونا نتمسك بهذا لبعض الوقت.)

القاعدة 2 : عبارات في تشغيل الكتلة أخيرًا عندما يترك عنصر التحكم تجربة أو كتلة catch. يمكن أن يحدث نقل التحكم كنتيجة للتنفيذ العادي أو لتنفيذ فترة راحة أو متابعة أو الانتقال إلى goto أو بيان الإرجاع ، أو لامتداد استثناء.

في حالة بيان الإرجاع على وجه التحديد (منذ التسمية التوضيحية) ، يجب أن يترك عنصر التحكم طريقة الاستدعاء ، وبالتالي يستدعي الكتلة النهائية لهيكل المحاولة المطابق. يتم تنفيذ بيان الإرجاع بعد الحظر الأخير.

في حالة وجود بيان عائد في المجموعة الأخيرة أيضًا ، فسوف يتجاوز بالتأكيد العبارة المعلقة في كتلة المحاولة ، نظرًا لأنه يزيل مكدس الاتصال.

يمكنك الرجوع إلى شرح أفضل هنا: http://msdn.Microsoft.com/en-us/ .... المفهوم هو نفسه في الغالب بجميع اللغات عالية المستوى.

5
Sandip Solanki
  1. وأخيرا كتلة دائما الحصول على تنفيذها. ما لم وحتى System.exit () عبارة موجودة هناك (العبارة الأولى في كتلة أخيرًا).
  2. إذا كان system.exit () هو أول عبارة ، فلن يتم تنفيذ الحظر نهائيًا ويخرج عنصر التحكم من الكتلة الأخيرة. كلما تم الحصول على جملة System.exit () أخيرًا ، حتى يتم تنفيذ العبارة أخيرًا ، وعندما يظهر System.exit () ، تخرج قوة التحكم تمامًا من الكتلة الأخيرة.
5
Avinash Pande

نفسه مع الكود التالي:

static int f() {
    while (true) {
        try {
            return 1;
        } finally {
            break;
        }
    }
    return 2;
}

و سوف يعود 2!

4
dibo

لأنه يتم دائمًا استدعاء النهائي في أي حالة لديك. ليس لديك استثناء ، ما زال يطلق عليه ، استثناء catch ، لا يزال يسمى

4
vodkhang

نعم ، سيتم الاتصال دائمًا ولكن في حالة واحدة لا يتم الاتصال بها عند استخدام System.exit ()

try{
//risky code
}catch(Exception e){
//exception handling code
}
finally(){
//It always execute but before this block if there is any statement like System.exit(0); then this block not execute.
}
4
Akash Manngroliya

أخيرًا ، قم دائمًا بتنفيذ ما إذا كان مقبض الاستثناء أم لا. إذا حدث أي استثناء قبل محاولة المحاولة ، فلن يتم تنفيذ الحظر نهائيًا.

4
Rohit Chugh

إذا تم طرح استثناء ، فسيتم تشغيله أخيرًا. إذا لم يتم طرح استثناء ، فسيتم تشغيله أخيرًا. إذا تم اكتشاف الاستثناء ، فسيتم تشغيله أخيرًا. إذا لم يتم اكتشاف الاستثناء ، فسيتم تشغيله أخيرًا.

المرة الوحيدة التي لا يعمل فيها هو عندما يخرج JVM.

4
Bhushan

ضع في اعتبارك هذا في سياق التنفيذ العادي (أي دون طرح أي استثناء): إذا لم تكن الطريقة "باطلة" ، فعادة ما تُرجع شيئًا بشكل صريح دائمًا ، ومع ذلك ، يتم دائمًا تنفيذ

4
Gala101

جرب هذا الكود ، سوف تفهم الكود في النهاية يتم تنفيذ الكتلة بعد بيان الإرجاع .

public class TestTryCatchFinally {
    static int x = 0;

    public static void main(String[] args){
        System.out.println(f1() );
        System.out.println(f2() );
    }

    public static int f1(){
        try{
            x = 1;
            return x;
        }finally{
            x = 2;
        }
    }

    public static int f2(){
        return x;
    }
}
4
eric2323223

كنت في حيرة من أمري مع جميع الإجابات المقدمة في المنتديات المختلفة ، وقررت أخيرًا أن أشاهدها وشاهدها. و ouput هو:

في النهاية سيتم تنفيذها حتى لو كان هناك عودة في محاولة وقبض كتلة.

try {  
  System.out.println("try"); 
  return;
  //int  i =5/0;
  //System.exit(0 ) ;
} catch (Exception e) {   
  System.out.println("catch");
  return;
  //int  i =5/0;
  //System.exit(0 ) ;
} finally {  
   System.out.println("Print me FINALLY");
}

انتاج

محاولة

طباعة لي في النهاية

  1. إذا تم استبدال العائد بـ System.exit(0) في محاولة وقبض كتلة في التعليمات البرمجية أعلاه ويحدث استثناء قبل ذلك ، لأي سبب من الأسباب.
4
milton

أخيرًا ، يمكن أيضًا الخروج قبل الأوان إذا تم طرح استثناء داخل كتلة أخيرة متداخلة. سوف يحذرك المحول البرمجي إلى أن الكتلة أخيرًا لا تكتمل بشكل طبيعي أو تعطي خطأ بأن لديك رمز يتعذر الوصول إليه. سيتم عرض خطأ التعليمات البرمجية التي يتعذر الوصول إليها فقط في حالة عدم وجود رمي خلف عبارة شرطية أو داخل حلقة.

try{
}finally{
   try{
   }finally{
      //if(someCondition) --> no error because of unreachable code
      throw new RunTimeException();
   }
   int a = 5;//unreachable code
}
3
HopefullyHelpful

وأخيرا يسمى دائما في النهاية

عند المحاولة ، يتم تنفيذ بعض التعليمات البرمجية ، إذا حدث شيء ما في المحاولة ، فحينئذٍ سيتم التقاط هذا الاستثناء ويمكنك طباعة بعض mssg أو رمي خطأ ، ثم يتم تنفيذ الحظر أخيرًا.

عادةً ما يتم استخدامه أخيرًا عند إجراء عمليات التنظيف ، على سبيل المثال ، إذا كنت تستخدم ماسح ضوئي في Java ، فيجب عليك إغلاق الماسح الضوئي لأنه يؤدي إلى مشاكل أخرى مثل عدم القدرة على فتح بعض الملفات

2
Rubin Luitel

أخيرًا ، يتم تنفيذ حظر دائمًا حتى إذا وضعت عبارة إرجاع في كتلة المحاولة. سيتم تنفيذ الكتلة أخيرًا قبل بيان الإرجاع.

2
Sabrina