জাভা 8-এ ব্যতিক্রম প্রকারের অনুক্রমের এক অদ্ভুত বৈশিষ্ট্য


85

এই সাইটে অন্য উত্তরের জন্য কোড লেখার সময় আমি এই বিশেষত্বটি দেখতে পেয়েছি:

static void testSneaky() {
  final Exception e = new Exception();
  sneakyThrow(e);    //no problems here
  nonSneakyThrow(e); //ERRROR: Unhandled exception: java.lang.Exception
}

@SuppressWarnings("unchecked")
static <T extends Throwable> void sneakyThrow(Throwable t) throws T {
  throw (T) t;
}

static <T extends Throwable> void nonSneakyThrow(T t) throws T {
  throw t;
}

প্রথমে, আমি সংক্ষেপকারীর কাছে sneakyThrowকল ঠিক আছে কেন আমি বেশ বিভ্রান্ত । Tকোনও চেকড ব্যতিক্রম ব্যতীত কোথাও উল্লেখ না থাকলে এটি কোন সম্ভাব্য প্রকারের জন্য অনুধাবন করেছিল ?

দ্বিতীয়ত, গ্রহণ করে যে এটি কাজ করে, তাহলে কেন সংকলক nonSneakyThrowকলটিতে অভিযোগ করবে ? এগুলি দেখতে অনেকটা একই রকম।

উত্তর:


66

টি টি sneakyThrowঅনুমান করা হয় RuntimeException। টাইপ অনুমানের বিষয়ে ল্যাঙ্গেজ স্পেক থেকে এটি অনুসরণ করা যেতে পারে ( http://docs.oracle.com/javase/specs/jls/se8/html/jls-18.html )

প্রথমত, বিভাগ 18.1.3 একটি নোট আছে:

ফর্মের একটি সীমা throws αনিখুঁতভাবে তথ্যযুক্ত: এটি রেজোলিউশনটির নির্দেশ দেয় the এর ইনস্ট্যান্টেশনটি অনুকূল করে তোলে যাতে সম্ভব হলে এটি একটি পরীক্ষিত ব্যতিক্রম প্রকার নয়।

এটি কোনও কিছুর ক্ষতি করে না, তবে এটি রেজোলিউশন বিভাগে (১৮.৪) দেখায়, যা একটি বিশেষ কেসের সাথে অনুমানযুক্ত ব্যতিক্রম সম্পর্কিত আরও তথ্য পেয়েছে:

... তা না হলে, আবদ্ধ সেট থাকে throws αi, এবং αi যথাযথ উপরের কোট সর্বাধিক, are, Exception, Throwable, এবং Objectতারপর, Ti থেকে = RuntimeException

এই ক্ষেত্রে প্রযোজ্য sneakyThrow- একমাত্র উপরের গণ্ডি Throwable, তাই Tঅনুমান অনুযায়ী অনুমান করা হয় RuntimeException, তাই এটি সংকলন করে। পদ্ধতির বডিটি অবিচ্ছিন্ন - চেক না করা কাস্ট রানটটাইমে সফল হয় কারণ এটি আসলে ঘটে না, এমন একটি পদ্ধতি রেখে যা সংকলন-সময় চেক ব্যতিক্রম সিস্টেমকে পরাস্ত করতে পারে।

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


4
@ ম্যাকসেম আপনার অবশ্যই sneakyThrowকলটি বোঝানো উচিত । throws Tফর্মগুলির
অনুক্রম

4
ছোট্ট নিটপিক: ইন nonSneakyThrow, Tঅবশ্যই Exception"সুপারের Exceptionটাইপ " হতে হবে না , কারণ এটি ঠিক একই জায়গায় কল সাইটে সংকলনের সময় ঘোষিত যুক্তির ধরণ।
লোগিক

4
@llogiq যদি আমি বৈশিষ্ট সঠিকভাবে পড়েছি, এটি একটি নিম্ন বাউন্ড পেয়েছে Exceptionএবং একটি ঊর্ধ্ব বাউন্ড Throwable, তাই অন্তত উপরের আবদ্ধ, যা ফলে অনুমিত ধরনের হয় Exception
কোকো

4
@ লোগিক নোট করুন যে আর্গুমেন্টের ধরণটি কেবল একটি নিম্ন প্রকারের বাউন্ড সেট করে কারণ আর্গুমেন্টের কোনও সুপারটাইপ গ্রহণযোগ্য।
মার্কো টপোলনিক

4
"বা Exceptionনিজেই" বাক্যাংশটি পাঠকের পক্ষে সহায়ক হতে পারে তবে সাধারণত, এটি লক্ষ করা উচিত যে স্পেসিফিকেশনটি সর্বদা "নিজেকে অন্তর্ভুক্ত" অর্থে "সাব টাইপ" এবং "সুপার টাইপ" শব্দটি ব্যবহার করে ...
হোলার

17

প্রকারের অনুক্রমটি যদি কোনও প্রকারের ভেরিয়েবলের জন্য একক উচ্চতর বাউন্ড উত্পাদন করে তবে সাধারণত উপরের সীমাটি সমাধান হিসাবে বেছে নেওয়া হয়। উদাহরণস্বরূপ, যদি T<<Number, সমাধান হয় T=Number। যদিও Integer, Floatইত্যাদিও এই সীমাবদ্ধতা পূরণ করতে পারে, সেগুলি বেছে নেওয়ার কোনও ভাল কারণ নেই Number

যে ক্ষেত্রে দেখা যায় throws Tজাভা 5-7 মধ্যে: T<<Throwable => T=Throwable। (লুক্কায়িত থ্রো সমাধানগুলির সকলের স্পষ্ট <RuntimeException>ধরণের যুক্তি ছিল, অন্যথায় <Throwable>অনুমান করা হয়))

