জাভাক কেন কিছু অসম্ভব কস্টকে অনুমতি দেয় এবং অন্যকে নয়?


52

যদি আমি একটি কাস্ট করার জন্য চেষ্টা Stringএকটি থেকে java.util.Date, জাভা কম্পাইলার এরর ক্যাচ। তাহলে কেন সংকলকটি ত্রুটি হিসাবে নিম্নলিখিতটিকে পতাকাঙ্কিত করে না?

List<String> strList = new ArrayList<>();                                                                      
Date d = (Date) strList;

অবশ্যই, জেভিএম ClassCastExceptionরানটাইমের সময় একটি ছুড়ে ফেলে , তবে সংকলক এটি ফ্ল্যাগ করে না।

জাভ্যাক 1.8.0_212 এবং 11.0.2 এর সাথে আচরণটি একই।


2
Listএখানে বিশেষ কিছুই । Date d = (Date) new Object();
এলিয়ট ফ্রিচ

1
আমি ইদানীং একটি আরডুইনো নিয়ে খেলছি। আমি এমন একটি সংকলক পছন্দ করব যা আনন্দের সাথে কোনও castালাই গ্রহণ করে নি এবং কেবল সম্পূর্ণ অনাকাঙ্ক্ষিত ফলাফল দিয়ে সেগুলি করেছে। পূর্ণসংখ্যা স্ট্রিং? ঠিক! পূর্ণসংখ্যা দ্বিগুণ? জী জনাব! বুলিয়ান স্ট্রিং? কমপক্ষে সে একজন বেশিরভাগই মিথ্যা হয়ে যায় ...
স্টায়ান ইত্তেরভিক

@ এলিয়টফ্রিচ: তারিখ এবং অবজেক্টের মধ্যে সুস্পষ্ট উত্তরাধিকারের সম্পর্ক রয়েছে তবে তারিখ এবং তালিকার মধ্যে কোনও সম্পর্ক নেই। সুতরাং আমি আশা করেছি যে সংকলকটি এই কাস্টটিকে পতাকাযুক্ত করবে, ঠিক একইভাবে এটি স্ট্রিং থেকে তারিখের কোনও কাস্টকে পতাকাযুক্ত করবে। জাবুজা তাদের দুর্দান্ত উত্তরে ব্যাখ্যা হিসাবে, তালিকাটি একটি ইন্টারফেস, সুতরাং theালাই বৈধ হবে যদি strListকোনও শ্রেণীর তালিকা তৈরি হয় যা তালিকাকে কার্যকর করে।
মাইক ওয়াইনোস্কি 13

এটি প্রায়শই পুনরাবৃত্তি হওয়া প্রশ্ন এবং আমি নিশ্চিত যে এর একাধিক নকল আমি দেখেছি। এটি মূলত দৃ
হাল্ক

1
পুনঃটুইট করেছেন সংকলক সতর্কতা চালু করুন।
ববসবার্নার

উত্তর:


86

ঢালাই হয় টেকনিক্যালি সম্ভব। এটি জাভা দ্বারা সহজে প্রমাণিত হতে পারে না যে এটি আপনার ক্ষেত্রে এটি নয় এবং জেএলএস প্রকৃতপক্ষে এটি একটি বৈধ জাভা প্রোগ্রাম হিসাবে সংজ্ঞায়িত করেছে, সুতরাং একটি ত্রুটি চিহ্নিত করা ভুল হবে।

এটি কারণ Listএকটি ইন্টারফেস। সুতরাং আপনার এখানে একটি সাবক্লাস থাকতে পারে Dateযা বাস্তব Listহিসাবে Listএখানে ছদ্মবেশ প্রয়োগ করে - এবং তারপরে একে একে Dateএকে পুরোপুরি ঠিক আছে। উদাহরণ স্বরূপ:

public class SneakyListDate extends Date implements List<Foo> {
    ...
}

এবং তারপর:

List<Foo> list = new SneakyListDate();
Date date = (Date) list; // This one is valid, compiles and runs just fine

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

নোট করুন যে JLS আপনার কোডটি একটি বৈধ জাভা প্রোগ্রাম হতে হবে। ইন 5.1.6.1। অনুমোদিত সংকেত রেফারেন্স রূপান্তর এটিতে বলেছে:

একটি কমিয়ে আনায় রেফারেন্স রূপান্তর রেফারেন্স ধরণ থেকে বিদ্যমান Sরেফারেন্স টাইপ Tযদি সব নিম্নলিখিত হয় সত্য :

  • [...]
  • এক নিম্নলিখিত ক্ষেত্রে প্রযোজ্য :
    • [...]
    • Sএকটি ইন্টারফেস টাইপ, Tএকটি শ্রেণির ধরণ, এবং Tএকটি finalশ্রেণীর নাম দেয় না ।

