স্ট্যাটিক ইনিশিয়ালাইজেশন ব্লক থেকে জাভা কেন একটি চেক করা ব্যতিক্রম নিক্ষেপ করতে দেয় না?


135

স্ট্যাটিক ইনিশিয়ালাইজেশন ব্লক থেকে জাভা কেন একটি চেক করা ব্যতিক্রম নিক্ষেপ করতে দেয় না? এই ডিজাইনের সিদ্ধান্তের পিছনে কারণ কী ছিল?


স্ট্যাটিক ব্লকের কোন ধরণের পরিস্থিতি আপনি কীভাবে বাদ দিতে চান?
কাই হুপম্যান

1
আমি এরকম কিছু করতে চাই না। আমি কেবল জানতে চাইছি স্ট্যাটিক ব্লকের ভিতরে চেক করা ব্যতিক্রমগুলি কেন ধরা বাধ্যতামূলক।
মিসিংফ্যাক্টর

আপনি কীভাবে চেক করা ব্যতিক্রমটি হ্যান্ডেল করার আশা করবেন? যদি এটি আপনাকে বিরক্ত করে, তবে নতুন রানটাইম এক্সেকশন ("বার্তা বলার জন্য", ই) দিয়ে ধরা ব্যতিক্রমটিকে নতুন করে দেখুন;
থরবজর্ন রাভন অ্যান্ডারসন

18
@ থরবজর্নআরভানএন্ডারসন জাভা আসলে সেই পরিস্থিতির জন্য একটি ব্যাতিক্রমের প্রকার সরবরাহ করে: ডকসস.ওরকল
//

@ smp7d নীচে কেভিনার্প উত্তর এবং স্টিফেনসির কাছ থেকে তার মন্তব্য দেখুন। এটি সত্যিই দুর্দান্ত বৈশিষ্ট্যযুক্ত তবে এতে ফাঁদ রয়েছে!
বেঞ্জ

উত্তর:


122

কারণ আপনার উত্সে এই চেক করা ব্যতিক্রমগুলি পরিচালনা করা সম্ভব নয়। প্রারম্ভিককরণ প্রক্রিয়াটির উপর আপনার কোনও নিয়ন্ত্রণ নেই এবং আপনার উত্স থেকে স্থির}} ব্লকগুলি কল করা যায় না যাতে চেষ্টা করে আপনি এগুলি ঘিরে রাখতে পারেন।

আপনি কোনও পরীক্ষিত ব্যতিক্রম দ্বারা নির্দেশিত কোনও ত্রুটি পরিচালনা করতে পারবেন না, তাই চেক করা ব্যতিক্রম স্ট্যাটিক ব্লক নিক্ষেপ করার অনুমতি দেওয়া হয়নি।

স্ট্যাটিক ব্লক অবশ্যই চেক করা ব্যতিক্রমগুলি ছুঁড়ে ফেলবে না তবুও চেক করা / রানটাইম-ব্যতিক্রমগুলি ছুঁড়ে ফেলার অনুমতি দেয়। তবে উপরের কারণ অনুসারে আপনি এগুলি পরিচালনা করতেও অক্ষম হবেন।

