রিটার্ন টাইপ সহ জাভা পদ্ধতি রিটার্ন বিবৃতি ছাড়াই সংকলন করে


228

প্রশ্ন 1:

নীচের কোডটি রিটার্নের স্টেটমেন্ট না দিয়ে সংকলন করে কেন?

public int a() {
    while(true);
}

বিজ্ঞপ্তি: আমি যদি কিছুক্ষণ পরে ফিরতি যোগ করি তবে আমি একটি পাই Unreachable Code Error

প্রশ্ন 2:

অন্যদিকে, নীচের কোডগুলি কেন সংকলন করে,

public int a() {
    while(0 == 0);
}

যদিও নিম্নলিখিতটি না করে।

public int a(int b) {
    while(b == b);
}

2
২ য় প্রশ্নের দ্বিতীয়ার্ধের জন্য ধন্যবাদ, স্ট্যাকওভারফ্লো :: প্রশ্নগুলি / ১6789৮৮৮32৩২ / এর সদৃশ নয় ।
টিজে ক্রাউডার

উত্তর:


274

প্রশ্ন 1:

নীচের কোডটি রিটার্নের স্টেটমেন্ট না দিয়ে সংকলন করে কেন?

public int a() 
{
    while(true);
}

এটি JLS§8.4.7 দ্বারা আচ্ছাদিত :

যদি কোনও পদ্ধতির রিটার্ন টাইপ (§8.4.5) হিসাবে ঘোষিত হয়, তবে পদ্ধতিটির শরীরে সাধারণত (§14.1) সম্পূর্ণ করতে পারলে একটি সংকলন-সময় ত্রুটি ঘটে।

অন্য কথায়, একটি রিটার্ন টাইপ সহ একটি পদ্ধতি অবশ্যই একটি রিটার্ন স্টেটমেন্ট ব্যবহার করে ফিরে আসতে হবে যা একটি মান ফেরত সরবরাহ করে; পদ্ধতিটিকে "তার শরীরের শেষটি ফেলে দেওয়ার" অনুমতি দেওয়া হয় না। কোনও পদ্ধতিতে শরীরের রিটার্নের বিবৃতি সম্পর্কে সুনির্দিষ্ট নিয়মগুলির জন্য §14.17 দেখুন।

কোনও পদ্ধতির ক্ষেত্রে রিটার্নের ধরণ থাকা এবং এখনও কোনও রিটার্নের বিবৃতি না থাকা সম্ভব। এখানে একটি উদাহরণ দেওয়া হল:

class DizzyDean {
    int pitch() { throw new RuntimeException("90 mph?!"); }
}

যেহেতু সংকলক জানে যে লুপটি কখনই শেষ হবে না ( trueঅবশ্যই সর্বদা সত্য, অবশ্যই) তাই এটি জানে যে ফাংশনটি "স্বাভাবিকভাবে ফিরে আসতে পারে না" (তার দেহের শেষ প্রান্তটি ছেড়ে দিতে পারে), এবং সুতরাং ঠিক আছে যে কিছুই নেই return

প্রশ্ন 2:

অন্যদিকে, নীচের কোডগুলি কেন সংকলন করে,

public int a() 
{
    while(0 == 0);
}

যদিও নিম্নলিখিতটি না করে।

public int a(int b)
{
    while(b == b);
}

ইন 0 == 0মামলা, কম্পাইলার জানে যে লুপ বিনষ্ট হবে না (যে 0 == 0সবসময় সত্য হতে হবে)। তবে এটি তার জন্য জানে নাb == b

কেন না?

সংকলক ধ্রুবক এক্সপ্রেশন (§15.28) বোঝে§15.2 উদ্ধৃত করা - এক্সপ্রেশন এর ফর্ম (কারণ অদ্ভুতভাবে এই বাক্যটি 15.28 ডলারে নেই) :

কিছু এক্সপ্রেশন একটি মান আছে যা সংকলন সময়ে নির্ধারণ করা যেতে পারে। এগুলি ধ্রুবক অভিব্যক্তি (.215.28)।

