জাভা বাদে ধরা পড়েনি?


170

চেষ্টা করার চেষ্টাগুলি নিয়ে আমার একটি ছোট তাত্ত্বিক সমস্যা রয়েছে।

আমি জাভা সম্পর্কে গতকাল একটি ব্যবহারিক পরীক্ষা দিয়েছি এবং আমি নিম্নলিখিত উদাহরণটি বুঝতে পারি না:

try {
    try {
        System.out.print("A");
        throw new Exception("1");
    } catch (Exception e) {
        System.out.print("B");
        throw new Exception("2");
    } finally {
        System.out.print("C");
        throw new Exception("3");
    }
} catch (Exception e) {
    System.out.print(e.getMessage());
}

প্রশ্নটি ছিল "আউটপুটটি কেমন হবে?"

আমি নিশ্চিত ছিলাম এটি AB2C3 হবে, তবে চমকপ্রদ আশ্চর্য, এটি সত্য নয়।

সঠিক উত্তরটি এবিসি 3 (পরীক্ষিত এবং সত্যিই এটির মতো)।

আমার প্রশ্ন, ব্যতিক্রম ("2") কোথায় গেল?


8
+1 আহহ, আমি এই উত্তরটি জানতাম। আমাকে একটি সাক্ষাত্কারে এটি জিজ্ঞাসা করা হয়েছিল। চেষ্টা / ধরা / শেষ পর্যন্ত স্ট্যাকটিতে কীভাবে কাজ করে তা বোঝার জন্য এটি একটি খুব ভাল প্রশ্ন।
তবে আমি

10
এখানে কেবল একটি মুদ্রণ বিবৃতি রয়েছে যা একটি সংখ্যা মুদ্রণ করতে পারে (শেষ print(e.getMessage()):)। আপনি ভেবেছিলেন আউটপুটটি হবে AB2C3: আপনি কি ভেবেছিলেন বাইরেরতম catchব্লকটি দুটিবার কার্যকর করা হবে?
অ্যাড্রিয়ান প্রোঙ্ক

জাভাতে, ক্যাচ ব্লকের বাইরে ট্রান্সফার নিয়ন্ত্রণ কার্যকর করার নির্দেশের আগে, অবশেষে এটি উপস্থিত থাকলে শংসাপত্র কার্যকর করা হয়। যদি কেবল অবশেষে ব্লকের কোডগুলি বাইরে থেকে নিয়ন্ত্রণ স্থানান্তর না করে তবে ক্যাচ ব্লক থেকে বিলম্বিত নির্দেশ কার্যকর করা হবে।
থমাস

উত্তর:


198

থেকে জাভা ল্যাঙ্গুয়েজ স্পেসিফিকেশন 14.20.2। :

আর ব্লকের কারণে যদি ক্যাচ ব্লকটি হঠাৎ করে সম্পূর্ণ করে, তবে শেষ অবধি ব্লকটি কার্যকর করা হয়। তারপরে একটি পছন্দ আছে:

  • যদি অবশেষে ব্লকটি স্বাভাবিকভাবে সম্পূর্ণ হয়, তবে চেষ্টা স্টেটমেন্টটি হঠাৎ করে আর এর জন্য পূর্ণ হয়।

  • যদি অবশেষে ব্লকটি হঠাৎ করে এস এর কারণে সম্পূর্ণ হয়, তবে চেষ্টা স্টেটমেন্ট হঠাৎ এস এর কারণে (এবং কারণ আর বাদ দেওয়া হয়) জন্য সম্পূর্ণ হয়

সুতরাং, যখন কোনও ক্যাচ ব্লক থাকে যা ব্যতিক্রম ছুঁড়ে ফেলে:

try {
    // ...
} catch (Exception e) {
    throw new Exception("2");
}

তবে একটি অবশেষে ব্লক রয়েছে যা ব্যতিক্রম ছুঁড়ে ফেলেছে:

} finally {
    throw new Exception("3");
}

Exception("2")বাতিল করা হবে এবং কেবল Exception("3")প্রচার করা হবে।


72
এমনকি এটি returnবিবৃতিতে সত্যও ধারণ করে । যদি আপনার অবশেষে ব্লকের কোনও রিটার্ন থাকে তবে এটি কোনও tryবা catchব্লকের কোনও রিটার্নকে ওভাররাইড করে । এই "বৈশিষ্ট্যগুলি" এর কারণে, একটি ভাল অনুশীলন হ'ল শেষ অবধি ব্লকটি কখনই ব্যতিক্রম হয় না বা রিটার্নের বিবৃতি না দেয়।
আগস্টো

এটি জাভা in-এ প্রাপ্ত উত্তরাধিকার সূত্রে প্রাপ্ত উত্তরাধিকারী সুবিধাও হ'ল এটি প্রাথমিক ব্যতিক্রম সংরক্ষণ করে যদি সংস্থানগুলি বন্ধ করার সময় গৌণ ব্যতিক্রম উত্পন্ন হয়, সাধারণত ডিবাগিং সহজ করে তোলে।
w25r

19