তাই এমনকি যদি কম্পাইলার পারে জিনিসটা যে আপনার ক্ষেত্রে আসলে provably অসম্ভব, এটা পতাকা একটি ত্রুটি মঞ্জুরিপ্রাপ্ত নয় কারণ JLS বৈধ জাভা প্রোগ্রাম যেমন সংজ্ঞায়িত করা হয়।

এটি কেবলমাত্র একটি সতর্কতা দেখানোর অনুমতি দেওয়া হবে।


16
এবং লক্ষণীয় যে স্ট্রিংয়ের সাথে এটি কেস করার কারণ, এটি স্ট্রিং চূড়ান্ত, তাই সংকলক জানে যে কোনও শ্রেণি এটি বাড়িয়ে দিতে পারে না।
এমটিস্টल्ड

5
আসলে, আমি মনে করি না এটি স্ট্রিংয়ের "চূড়ান্ততা" যা myDate = (Date) myStringব্যর্থ হয়েছে। JLS পরিভাষা ব্যবহার করে, বিবৃতি প্রচেষ্টা থেকে রূপান্তর করতে S( Stringকরা) T( Date)। এখানে, Sকোনও ইন্টারফেসের ধরণ নয়, তাই উপরে উদ্ধৃত জেএলএস শর্তটি প্রযোজ্য নয়। উদাহরণস্বরূপ, একটি তারিখে একটি ক্যালেন্ডার কাস্ট করার চেষ্টা করুন এবং কোনও ক্লাস চূড়ান্ত না হলেও আপনি একটি সংকলক ত্রুটি পাবেন।
মাইক ওয়াইনোস্কি

1
আমি জানি না যে সংক্ষেপক হতাশ হবেন কি না তা প্রমাণ করার জন্য পর্যাপ্ত স্ট্যাটিক বিশ্লেষণ করতে পারে না যে স্ট্রললিস্ট কেবল কখনও অ্যারেলিস্ট টাইপ হতে পারে।
জোশুয়া

3
সংকলকটি পরীক্ষা করা নিষেধ। তবে এটিকে ত্রুটি বলা নিষিদ্ধ। এটি সংকলকটি অ-কমপ্লায়েন্ট করে তুলবে। (আমার উত্তর দেখুন ...)
স্টিফেন সি

3
একটি সামান্য বিট শ্রেণীর বা সম্প্রদায়ের ভাষা যুক্ত করার জন্য, কম্পাইলার প্রমাণ করতে হবে যে টাইপ করতে হবে Date & Listহয় বসবাসের অযোগ্য , এটা প্রমাণ করতে হবে যে এটা হয় যথেষ্ট নয় কেউ বাস বর্তমানে (এটা ভবিষ্যতে হতে পারে)।
২৩:৩১

15

আসুন আপনার উদাহরণের একটি সাধারণীকরণ বিবেচনা করুন:

List<String> strList = someMethod();       
Date d = (Date) strList;

Date d = (Date) strList;সংকলন ত্রুটি না হওয়ার মূল কারণগুলি এই ।

  • স্বজ্ঞাত কারণ যে কম্পাইলার বস্তু পদ্ধতি কল দ্বারা ফিরে সুনির্দিষ্ট টাইপ না (সাধারণ) জানে হয়। এটা সম্ভব যে একটি শ্রেণী হওয়া ছাড়াও যে কার্যকরী List, এটা এছাড়াও একটি উপশ্রেণী Date

  • প্রযুক্তিগত কারণে যে জাভা ল্যাঙ্গুয়েজ স্পেসিফিকেশন "দেয়" হয় সরু হয়ে রেফারেন্স রূপান্তর যে এই ধরনের ঢালাই অনুরূপ। জেএলএস 5.1.6.1 অনুসারে :

    " নীচের সমস্ত সত্য হলে Sরেফারেন্স টাইপ থেকে রেফারেন্স টাইপ পর্যন্ত সংকীর্ণ রেফারেন্স রূপান্তর বিদ্যমান T:"

    ...

    5) " Sএকটি ইন্টারফেস টাইপ, Tএটি একটি শ্রেণীর ধরণের, এবং Tকোনও finalশ্রেণীর নাম দেয় না ।"

    ...

    অন্য কোনও জায়গায়, জেএলএস আরও বলেছে যে রানটাইমের সময় একটি ব্যতিক্রম ছোঁড়া হতে পারে ...

    লক্ষ্য করুন JLS 5.1.6.1 সংকল্প ভিত্তি করে একমাত্র আসল রানটাইমের ধরণের পরিবর্তে জড়িত ভেরিয়েবলগুলির ঘোষিত ধরণের উপর । সাধারণ ক্ষেত্রে, সংকলক প্রকৃত রানটাইম প্রকারগুলি জানে না এবং জানতে পারে না।


