سؤال

ما الفرق بين

try {
    fooBar();
} finally {
    barFoo();
}

و

try {
  fooBar();
} catch(Throwable throwable) {
    barFoo(throwable); // Does something with throwable, logs it, or handles it.
}

أنا أحب الإصدار الثاني بشكل أفضل لأنه يتيح لي الوصول إلى الرمي. هل هناك أي فرق منطقي أو اتفاقية مفضلة بين الاختلافين؟

أيضا ، هل هناك طريقة للوصول إلى الاستثناء من البند الأخير؟

هل كانت مفيدة؟

المحلول

هذان شيئان مختلفان:

  • يتم تنفيذ كتلة الصيد فقط إذا تم إلقاء استثناء في كتلة المحاولة.
  • يتم تنفيذ الكتلة الأخيرة دائمًا بعد كتلة المحاولة (-catch) ، إذا تم إلقاء استثناء أم لا.

في المثال الخاص بك ، لم تقم بتشكيل البنية الثالثة الممكنة:

try {
    // try to execute this statements...
}
catch( SpecificException e ) {
    // if a specific exception was thrown, handle it here
}
// ... more catches for specific exceptions can come here
catch( Exception e ) {
    // if a more general exception was thrown, handle it here
}
finally {
    // here you can clean things up afterwards
}

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

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

Throwable throwable = null;
try {
    // do some stuff
}
catch( Throwable e ) {
    throwable = e;
}
finally {
    if( throwable != null ) {
        // handle it
    }
}

نصائح أخرى

هذه ليست اختلافات ، فهي أشياء مختلفة بشكل أساسي. finally يتم تنفيذ دائماً, catch فقط عندما يحدث استثناء.

أخيرًا ، تختلف الكتل تمامًا:

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

لذا

try {
  //some code
}
catch (ExceptionA) {
  // Only gets executed if ExceptionA 
  // was thrown in try block
}
catch (ExceptionB) {
  // Only executed if ExceptionB was thrown in try 
  // and not handled by first catch block
}

يختلف عن

try {
  //some code
}
finally {
  // Gets executed whether or not 
  // an exception was thrown in try block
}

بشكل كبير.

إذا حددت مجموعة محاولة عليك تحديدها

  1. حظر واحد أخيرا ، أو
  2. واحدة أو أكثر من كتل الصيد ، أو
  3. واحد أو أكثر من كتل الصيد وأخيراً كتلة واحدة

لذا فإن الرمز التالي سيكون صالحًا أيضًا:

try {
  //some code
}
catch (ExceptionA) {
  // Only gets executed if 
  // ExceptionA was thrown in try block
}
catch (ExceptionB) {
  // Only executed if ExceptionB was thrown in 
  // try and not handled by first catch block
}
//even more catch blocks
finally {
  // Gets executed whether or not an 
  // exception was thrown in try block
}
try {
    statements;
} catch (exceptionType1 e1) {      // one or multiple
    statements;                 
} catch (exceptionType2 e2) {
    statements;
}    
...
} finally {                                 // one or none
    statements;
}
  1. يجب أن تتضمن جميع عبارات المحاولة إما بند اصطياد واحد أو شرط أخيرًا
  2. يمكن أن يكون له بنود الصيد المتعددة ولكن بند واحد فقط أخيرًا
  3. أثناء أي تنفيذ ، في حالة حدوث أي أخطاء ، يتم نقل التحكم إلى كتلة الصيد المناسبة وتنفيذ البيانات ويتم تنفيذ كتلة أخيرًا.

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

أخيرًا ، تختلف الكتل تمامًا:

داخل كتلة الصيد ، يمكنك الرد على الاستثناء الذي تم إلقاؤه. يتم تنفيذ هذه الكتلة فقط إذا كان هناك استثناء غير معقول والنوع يتطابق مع واحدة أو فئة فرعية من الكاتبة المحددة في معلمة Catch Block. أخيرًا ، سيتم تنفيذها دائمًا بعد محاولة التقاط الكتل سواء كان هناك استثناء تم رفعه أم لا.

يتم استخدام المحاولة لتشغيل طريقة قد ترمي استثناء

يتم استخدام الصيد "للقبض" على هذا الاستثناء

أخيرًا يستخدم لأي تنظيف مطلوب من هذا الاستثناء يتم اكتشافه أم لا

try{
    myObject.riskyMethod(); // run a method that may throw an exception
}
catch(Exception ex){
    myLogger.log(ex.Message); // "catch" stop that exception
}
finally{
    myObject = null; // clean up needed from that exception being caught
}

في أخيرًا ، يتم تنفيذ Block Risearch أخيرًا ويتم استخدامه بشكل أساسي "لأي اتصالات مفتوحة لإغلاق" وتدمير شيء يعمل دون داع.

أخيرًا يتم تنفيذ Block دائمًا. يتم تنفيذ كتلة الصيد فقط عندما يتم اللحاق استثناء يتطابق مع المعلمة الكتل.

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

بشكل عام عندما نستخدم أي موارد مثل التدفقات والاتصالات وما إلى ذلك .. يتعين علينا إغلاقها بشكل صريح باستخدام Block أخيرًا. في البرنامج الوارد أدناه ، نقرأ البيانات من ملف باستخدام FileReader ونغلقها باستخدام Block أخيرًا.

import java.io.File;
import java.io.FileReader;
import java.io.IOException;

public class ReadData_Demo {

   public static void main(String args[]){
      FileReader fr=null;       
      try{
         File file=new File("file.txt");
         fr = new FileReader(file);  char [] a = new char[50];
         fr.read(a); // reads the content to the array
         for(char c : a)
         System.out.print(c); //prints the characters one by one
      }catch(IOException e){
          e.printStackTrace();
       }
       finally{ 
          try{
              fr.close();
          }catch(IOException ex){       
               ex.printStackTrace();
           }
       }
    }

}

ربما بحث شباب آخرون مثلي عن شيء مثل هذا.

معلومات من هذه الصفحة TUTPOINT

ستعقد Try Block العبارات التي ستجذب استثناء. ستعقد كتلة الصيد المرجع الذي تم إلقاؤه من كتلة المحاولة ويتم إنشاء الرسائل المطلوبة من كتلة الصيد. أخيرًا ، يتم استخدام Block أيضًا لإغلاق الموارد المستخدمة مثل إغلاق IO ، وإغلاق الملف ، وإغلاق DB .. في Java -9 المحاولة المحسنة مع الموارد التي تم الإعلان عن الموارد خارج المحاولة .. في محاولة مع الموارد كتلة catch block إلزامي

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top