শেষ অবধি ব্লকযুক্ত ব্যতিক্রমগুলি চেষ্টা বা ক্যাচ ব্লকের আগে ছুঁড়ে দেওয়া ব্যতিক্রমকে দমন করে।

জাভা 7 উদাহরণ: http://ideone.com/0YdeZo

থেকে Javadoc এর উদাহরণ:


static String readFirstLineFromFileWithFinallyBlock(String path)
                                                     throws IOException {
    BufferedReader br = new BufferedReader(new FileReader(path));
    try {
        return br.readLine();
    } finally {
        if (br != null) br.close();
    }
}

যাইহোক, এই উদাহরণে, পদ্ধতিগুলি যদি লাইন পড়ায় এবং উভয়ই ব্যতিক্রমগুলি বন্ধ করে দেয়, তবে পদ্ধতিটি পড়ুন ফার্স্টলাইনফ্রমফাইলে ফিনলি ব্লক অবশেষে ব্লক থেকে ফেলে দেওয়া ব্যতিক্রম ছোঁড়ে; চেষ্টা ব্লক থেকে নিক্ষিপ্ত ব্যতিক্রম চাপা দেওয়া হয়।


try-withজাভা 7 এর নতুন সিনট্যাক্স ব্যতিক্রমী দমনের আরও একটি পদক্ষেপ যুক্ত করেছে: ট্রাই ব্লক করা ব্যতিক্রমগুলি চেষ্টা-সহ অংশে ফেলে দেওয়া লোকদের দমন করে।

একই উদাহরণ থেকে:

try (
        java.util.zip.ZipFile zf = new java.util.zip.ZipFile(zipFileName);
        java.io.BufferedWriter writer = java.nio.file.Files.newBufferedWriter(outputFilePath, charset)
    ) {
        for (java.util.Enumeration entries = zf.entries(); entries.hasMoreElements();) {
            String newLine = System.getProperty("line.separator");
            String zipEntryName = ((java.util.zip.ZipEntry)entries.nextElement()).getName() + newLine;
            writer.write(zipEntryName, 0, zipEntryName.length());
        }
    }

সম্পদ বিবরণীর সাথে যুক্ত কোডের ব্লক থেকে একটি ব্যতিক্রম ছুঁড়ে ফেলা যায়। উপরের উদাহরণে ট্রাই ব্লক থেকে একটি ব্যতিক্রম ছুঁড়ে ফেলা যায় এবং যখন জিপফায়ার এবং বাফারড্রাইটার অবজেক্টগুলিকে বন্ধ করার চেষ্টা করে তবে রিসোর্স-উইথ স্টেটমেন্ট থেকে দু'টি ব্যতিক্রম পর্যন্ত ছুঁড়ে দেওয়া যায়। যদি চেষ্টা ব্লক থেকে একটি ব্যতিক্রম ছুঁড়ে দেওয়া হয় এবং চেষ্টা করা সম্পদ-বিবৃতি থেকে এক বা একাধিক ব্যতিক্রম ছুঁড়ে ফেলা হয়, তবে চেষ্টা-সহ-সংস্থার বিবৃতি থেকে ছুঁড়ে দেওয়া ব্যতিক্রমগুলি দমন করা হয়, এবং ব্লকটি ছুঁড়ে দেওয়া ব্যতিক্রমটি হ'ল যা WritToFileZipFileContents পদ্ধতি দ্বারা নিক্ষেপ করা হয়। আপনি চেষ্টা ব্লক দ্বারা ছোঁড়া ব্যতিক্রম থেকে থ্রোয়েবল.জেটসপ্রেসড পদ্ধতিতে কল করে এই চাপা ব্যতিক্রমগুলি পুনরুদ্ধার করতে পারেন।


প্রশ্ন থেকে কোডে, প্রতিটি ব্লক পুরানো ব্যতিক্রমটি স্পষ্টতই বাতিল করে দিচ্ছে, এমনকি এটি লগ করাও নয়, আপনি যখন কিছু বাগ সমাধান করার চেষ্টা করছেন তখন ভাল নয়:

http://en.wikipedia.org/wiki/Error_hiding


9

যেহেতু ব্লক throw new Exception("2");থেকে নিক্ষিপ্ত catchএবং না try, তাই এটি আর ধরা পড়বে না। 14.20.2
দেখুন । শেষ অবধি চেষ্টা করে দেখুন-শেষ পর্যন্ত চেষ্টা করুন

এটাই হচ্ছে:

try {
    try {
        System.out.print("A");         //Prints A
        throw new Exception("1");   
    } catch (Exception e) { 
        System.out.print("B");         //Caught from inner try, prints B
        throw new Exception("2");   
    } finally {
        System.out.print("C");         //Prints C (finally is always executed)
        throw new Exception("3");  
    }
} catch (Exception e) {
    System.out.print(e.getMessage());  //Prints 3 since see (very detailed) link
}

হ্যাঁ এটা ঠিক, আমি এটি ঘটতে দেখছি, তবে আমি ব্যাখ্যাটির সন্ধান করছিলাম - কেন এটি এমন আচরণ করা হচ্ছে
কাউসালিক

5