জাভা 8-এ, ল্যাম্বদা প্রবর্তনের সাথে সাথে এটি সমস্যাযুক্ত হয়ে ওঠে। এই ক্ষেত্রে বিবেচনা করুন

interface Action<T extends Throwable>
{
    void doIt() throws T;
}

<T extends Throwable> void invoke(Action<T> action) throws T
{
    action.doIt(); // throws T
}    

যদি আমরা একটি খালি লাম্বদা দিয়ে প্রার্থনা করি তবে কী Tঅনুমান করা হবে?

    invoke( ()->{} ); 

একমাত্র সীমাবদ্ধতা Tহ'ল একটি উপরের আবদ্ধ Throwable। জাভা 8 এর প্রথম পর্যায়ে, T=Throwableঅনুমান করা হবে। আমি দায়ের এই রিপোর্ট দেখুন ।

তবে এটি বেশ নির্বোধ, Throwableখালি ব্লকের বাইরে পরীক্ষা করা ব্যতিক্রম। প্রতিবেদনে একটি সমাধান প্রস্তাব করা হয়েছিল (যা স্পষ্টতই জেএলএস গ্রহণ করেছেন) -

If E has not been inferred from previous steps, and E is in the throw clause, 
and E has an upper constraint E<<X,
    if X:>RuntimeException, infer E=RuntimeException
    otherwise, infer E=X. (X is an Error or a checked exception)

অর্থাত যদি সর্বোচ্চ সীমা Exceptionবা Throwableচয়ন RuntimeExceptionসমাধান হিসেবে। এই ক্ষেত্রে, সেখানে হয় ঊর্ধ্বসীমা নির্দিষ্ট উপপ্রকার পছন্দ করে নিন একটি ভাল কারণ।


X:>RuntimeExceptionআপনার শেষ উদাহরণ স্নিপেট এর অর্থ কী ?
মার্সউফ

1

এর সাথে sneakyThrow, টাইপটি একটি নির্দিষ্ট ধরণের ছাড়াইT একটি সীমাবদ্ধ জেনেরিক টাইপ ভেরিয়েবল (কারণ টাইপটি আসতে পারে এমন কোনও জায়গা নেই)।

সঙ্গে nonSneakyThrow, টাইপ Tআর্গুমেন্ট হিসাবে একই ধরনের, এইভাবে আপনার উদাহরণে হয় Tএর nonSneakyThrow(e);হয় Exception। যেমন testSneaky()একটি নিক্ষিপ্ত ঘোষণা করে না Exception, ত্রুটি দেখানো হয়েছে।

নোট করুন যে এটি চেক ব্যাতিক্রম সহ জেনারিক্সের একটি পরিচিত হস্তক্ষেপ।


সুতরাং sneakyThrowএটির জন্য আসলে কোনও নির্দিষ্ট ধরণের অনুমান করা যায় না, এবং "castালাই" কি এইরকম একটি অপরিজ্ঞাত টাইপের? আমি আশ্চর্য কি এই সঙ্গে আসলে ঘটে।
মার্কো টপলনিক
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.