সুতরাং, জাভা সংকলক কেন কাজ করতে পারে না যে কাস্ট কাজ করবে না?

  • আমার উদাহরণে, someMethod কলটি বিভিন্ন ধরণের জিনিসগুলিতে ফিরে আসতে পারে could এমনকি যদি সংকলকটি পদ্ধতিটির প্রধান অংশটি বিশ্লেষণ করতে সক্ষম হয়েছিল এবং ফেরত দেওয়া যেতে পারে তার প্রকারের নির্দিষ্ট সেট নির্ধারণ করতে সক্ষম হয়েও, কাউকে কল করে এমন কোড সংকলন করার পরেও কাউকে বিভিন্ন ধরণের ফেরত দিতে এটি পরিবর্তন করা বন্ধ করার কিছুই নেই। জেএলএস 5.1.6.1 এটি যা বলে তার মূল কারণ এটি।

  • আপনার উদাহরণে, একটি স্মার্ট কম্পাইলার পারে জিনিসটা যে ঢালাই সফল না করতে পারেন। এবং সমস্যাটি চিহ্নিত করার জন্য এটি একটি সংকলন-সময় সতর্কতা নির্গত করার অনুমতি দেওয়া হয় ।

তাহলে কেন কোনও স্মার্ট সংকলককে এটি ত্রুটি বলে বলার অনুমতি দেওয়া হচ্ছে না?

  • কারণ জেএলএস বলে যে এটি একটি বৈধ প্রোগ্রাম। সময়কাল। যে কোনও সংকলক যাকে এটিকে ত্রুটি বলেছে তা জাভা অনুগত হবে না।

  • এছাড়াও, জেএলএস এবং অন্যান্য সংকলকগুলি জাভা বলে যে জাভা প্রোগ্রামগুলি প্রত্যাখ্যান করে এমন কোনও সংকলক জাভা উত্স কোডের বহনযোগ্যতার জন্য একটি প্রতিবন্ধক।


4
আপত্তি জানাতে যে কলিং ক্লাস সংকলনের পরে তথাকথিত ফাংশন বাস্তবায়ন পরিবর্তিত হতে পারে , তাই এমনকি যদি এটি ক্যালির বর্তমান প্রয়োগের সাথে সংকলন সময়ে প্রমাণযোগ্য হয় তবে castালাই অসম্ভব, পরবর্তী সময়ে চলমান সময়ে এটি এমন নাও হতে পারে যখন কলি পরিবর্তন হয়েছে বা প্রতিস্থাপন করা হয়েছে।
পিটার - মনিকা

2
পোর্টেবিলিটি সমস্যাটি হাইলাইট করার জন্য আপভোট যা কোনও সংকলক খুব স্মার্ট হওয়ার চেষ্টা করলে প্রবর্তিত হবে।
মাইক ওয়াইনোস্কি

2

5.5.1। রেফারেন্স প্রকারের ingালাই:

একটি কম্পাইল-টাইম রেফারেন্স টাইপ দেওয়া S(উৎস) এবং একটি কম্পাইল-টাইম রেফারেন্স টাইপ T(টার্গেট), একটি ভোটদান রূপান্তর থেকে বিদ্যমান Sকরার T কোন কম্পাইল-টাইম এরর নিম্নলিখিত নিয়মগুলি কারণে ঘটে থাকে।

[...]

যদি Sকোনও ইন্টারফেসের ধরণ থাকে:

  • [...]

  • যদি Tএকটি বর্গ বা ইন্টারফেস ধরনের যে চূড়ান্ত নয়, তারপর সেখানে একটি supertype যদি উপস্থিত থাকে Xএর T, এবং একটি supertype Yএর S, এই ধরনের উভয় Xএবং Yprovably স্বতন্ত্র স্থিতিমাপ ধরনের হয়, এবং যে erasures XএবংY একই, একটি কম্পাইল-টাইম এরর দেখা দেয়।

    অন্যথায়, castালাই সর্বদা সংকলনের সময় আইনী (কারণ Tবাস্তবায়িত না হলেও S, শক্তির একটি সাবক্লাস T)।

List<String>হয় Sএবং Dateহয় Tআপনার ক্ষেত্রে।

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