আপনার b == bউদাহরণে, একটি পরিবর্তনশীল জড়িত থাকার কারণে, এটি একটি ধ্রুবক প্রকাশ নয় এবং সংকলনের সময় নির্ধারিত হওয়ার জন্য নির্দিষ্ট করা হয় না। আমরা দেখতে পারেন এটা সবসময় এই ক্ষেত্রে সত্য হতে যাচ্ছে (যদিও যদি bছিল double, যেমন QBrute নির্দিষ্ট , আমরা সহজেই বোকা বানানো যেতে পারে Double.NaN, যা না ==নিজেই ), কিন্তু JLS শুধুমাত্র নির্দিষ্ট করে যে ধ্রুব এক্সপ্রেশন কম্পাইল সময়ে নির্ধারিত হয় এটি সংকলকটিকে অ-ধ্রুবক অভিব্যক্তিগুলি মূল্যায়নের চেষ্টা করতে দেয় না। bayou.io কেন একটি ভাল পয়েন্ট উত্থাপন করেছেন : আপনি যদি সংকলনের সময় ভেরিয়েবল জড়িত প্রকাশগুলি নির্ধারণের চেষ্টা করার রাস্তায় নামতে শুরু করেন তবে আপনি কোথায় থামবেন? b == bসুস্পষ্ট (এর, অ-জন্যNaNমান) তবে কী a + b == b + a? নাকি (a + b) * 2 == a * 2 + b * 2? ধ্রুবকগুলিতে লাইনটি আঁকলে বোঝা যায়।

সুতরাং যেহেতু এটি অভিব্যক্তিটি "নির্ধারণ" করে না, সংকলক জানে না যে লুপটি কখনই শেষ হবে না, সুতরাং এটি মনে করে যে পদ্ধতিটি সাধারণত ফিরে আসতে পারে - যা এটি করার অনুমতি নেই, কারণ এটি ব্যবহার করা প্রয়োজন return। সুতরাং এটি একটি অভাব সম্পর্কে অভিযোগ return


34

নির্দিষ্ট ধরনের একটি মান ফিরে যাওয়ার প্রতিশ্রুতি যেমন একটি পদ্ধতি রিটার্ন টাইপ মনে না আকর্ষণীয় হতে পারে, কিন্তু একটি প্রতিশ্রুতি যেমন না যে একটি মান ফিরে যাওয়ার নয় নির্দিষ্ট ধরনের। সুতরাং, আপনি যদি কখনই কোনও কিছু ফেরত না পান তবে আপনি প্রতিশ্রুতি ভঙ্গ করছেন না, এবং সুতরাং নিম্নলিখিতগুলির কোনওটি বৈধ:

  1. চিরকালের জন্য লুপিং:

    X foo() {
        for (;;);
    }
  2. চিরকাল পুনরাবৃত্তি:

    X foo() {
        return foo();
    }
  3. ব্যতিক্রম ছুঁড়ে ফেলা:

    X foo() {
        throw new Error();
    }

(আমি পুনরাবৃত্তিটি ভাবার জন্য একটি মজা পাই: সংকলকটি বিশ্বাস করে যে পদ্ধতিটি যে কোনও ধরণের মান X(যা কিছু হোক) ফেরত দেবে , তবে এটি সত্য নয়, কারণ এমন কোনও কোড নেই যা কীভাবে তৈরি করতে হয় বা কোনও ধারণা নেই) সংগ্রহ করা X।)


8

বাইট কোডটি দেখে, যা যা ফিরিয়ে দেওয়া হচ্ছে সংজ্ঞাটির সাথে মেলে না, আপনি একটি সংকলন ত্রুটি পাবেন।

উদাহরণ:

for(;;) বাইকোডগুলি প্রদর্শন করবে:

L0
    LINENUMBER 6 L0
    FRAME SAME
    GOTO L0

কোনও রিটার্ন বাইটকোডের অভাব নোট করুন

এটি কখনও কোনও রিটার্নকে আঘাত করে না এবং এভাবে ভুল প্রকারটি ফিরে আসে না।

তুলনার জন্য, একটি পদ্ধতি:

public String getBar() { 
    return bar; 
}

নিম্নলিখিত বাইকোডগুলি ফিরিয়ে দেবে:

public java.lang.String getBar();
    Code:
      0:   aload_0
      1:   getfield        #2; //Field bar:Ljava/lang/String;
      4:   areturn

"Areturn" যার অর্থ "রেফারেন্স ফিরিয়ে দিন"

এখন যদি আমরা নিম্নলিখিতটি করি:

public String getBar() { 
    return 1; 
}

নিম্নলিখিত বাইকোডগুলি ফিরিয়ে দেবে:

public String getBar();
  Code:
   0:   iconst_1
   1:   ireturn

এখন আমরা দেখতে পাচ্ছি যে সংজ্ঞায়িত টাইপটি রিটার্নের রিটার্ন টাইপের সাথে মেলে না, যার অর্থ রিটার্ন ইনট।

সুতরাং এটি কী নেমে আসে তা হ'ল যদি পদ্ধতিটির কোনও ফেরতের পথ থাকে তবে সেই পথটি অবশ্যই ফেরতের ধরণের সাথে মেলে। তবে বাইটকোডে এমন কিছু উদাহরণ রয়েছে যেখানে কোনও ফেরার পথই তৈরি হয় না এবং এভাবে নিয়ম ভঙ্গ হয় না।

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