সংক্ষিপ্তসার হিসাবে, এই বিধিনিষেধটি বিকাশকারীকে এমন কিছু তৈরি করা থেকে বাধা দেয় (যার ফলে ত্রুটি হতে পারে যা থেকে অ্যাপ্লিকেশনটি পুনরুদ্ধার করতে অক্ষম হবে।


69
আসলে, এই উত্তরটি সঠিক নয়। আপনি একটি স্থিতিশীল ব্লকে ব্যতিক্রম ফেলতে পারেন। আপনি যা করতে পারবেন না তা হ'ল স্থিতিশীল ব্লকের বাইরে কোনও পরীক্ষিত ব্যতিক্রম প্রচার করতে দেওয়া
স্টিফেন সি

16
আপনি যদি এই ব্যতিক্রমটিকে পরিচালনা করতে পারেন, আপনি যদি ক্লাস.ফোনেম (..., সত্য, ...) সহ গতিশীল ক্লাস লোড করছেন; মঞ্জুর, এটি এমন কিছু নয় যা আপনি প্রায়শই ঘুরে আসেন।
18:25

2
স্ট্যাটিক {নতুন নলপয়েন্টারএক্সসিপশন () নিক্ষেপ করুন - এটিও সংকলন করবে না!
কিরিল বাজারভ

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

2
@ রবিশা কারণ যে ক্ষেত্রে আর কোনও ক্ষেত্রে প্রাথমিকভাবে আরম্ভ করার সুযোগ নেই। ট্রাই-ক্যাচের সাথে প্রিন্টলন দ্বারা ছোঁড়া কোনও ব্যতিক্রম থাকতে পারে না এবং তাই আরম্ভকারীটির ব্যতিক্রম ছাড়াই সম্পূর্ণ করার সুযোগ রয়েছে। এটি একটি ব্যতিক্রমের নিঃশর্ত ফলাফল যা এটি একটি সংকলন-ত্রুটি করে তোলে। এর জন্য জেএলএস দেখুন: ডকসস.অরাকল.com / javase / specs / jls / se7 / html / jls-8.html#jls-8.7 তবে আপনার ক্ষেত্রে একটি সাধারণ শর্ত যুক্ত করে সংকলকটি বোকা হতে পারে:static { if(1 < 10) { throw new NullPointerException(); } }
Kosi2801

67

যে কোনও চেক করা ব্যতিক্রম ধরা এবং এটি একটি চেক করা ব্যতিক্রম হিসাবে পুনর্বিবেচনা করে আপনি সমস্যার আশপাশে কাজ করতে পারেন। এই অবারিত ব্যতিক্রম বর্গ একটি লেফাফা পাশাপাশি কাজ করে: java.lang.ExceptionInInitializerError

কোডের উদাহরণ:

protected static class _YieldCurveConfigHelperSingleton {

    public static YieldCurveConfigHelper _staticInstance;

    static {
        try {
            _staticInstance = new YieldCurveConfigHelper();
        }
        catch (IOException | SAXException | JAXBException e) {
            throw new ExceptionInInitializerError(e);
        }
    }
}

1
@ ডি কে: সম্ভবত আপনার জাভা সংস্করণটি এই ধরণের ক্যাচ ক্লজটিকে সমর্থন করে না। চেষ্টা করুন: catch (Exception e) {পরিবর্তে।
কেভিনারপে

4
হ্যাঁ, আপনি এটি করতে পারেন তবে এটি সত্যিই খারাপ ধারণা। চেক না করা ব্যতিক্রম ক্লাস এবং অন্যান্য ক্লাসের উপর নির্ভর করে যা এর উপর নির্ভর করে ব্যর্থ রাষ্ট্র যা কেবল ক্লাসগুলি আনলোডের মাধ্যমে সমাধান করা যেতে পারে। এটি সাধারণত অসম্ভব, এবং System.exit(...)(বা সমতুল্য) হ'ল আপনার একমাত্র বিকল্প,
স্টিফেন সি

1
@ স্টেফেনসি আমরা কী ভাবতে পারি যে কোনও "পিতামাতা" শ্রেণি যদি লোড করতে ব্যর্থ হয় তবে আপনার কোডটি কাজ করবে না বলে নির্ভরশীল শ্রেণিগুলি লোড করা অপ্রয়োজনীয়? আপনি কি দয়া করে এমন একটি মামলার উদাহরণ প্রদান করতে পারেন যেখানে যে কোনও উপায়ে এই ধরনের নির্ভরশীল শ্রেণিকে লোড করা প্রয়োজন হবে? ধন্যবাদ
বেনজ

কীভাবে ... যদি কোডটি এটিকে গতিশীলভাবে লোড করার চেষ্টা করে; যেমন Class.forName এর মাধ্যমে।
স্টিফেন সি

21

এটি দেখতে এমন হবে (এই হল না বৈধ জাভা কোড)

// Not a valid Java Code
static throws SomeCheckedException {
  throw new SomeCheckedException();
}

আপনি যেখানে এটি ধরবেন সেখানে বিজ্ঞাপনটি কীভাবে হবে? চেক করা ব্যতিক্রমগুলি ধরা দরকার। কিছু উদাহরণ কল্পনা করুন যা ক্লাসটি সূচনা করতে পারে (বা এটি ইতিমধ্যে আরম্ভ করা হয়েছে বলেই নাও হতে পারে), এবং এটি যে জটিলতার পরিচয় দেবে তার মনোযোগ আকর্ষণ করার জন্য, আমি উদাহরণগুলিকে অন্য স্ট্যাটিক ইনিটালাইজারে রেখেছি:

static {
  try {
     ClassA a = new ClassA();
     Class<ClassB> clazz = Class.forName(ClassB.class);
     String something = ClassC.SOME_STATIC_FIELD;
  } catch (Exception oops) {
     // anybody knows which type might occur?
  }
}

এবং অন্য একটি খারাপ জিনিস -

interface MyInterface {
  final static ClassA a = new ClassA();
}

কল্পনা করুন ক্লাসএতে একটি স্ট্যাটিক ইনিশিয়ালাইজার ছিল যাচাই করা ব্যতিক্রম ছুঁড়েছে: এক্ষেত্রে মাইইনটারফেস (যা একটি 'লুকানো' স্ট্যাটিক ইনিশিয়ালাইজারের সাথে একটি ইন্টারফেস) ব্যতিক্রম ছোঁড়াতে বা এটি পরিচালনা করতে হবে - কোনও ইন্টারফেসে ব্যতিক্রম হ্যান্ডলিং? এটি যেমন আছে তেমন ছেড়ে দিন।


7
mainচেক করা ব্যতিক্রম ছুঁড়ে ফেলতে পারে। স্পষ্টতই সেগুলি পরিচালনা করা যায় না।
যান্ত্রিক শামুক 8

@ মেকানিক্যালসেল: আকর্ষণীয় বিষয়। আমার জাভা সম্পর্কিত মানসিক মডেলটিতে, আমি ধরে নিই যে সেখানে একটি "জাদুকরী" (ডিফল্ট) থ্রেড রয়েছে Uউচ্ছুক এক্সসেপশনহ্যান্ডলার থ্রেডের সাথে সংযুক্ত main()যা স্ট্যাক ট্রেস দিয়ে ব্যতিক্রমটি মুদ্রণ করে System.err, তারপরে কল করে System.exit()। শেষ পর্যন্ত, এই প্রশ্নের উত্তর সম্ভবত: "কারণ জাভা ডিজাইনাররা তাই বলেছিলেন"।
কেভিনার্পে

7

স্ট্যাটিক ইনিশিয়ালাইজেশন ব্লক থেকে জাভা কেন একটি চেক করা ব্যতিক্রম নিক্ষেপ করতে দেয় না?

প্রযুক্তিগতভাবে, আপনি এটি করতে পারেন। তবে, পরীক্ষিত ব্যতিক্রম অবশ্যই ব্লকের মধ্যে ধরা উচিত be একটি পরীক্ষিত ব্যতিক্রম ব্লক থেকে প্রচার করার অনুমতি নেই ।

প্রযুক্তিগতভাবে, একটি স্ট্যাটিক ইনিশিয়ালাইজার ব্লক 1 এর বাইরে কোনও চেক করা ব্যতিক্রমকেও প্রচার করতে দেওয়া সম্ভব । তবে এটি ইচ্ছাকৃতভাবে করা সত্যিই খারাপ ধারণা! সমস্যাটি হ'ল জেভিএম নিজেই অচিহ্নযুক্ত ব্যতিক্রমটি ধরবে এবং এটিকে জড়িয়ে রাখবে এবং এটিকে আবার নতুন করে দেখায়ExceptionInInitializerError

এনবি: এটি একটি Error একটি নিয়মিত ব্যতিক্রম নয়। আপনার এটি থেকে পুনরুদ্ধার করার চেষ্টা করা উচিত নয়।

বেশিরভাগ ক্ষেত্রে, ব্যতিক্রম ধরা যায় না:

public class Test {
    static {
        int i = 1;
        if (i == 1) {
            throw new RuntimeException("Bang!");
        }
    }

    public static void main(String[] args) {
        try {
            // stuff
        } catch (Throwable ex) {
            // This won't be executed.
            System.out.println("Caught " + ex);
        }
    }
}

$ java Test
Exception in thread "main" java.lang.ExceptionInInitializerError
Caused by: java.lang.RuntimeException: Bang!
    at Test.<clinit>(Test.java:5)

2try ... catch ধরার জন্য আপনি উপরের কোনও জায়গায় রাখতে পারবেন নাExceptionInInitializerError

কিছু ক্ষেত্রে আপনি এটি ধরতে পারেন। উদাহরণস্বরূপ, যদি আপনি কল করে ক্লাস ইনিশিয়েশনটি ট্রিগার করেন Class.forName(...), আপনি কলটি একটিতে বন্ধ করে দিতে পারেন এবং একটি বা tryপরবর্তীটি ধরতে পারেনExceptionInInitializerErrorNoClassDefFoundError

তবে, যদি আপনি কোনওটি থেকে পুনরুদ্ধার করার চেষ্টা করেন তবে আপনি একটি ExceptionInInitializerErrorরোড ব্লক দৌড়ে দায়বদ্ধ। সমস্যাটি হ'ল ত্রুটিটি ছুঁড়ে ফেলার আগে, জেভিএম ক্লাস চিহ্নিত করে যা সমস্যাটি "ব্যর্থ" হিসাবে চিহ্নিত করে। আপনি কেবল এটি ব্যবহার করতে সক্ষম হবেন না। তদ্ব্যতীত, ব্যর্থ শ্রেণীর উপর নির্ভরশীল অন্য কোনও শ্রেণি যদি তারা আরম্ভ করার চেষ্টা করে তবে ব্যর্থ অবস্থায়ও যাবে। এগিয়ে যাওয়ার একমাত্র উপায় হ'ল সমস্ত ব্যর্থ ক্লাসকে আনলোড করা। এটি গতিশীল লোড কোড 3 এর জন্য সম্ভব হতে পারে , তবে সাধারণভাবে তা হয় না।

1 - স্থিতিশীল ব্লকটি নিঃশর্তভাবে একটি চেক করা ব্যতিক্রম ছুঁড়ে ফেলা হলে এটি সংকলন ত্রুটি ।

2 - আপনি কোনও পূর্বনির্ধারিত ব্যতিক্রম ব্যতিক্রম হ্যান্ডলারটি রেজিস্ট্রেশন করে এটিকে আটকাতে সক্ষম হতে পারেন তবে এটি আপনাকে পুনরুদ্ধার করতে দেয় না কারণ আপনার "মূল" থ্রেড শুরু হতে পারে না।

3 - আপনি যদি ব্যর্থ ক্লাসগুলি পুনরুদ্ধার করতে চান, আপনার ক্লাসলোডার যে লোড করেছে সেগুলি থেকে আপনাকে মুক্তি দিতে হবে।


এই ডিজাইনের সিদ্ধান্তের পিছনে কারণ কী ছিল?

প্রোগ্রামারকে কোড লেখা থেকে রক্ষা করা যা হ্যান্ডেল করা যায় না এমন ব্যতিক্রম ছুঁড়ে দেয় !

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


ঠিক আছে, সুতরাং যদি আপনার কোডটি একটি স্ট্যাটিক ইনিশিয়ালাইজারে ব্যতিক্রম ছোঁড়ার "প্রয়োজন" হয় তবে আপনার কী করা উচিত। মূলত, দুটি বিকল্প রয়েছে:

  1. যদি (পূর্ণ!) ব্লকের মধ্যে ব্যতিক্রম থেকে পুনরুদ্ধার সম্ভব হয়, তবে এটি করুন।

  2. অন্যথায়, আপনার কোডটি পুনর্গঠন করুন যাতে কোনও স্ট্যাটিক ইনিশিয়ালাইজেশন ব্লক (বা স্ট্যাটিক ভেরিয়েবলগুলির আরম্ভকারীগুলিতে) সূচনা না ঘটে।


কোডটি কীভাবে গঠন করা যায় সে সম্পর্কে কোনও সাধারণ সুপারিশ রয়েছে যাতে এটি কোনও স্থির সূচনা না করে?
মাস্টারজয়ে

এই সমাধানগুলি কীভাবে বাজে? stackoverflow.com/a/21321935/6648326 এবং stackoverflow.com/a/56575807/6648326
MasterJoe2

1
1) আমার কোন নেই। 2) তারা খারাপ শোনাচ্ছে। আমি তাদের উপর দেওয়া মন্তব্য দেখুন। তবে আমি উপরের আমার উত্তরে আমি যা বলেছি কেবল তা পুনরাবৃত্তি করছি। আপনি যদি আমার উত্তরটি পড়েন এবং বুঝতে পারেন তবে আপনি জানবেন যে "সমাধানগুলি" কোনও সমাধান নয়।
স্টিফেন সি

4

জাভা ল্যাঙ্গুয়েজ স্পেসিফিকেশনগুলির দিকে একবার নজর দিন : এটি স্থিতিশীল আরম্ভকারী ব্যর্থ যদি চেক করা ব্যতিক্রম সহ আকস্মিকভাবে সম্পূর্ণ করতে সক্ষম হয় তবে এটি একটি সংকলন সময় ত্রুটি বলে উল্লেখ করা হয় ।


5
এটি যদিও প্রশ্নের উত্তর দেয় না। তিনি জিজ্ঞাসা করলেন কেন এটি একটি সংকলন সময় ত্রুটি।
উইনস্টন স্মিথ

হুঁ, সুতরাং যে কোনও রানটাইম এরির নিক্ষেপ করা সম্ভব হওয়া উচিত, কারণ জেএলএস কেবলমাত্র পরীক্ষিত ব্যতিক্রমগুলির উল্লেখ করে।
Andreas ডলক

এটা ঠিক, তবে আপনি কখনও স্ট্যাকট্র্যাস হিসাবে দেখতে পাবেন না। এজন্য আপনার স্ট্যাটিক ইনিশিয়েশন ব্লকগুলি সম্পর্কে সতর্ক হওয়া দরকার be
ইজেবি

2
@ ইজেবি: এটি ভুল। আমি কেবল এটি চেষ্টা করেছিলাম এবং নিম্নলিখিত কোডটি আমাকে একটি ভিজ্যুয়াল স্ট্যাকট্রেস দিয়েছে: public class Main { static { try{Class.forName("whathappenswhenastaticblockthrowsanexception");} catch (ClassNotFoundException e){throw new RuntimeException(e);} } public static void main(String[] args){} }আউটপুট:Exception in thread "main" java.lang.ExceptionInInitializerError Caused by: java.lang.RuntimeException: java.lang.ClassNotFoundException: whathappenswhenastaticblockthrowsanexception at Main.<clinit>(Main.java:6) Caused by: java.lang.ClassNotFoundException: whathappen...
কনরাড হাফনার

"এর দ্বারা সৃষ্ট" অংশটি স্ট্যাকের ট্রেসটি দেখায় যা আপনি সম্ভবত আরও আগ্রহী
লেডি ক্যালিন

2

যেহেতু আপনি যে কোনও কোড লিখেছেন তা স্ট্যাটিক ইনিশিয়ালাইজেশন ব্লকে কল করতে পারে না তাই এটি পরীক্ষা করা নিক্ষেপ করা কার্যকর নয় exceptions। যদি এটি সম্ভব হত, একটি চেক করা ব্যতিক্রম ছুঁড়ে ফেলা হলে jvm কী করবে? Runtimeexceptionsপ্রচার করা হয়।


1
ঠিক আছে, হ্যাঁ আমি এখন বিষয়টি বুঝতে পারি। এটি একটি প্রশ্ন পোস্ট করে আমার খুব বোকা ছিল। কিন্তু হায়রে ... আমি এখন এটি মুছে ফেলতে পারি না। :( তবুও, আপনার প্রতিক্রিয়াটির জন্য +1 ...
অনুপস্থিত ফ্যাক্টর

1
@ প্রাসঙ্গিকভাবে, চেক করা ব্যতিক্রমগুলি রানটাইম এক্সেক্সসে রূপান্তরিত হয় না। আপনি যদি নিজে বাইকোড লেখেন, আপনি চিকিত্সা ব্যতিক্রমগুলি স্ট্যাটিক ইনিশিয়ালাইজারের ভিতরে আপনার হৃদয়ের সামগ্রীতে ফেলে দিতে পারেন। জেভিএম মোটেও ব্যতিক্রম চেক করার বিষয়ে চিন্তা করে না; এটি নিখুঁতভাবে জাভা ভাষার নির্মাণ ruct
অ্যান্টিমোনি

0

উদাহরণস্বরূপ: স্প্রিংয়ের ডিসপ্যাচারসার্ভালেট (org.springframework.web.servlet.DispatcherServlet) একটি দৃশ্যের ব্যয় করে যা একটি চেক করা ব্যতিক্রম ধরা পড়ে এবং অন্য একটি চেক করা ব্যতিক্রম ছোঁড়ে।

static {
    // Load default strategy implementations from properties file.
    // This is currently strictly internal and not meant to be customized
    // by application developers.
    try {
        ClassPathResource resource = new ClassPathResource(DEFAULT_STRATEGIES_PATH, DispatcherServlet.class);
        defaultStrategies = PropertiesLoaderUtils.loadProperties(resource);
    }
    catch (IOException ex) {
        throw new IllegalStateException("Could not load '" + DEFAULT_STRATEGIES_PATH + "': " + ex.getMessage());
    }

1
এই সমস্যাটি যাচাই করা ব্যতীত ধরা পড়তে পারে না এমন সমস্যা। পরিবর্তে এটি শ্রেণি এবং অন্য যে কোনও শ্রেণীর উপর নির্ভর করে যা একটি অপ্রাপ্তযোগ্য রাজ্যে পরিণত করে।
স্টিফেন সি

@ স্টেফেনসি - আপনি কি দয়া করে এমন একটি সাধারণ উদাহরণ দিতে পারেন যাতে আমরা পুনরুদ্ধারযোগ্য রাষ্ট্র চাই?
মাস্টারজয়ে 2

হাইপোথিটিক্যালি ... আপনি যদি IOException থেকে পুনরুদ্ধার করতে সক্ষম হতে চান যাতে অ্যাপ্লিকেশনটি চালিয়ে যেতে পারে। যদি আপনি এটি করতে চান, তবে আপনাকে অবশ্যই এই ব্যতিক্রমটি ধরতে হবে এবং এটি অবশ্যই পরিচালনা করতে হবে ... একটি চেক করা ব্যতিক্রম নিক্ষেপ করবেন না।
স্টিফেন সি

-5

আমি একটি চেক করা ব্যতিক্রম ছোঁড়াটিও সংকলন করতে সক্ষম হয়েছি ...

static {
    try {
        throw new IOException();
    } catch (Exception e) {
         // Do Something
    }
}

3
হ্যাঁ তবে আপনি এটি স্ট্যাটিক ব্লকের মধ্যে ধরছেন। আপনি একটি স্ট্যাটিক ব্লকের ভিতরে থেকে বাইরে এটির বাইরে চেক করা ব্যতিক্রম নিক্ষেপ করার অনুমতি নেই।
আর্টঅফ ওয়ারফেয়ার
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.