আপনার প্রশ্নটি খুব সুস্পষ্ট, এবং উত্তরটিও একই পরিমাণে সহজ .. "2" হিসাবে বার্তাযুক্ত ব্যতিক্রম বস্তুটি "3" হিসাবে বার্তা সহ ব্যতিক্রমী বিষয়টিকে ওভাররাইট করে।

ব্যাখ্যা: যখন কোনও ব্যতিক্রম ঘটে তখন এটির হ্যান্ডেলটি ব্লক ধরার জন্য এটির বস্তু নিক্ষেপ করা হয়। কিন্তু যখন ব্যতিক্রম নিজেই ক্যাচ ব্লকে ঘটে তখন ব্যতিক্রম হ্যান্ডলিংয়ের জন্য এর অবজেক্টটি আউটর ক্যাচ ব্লকে (যদি থাকে) স্থানান্তরিত হয়। এবং একই ঘটেছে এখানে। "2" বার্তা সহ ব্যতিক্রম অবজেক্টটি OUTER ক্যাচ ব্লকে স্থানান্তরিত হয়। তবে অপেক্ষা করুন .. অভ্যন্তরীণ চেষ্টা-ধরার আগে এটি অবরুদ্ধ করা শেষ TO এখানে আমরা উদ্বিগ্ন পরিবর্তন ঘটে। একটি নতুন এক্সেসপশন অবজেক্ট (বার্তা "3" সহ) ফেলে দেওয়া হয়েছে বা এটি অবশেষে ব্লকটি ফেলেছে যা ইতিমধ্যে ফেলে দেওয়া এক্সসেপশন অবজেক্টকে প্রতিস্থাপন করেছে (বার্তা "2" সহ)। যার ফলস্বরূপ, যখন ব্যতিক্রম বস্তুর বার্তা প্রিন্ট করা হয়, তখন আমরা পেয়েছিলাম ওভাররাইড মান যেমন "3" এবং "2" নয়।

মনে রাখবেন: ক্যাচ ব্লকে কেবলমাত্র একটি ব্যতিক্রম বস্তু পরিচালনা করতে পারে।


2

finallyব্লক সবসময় চালায়। হয় আপনি returnচেষ্টা ব্লকের ভিতরে থেকে বা একটি ব্যতিক্রম নিক্ষেপ করা হয়। finallyব্লকটিতে ফেলে দেওয়া ব্যতিক্রম ক্যাপ শাখায় নিক্ষিপ্ত একটিকে ওভাররাইড করে।

অতিরিক্তভাবে, একটি ব্যতিক্রম ছুঁড়ে দেওয়া নিজেই কোনও আউটপুট সৃষ্টি করবে না। লাইন throw new Exception("2");কিছু লিখবে না।


1
হ্যাঁ, আমি নিজেই এক্সেক্সশন আউটপুটটি ছুঁড়ে ফেলা জানি, তবে কেন কারণ ব্যতিক্রম 2 বাদ দেওয়া উচিত তা আমি দেখিনি। আমি আবার কিছুটা স্মার্ট
হয়েছি

সবসময় খুব দীর্ঘ সময়ের এবং খুব দীর্ঘ সময়ের কিছু ঘটতে পারে (চেক ধাঁধা wouter.coekaerts.be/2012/puzzle-dreams )
Dainius

0

আপনার কোড অনুসারে:

try {
    try {
        System.out.print("A");
        throw new Exception("1");   // 1
    } catch (Exception e) {
        System.out.print("B");      // 2
        throw new Exception("2");
    } finally {                     // 3
        System.out.print("C");      // 4 
        throw new Exception("3");
    }
} catch (Exception e) {             // 5
    System.out.print(e.getMessage());
}

আপনি এখানে দেখতে পারেন:

  1. A মুদ্রণ এবং ব্যতিক্রম ছোঁড়া # 1;
  2. এই ব্যতিক্রম ধরা বিবৃতি এবং মুদ্রণ দ্বারা ধরা হয়েছে B - # 2;
  3. অবশেষে # 3চেষ্টা করুন-ধরা পরে মৃত্যুদন্ড কার্যকর করা (বা কেবল চেষ্টা করুন, যদি কোনও ব্যতিক্রম ঘটে না থাকে) বিবৃতি এবং মুদ্রণ C - # 4এবং নতুন ব্যতিক্রম ছুঁড়ে;
  4. এই একজন বহিরাগত ক্যাচ স্টেটমেন্ট দ্বারা ধরা পড়েছে # 5;

ফলাফল হয় ABC3। এবং 2একই ভাবে বাদ দেওয়া হয় is1


দুঃখিত, ব্যতিক্রম ("1") বাদ দেওয়া হয়নি, তবে সফলভাবে ধরা পড়েছে
ব্ল্যাক ম্যাগি

@ ব্ল্যাক ম্যাগি এটি ক্যাশেড এবং নিক্ষেপ করেছে নতুন ব্যতিক্রম => এটি ক্যাশেড এবং প্রোগ্রামের সমাপ্ত নয়। এবং এই ব্লক অবশেষে মৃত্যুদন্ড কার্যকর করার আগে।
নাজার_আর
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.