চূড়ান্ত এবং কার্যকরভাবে চূড়ান্ত মধ্যে পার্থক্য


350

আমি জাভা 8 এ ল্যাম্বডাসের সাথে খেলছি এবং আমি সতর্কতা পেলাম local variables referenced from a lambda expression must be final or effectively final। আমি জানি যে আমি যখন বেনামে বর্গের ভিতরে ভেরিয়েবলগুলি ব্যবহার করি তখন অবশ্যই তাদের অবশ্যই বাইরের শ্রেণিতে চূড়ান্ত হতে হবে, তবে এখনও - চূড়ান্ত এবং কার্যকরভাবে চূড়ান্তের মধ্যে পার্থক্য কী ?


2
প্রচুর উত্তর, তবে সমস্ত মূলত "কোনও পার্থক্য নেই" to কিন্তু আসলেই কী ওটা সত্যি? দুর্ভাগ্যক্রমে, আমি জাভা 8 এর জন্য কোনও ভাষা স্পেসিফিকেশন খুঁজে পাচ্ছি না
আলেকসান্দ্র ডাবিনস্কি

3
@AleksandrDubinsky docs.oracle.com/javase/specs
Eis

@ আলেকসান্ডারডুবিনস্কি "সত্যই" সত্য নয়। আমি এই নিয়মের একটি ব্যতিক্রম পেয়েছি। একটি ধ্রুবক দিয়ে স্থানীয় স্থানীয় পরিবর্তনশীল সংকলকটির কাছে ধ্রুবক প্রকাশ নয়। আপনি চূড়ান্তভাবে চূড়ান্ত কীওয়ার্ডটি যোগ না করা পর্যন্ত আপনি স্যুইচ / কেসের ক্ষেত্রে কোনও ক্ষেত্রে এই জাতীয় পরিবর্তনশীল ব্যবহার করতে পারবেন না। যেমন "int k = 1; স্যুইচ (সামান্য কিছু) {কেস কে: ..."।
হেন্নো ভার্মুলেন

উত্তর:


234

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

উদাহরণস্বরূপ, ধরুন যে চলকটি numberLengthচূড়ান্ত হিসাবে ঘোষিত হয়নি এবং আপনি নির্ধারকটিতে চিহ্নিত অ্যাসাইনমেন্ট বিবৃতি যুক্ত করেছেন PhoneNumber:

public class OutterClass {  

  int numberLength; // <== not *final*

  class PhoneNumber {

    PhoneNumber(String phoneNumber) {
        numberLength = 7;   // <== assignment to numberLength
        String currentNumber = phoneNumber.replaceAll(
            regularExpression, "");
        if (currentNumber.length() == numberLength)
            formattedPhoneNumber = currentNumber;
        else
            formattedPhoneNumber = null;
     }

  ...

  }

...

}

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

http://codeinventions.blogspot.in/2014/07/difference-between-final-and.html

http://docs.oracle.com/javase/tutorial/java/javaOO/localclasses.html


68
+1 দ্রষ্টব্য: যদি কোনও রেফারেন্স পরিবর্তন না করা হয় তবে এটি কার্যকরভাবে চূড়ান্ত হয় এমনকি রেফারেন্সযুক্ত বস্তুটি পরিবর্তন করা হয়।
পিটার লরে

1
: @stanleyerror এতে কিছু সাহায্য হতে পারে stackoverflow.com/questions/4732544/...

1
আমি মনে করি কার্যকরভাবে চূড়ান্ত না হওয়ার উদাহরণের চেয়ে বেশি কার্যকর, যখন কোনও কিছু কার্যকরভাবে চূড়ান্ত হয় তার একটি উদাহরণ । যদিও বর্ণনাটি এটি পরিষ্কার করে দেয়। কোনও কোডের মান পরিবর্তন না হলে ভ্যারকে চূড়ান্ত ঘোষণা করার দরকার নেই।
স্কাইচান

1
উদাহরণটি ভুল। এই কোডটি নিখুঁতভাবে সংকলন করে (অবশ্যই বিন্দু ছাড়াই)। সংকলক ত্রুটি পেতে এই কোডটি কিছু পদ্ধতির অভ্যন্তরে থাকা উচিত যাতে এটি numberLengthএই পদ্ধতির স্থানীয় পরিবর্তনশীল হয়ে যায়।
মাইকোলা

1
এই উদাহরণটি এত জটিল হওয়ার কারণ রয়েছে কি? কেন বেশিরভাগ কোড সম্পূর্ণ অপ্রাসঙ্গিক রেজেক্স অপারেশনের সাথে কাজ করে? এবং, যেমন মাইকোলা ইতিমধ্যে বলেছে, কার্যকর চূড়ান্ত সম্পত্তি সম্পর্কিত চিহ্নটি এটি পুরোপুরি অনুপস্থিত , কারণ এটি কেবল স্থানীয় ভেরিয়েবলের সাথে প্রাসঙ্গিক এবং এই উদাহরণে কোনও স্থানীয় ভেরিয়েবল নেই।
হলগার

130

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


4
এটি সত্য, যতক্ষণ না জাভা 8 এর "ফাইনাল" বোঝার বিষয়টি ভালভাবে বোঝা যায়। অন্যথায় আমি এমন কোনও পরিবর্তনশীল না দেখে চূড়ান্ত হিসাবে ঘোষিত হয়েছি যা আপনি পরে একটি অ্যাসাইনমেন্ট করেছেন, এবং ভ্রান্তভাবে মনে হয় এটি চূড়ান্ত নয়। আপনি "অবশ্যই" বলতে পারেন ... তবে সকলেই তার সর্বশেষতম ভাষা সংস্করণের পরিবর্তনের প্রতি ততটা মনোযোগ দেয় না।
বোকা

8
এই নিয়মের একটি ব্যতিক্রম হ'ল একটি স্থির সঙ্গে স্থানীয় ভেরিয়েবল প্রাথমিকভাবে সংকলকটির কাছে ধ্রুবক প্রকাশ নয়। আপনি চূড়ান্তভাবে চূড়ান্ত কীওয়ার্ডটি যোগ না করা পর্যন্ত আপনি স্যুইচ / কেসের ক্ষেত্রে কোনও ক্ষেত্রে এই জাতীয় পরিবর্তনশীল ব্যবহার করতে পারবেন না। যেমন "int k = 1; স্যুইচ (সামান্য কিছু) {কেস কে: ..."।
হেনো ভার্মিউলেন

2
@ হেন্নো ভার্মুলেন স্যুইচ-কেস এই উত্তরের নিয়মের ব্যতিক্রম নয়। ভাষাটি উল্লেখ করে যে case kএকটি ধ্রুবক অভিব্যক্তি প্রয়োজন যা একটি ধ্রুবক পরিবর্তনশীল হতে পারে ("একটি ধ্রুবক পরিবর্তনশীল আদিম ধরণের বা স্ট্রিংয়ের একটি চূড়ান্ত পরিবর্তনশীল যা ধ্রুবক অভিব্যক্তি দিয়ে শুরু করা হয়" JLS 4.12.4 ) যা একটি ফাইনালের একটি বিশেষ ক্ষেত্রে পরিবর্তনশীল।
কলিন ডি বেনেট

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

36

ডক্স অনুসারে :

একটি পরিবর্তনশীল বা প্যারামিটার যার মান আরম্ভের পরে আর পরিবর্তন হয় না কার্যকরভাবে চূড়ান্ত।

মূলত, যদি সংকলকটি আবিষ্কার করে যে কোনও ভেরিয়েবল তার আরম্ভের বাইরে অ্যাসাইনমেন্টে উপস্থিত না হয়, তবে ভেরিয়েবল কার্যকরভাবে চূড়ান্ত হিসাবে বিবেচিত হয় ।

উদাহরণস্বরূপ, কিছু শ্রেণি বিবেচনা করুন:

public class Foo {

    public void baz(int bar) {
        // While the next line is commented, bar is effectively final
        // and while it is uncommented, the assignment means it is not
        // effectively final.

        // bar = 2;
    }
}

ডক্স স্থানীয় ভেরিয়েবল সম্পর্কে কথা বলে about barআপনার উদাহরণে স্থানীয় বৈকল্পিক নয়, তবে একটি ক্ষেত্র। উপরের হিসাবে ত্রুটি বার্তায় "কার্যকরভাবে চূড়ান্ত" ক্ষেত্রগুলিতে মোটেই প্রযোজ্য নয়।
আন্টি হাপালা

6
অ্যান্টিহাপালা barএখানে একটি প্যারামিটার, ক্ষেত্র নয়।
পিটার.পেট্রভ

30

'কার্যকরভাবে চূড়ান্ত' একটি পরিবর্তনশীল যা এটি 'চূড়ান্ত' দ্বারা যুক্ত করা হলে সংকলক ত্রুটি দেয় না

'ব্রায়ান গয়েটজ' এর একটি নিবন্ধ থেকে,

অনানুষ্ঠানিকভাবে, কোনও স্থানীয় পরিবর্তনশীল কার্যকরভাবে চূড়ান্ত হয় যদি এর প্রাথমিক মানটি কখনও পরিবর্তন না করা হয় - অন্য কথায়, এটি চূড়ান্ত ঘোষণা করা সংকলনের ব্যর্থতার কারণ হবে না।

ল্যাম্বদা-রাজ্য-ফাইনাল- ব্রায়ান গোয়েটস


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

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

26

নীচে এই ভেরিয়েবলটি চূড়ান্ত , সুতরাং একবারের শুরুতে আমরা এর মানটি পরিবর্তন করতে পারি না। আমরা যদি চেষ্টা করি তবে আমরা একটি সংকলন ত্রুটি পেয়ে যাব ...

final int variable = 123;

তবে আমরা যদি এর মতো একটি চলক তৈরি করি তবে আমরা এর মানটি পরিবর্তন করতে পারি ...

int variable = 123;
variable = 456;

তবে জাভা 8-এ , সমস্ত ভেরিয়েবলগুলি ডিফল্টরূপে চূড়ান্ত । তবে কোডে ২ য় লাইনের অস্তিত্ব একে চূড়ান্ত করে তোলে । সুতরাং আমরা যদি উপরের কোড থেকে ২ য় লাইনটি সরিয়ে ফেলি তবে আমাদের চলকটি এখন "কার্যকরভাবে চূড়ান্ত" ...

int variable = 123;

তাই .. কোন পরিবর্তনশীল যে একবার এবং শুধুমাত্র একবার নিয়োগ, "কার্যকরভাবে চূড়ান্ত" হয়


উত্তরটি যতটা সহজ হওয়া উচিত।
সুপারিগানো

@ ইউরিগ, "সমস্ত ভেরিয়েবলগুলি ডিফল্টরূপে চূড়ান্ত হয়" এর জন্য প্রয়োজনীয় উদ্ধৃতি প্রদান করা হয়।
পেসারিয়ার

10

কোনও পরিবর্তনশীল চূড়ান্ত বা কার্যকরভাবে চূড়ান্ত হয় যখন এটি একবার শুরু করা হয় এবং এটি কখনও তার মালিক শ্রেণিতে রূপান্তরিত হয় না । এবং আমরা এটিকে লুপ বা অভ্যন্তর শ্রেণিতে আরম্ভ করতে পারি না

ফাইনাল :

final int number;
number = 23;

কার্যকরভাবে চূড়ান্ত :

int number;
number = 34;

দ্রষ্টব্য : চূড়ান্ত এবং কার্যকর ফাইনাল সমান (অ্যাসাইনমেন্টের পরে তাদের মান পরিবর্তন হয় না) তবে কার্যকর কার্যকর চূড়ান্ত কীওয়ার্ড সহ ঘোষিত হয় না final


7

যখন একটি ল্যাম্বডা এক্সপ্রেশনটি তার ঘেরের জায়গা থেকে একটি নির্ধারিত স্থানীয় ভেরিয়েবল ব্যবহার করে তখন একটি গুরুত্বপূর্ণ বাধা থাকে। ল্যাম্বডা এক্সপ্রেশনটি কেবলমাত্র স্থানীয় ভেরিয়েবল ব্যবহার করতে পারে যার মান পরিবর্তন হয় না। এই সীমাবদ্ধতাটিকে " ভেরিয়েবল ক্যাপচার " হিসাবে উল্লেখ করা হয় যা বর্ণনা করা হয়; ল্যাম্বদা এক্সপ্রেশন ক্যাপচার মানগুলি, ভেরিয়েবলগুলি নয়
ল্যাম্বডা এক্সপ্রেশন ব্যবহার করতে পারে এমন স্থানীয় ভেরিয়েবলগুলি " কার্যকরভাবে চূড়ান্ত " হিসাবে পরিচিত ।
কার্যকরভাবে চূড়ান্ত পরিবর্তনশীল হ'ল তার মানটি প্রথম বরাদ্দের পরে পরিবর্তন হয় না। এ জাতীয় পরিবর্তনকে চূড়ান্ত হিসাবে ঘোষণা করার দরকার নেই, যদিও এটি করা কোনও ত্রুটি হবে না।
আসুন এটি একটি উদাহরণ সহ দেখুন, আমাদের একটি স্থানীয় ভেরিয়েবল i আছে যা মান 7 দিয়ে শুরু করা হয়েছিল, ল্যাম্বডা এক্সপ্রেশন দিয়ে আমরা নতুন মান নির্ধারণ করে সেই মানটি পরিবর্তন করার চেষ্টা করছি। এটি সংকলক ত্রুটির ফলস্বরূপ হবে - " স্থানীয় একটি পরিবর্তনক স্কোপ সংজ্ঞায়িত স্থানীয় পরিবর্তনশীল অবশ্যই চূড়ান্ত বা কার্যকরভাবে চূড়ান্ত হতে হবে "

@FunctionalInterface
interface IFuncInt {
    int func(int num1, int num2);
    public String toString();
}

public class LambdaVarDemo {

    public static void main(String[] args){             
        int i = 7;
        IFuncInt funcInt = (num1, num2) -> {
            i = num1 + num2;
            return i;
        };
    }   
}

2

কার্যকর চূড়ান্ত বিষয়টি জেএলএস 4.12.4 এ বর্ণিত হয়েছে এবং শেষ অনুচ্ছেদে একটি স্পষ্ট ব্যাখ্যা রয়েছে:

যদি কোনও ভেরিয়েবল কার্যকরভাবে চূড়ান্ত হয় তবে এর ঘোষণায় চূড়ান্ত সংশোধক যুক্ত করার ফলে কোনও সংকলন-সময় ত্রুটি প্রবর্তিত হবে না। বিপরীতে, একটি স্থানীয় পরিবর্তনশীল বা পরামিতি যা একটি বৈধ প্রোগ্রামে চূড়ান্ত ঘোষিত হয় চূড়ান্ত সংশোধক অপসারণ করা হলে কার্যকরভাবে চূড়ান্ত হয়।


2

চূড়ান্ত হ'ল মূল শব্দের সাথে একটি পরিবর্তনীয় ঘোষণা final, উদাহরণস্বরূপ:

final double pi = 3.14 ;

এটি finalপ্রোগ্রামের বাইরে থেকে যায়।

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

class EffectivelyFinal {

    public static void main(String[] args) {
        calculate(124,53);
    }

    public static void calculate( int operand1, int operand2){   
     int rem = 0;  //   operand1, operand2 and rem are effectively final here
     rem = operand1%2  // rem lost its effectively final property here because it gets its second assignment 
                       // operand1, operand2 are still effectively final here 
        class operators{

            void setNum(){
                operand1 =   operand2%2;  // operand1 lost its effectively final property here because it gets its second assignment
            }

            int add(){
                return rem + operand2;  // does not compile because rem is not effectively final
            }
            int multiply(){
                return rem * operand1;  // does not compile because both rem and operand1 are not effectively final
            }
        }   
   }    
}

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

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

@ অ্যান্ড্রুএফ যদি সময়ের সাথে সাথে পরিবর্তন না হয় তবে আপনি কী মনে করেন যে শেষ পংক্তিটি সংকলন করে না? গণনা পদ্ধতিতে রেমটি 1 লাইনটিতে কার্যকরভাবে চূড়ান্ত হয়েছিল। তবে, সর্বশেষ লাইনে, সংকলকটি অভিযোগ করেছে যে রিম কার্যকরভাবে চূড়ান্ত নয়
বৈজ্ঞানিক পদ্ধতি

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

1
public class LambdaScopeTest {
    public int x = 0;        
    class FirstLevel {
        public int x = 1;    
        void methodInFirstLevel(int x) {

            // The following statement causes the compiler to generate
            // the error "local variables referenced from a lambda expression
            // must be final or effectively final" in statement A:
            //
            // x = 99; 

        }
    }    
}

অন্যরা যেমন বলেছে, কোনও পরিবর্তনশীল বা প্যারামিটার যার মান আরম্ভের পরে আর পরিবর্তন হয় না তা কার্যকরভাবে চূড়ান্ত। উপরের কোডে, আপনি xযদি অভ্যন্তরীণ শ্রেণীর মান পরিবর্তন করেন FirstLevelতবে সংকলক আপনাকে ত্রুটি বার্তা দেবে:

ল্যাম্বডা এক্সপ্রেশন থেকে স্থানীয় ভেরিয়েবলগুলি অবশ্যই চূড়ান্ত বা কার্যকরভাবে চূড়ান্ত হতে হবে।


1

আপনি যদি finalস্থানীয় ভেরিয়েবলটিতে সংশোধক যুক্ত করতে পারেন তবে এটি কার্যকরভাবে চূড়ান্ত ছিল

লাম্বদা এক্সপ্রেশন অ্যাক্সেস করতে পারেন

  • স্ট্যাটিক ভেরিয়েবল,

  • উদাহরণস্বরূপ ভেরিয়েবল,

  • কার্যকরভাবে চূড়ান্ত পদ্ধতি পরামিতি, এবং

  • কার্যকরভাবে চূড়ান্ত স্থানীয় ভেরিয়েবল।

উত্স: ওসিপি: ওরাকল সার্টিফাইড পেশাদার জাভা এসই 8 প্রোগ্রামার II স্টাডি গাইড, জ্যানি বোয়ারস্কি, স্কট সেলিকফ

উপরন্তু,

একটি effectively finalভেরিয়েবল এমন একটি ভেরিয়েবল যা এর মান কখনই পরিবর্তন হয় না তবে finalকীওয়ার্ড সহ এটি ঘোষিত হয় না ।

উত্স: জাভা দিয়ে শুরু হচ্ছে: অবজেক্টগুলির মাধ্যমে নিয়ন্ত্রণ কাঠামো থেকে (6th ষ্ঠ সংস্করণ), টনি গাদিস

তদ্ব্যতীত, finalএটি প্রথমবার ব্যবহার করার আগে একেবারে একবারে শুরু করা হয়েছে এর অর্থটি ভুলে যাবেন না ।


0

কোনও ভেরিয়েবল ঘোষণা করা finalবা না ঘোষণা করা final, তবে এটিকে কার্যকরভাবে চূড়ান্ত রাখার ফলে বিভিন্ন বাইকোডে (সংকলকের উপর নির্ভরশীল) ফলাফল আসতে পারে।

আসুন একটি ছোট উদাহরণ দেখুন:

    public static void main(String[] args) {
        final boolean i = true;   // 6  // final by declaration
        boolean j = true;         // 7  // effectively final

        if (i) {                  // 9
            System.out.println(i);// 10
        }
        if (!i) {                 // 12
            System.out.println(i);// 13
        }
        if (j) {                  // 15
            System.out.println(j);// 16
        }
        if (!j) {                 // 18
            System.out.println(j);// 19
        }
    }

সংশ্লিষ্ট বাইটকোড mainপদ্ধতি (জাভা 8u161 উইন্ডোজ 64 বিট উপর):

  public static void main(java.lang.String[]);
    Code:
       0: iconst_1
       1: istore_1
       2: iconst_1
       3: istore_2
       4: getstatic     #16                 // Field java/lang/System.out:Ljava/io/PrintStream;
       7: iconst_1
       8: invokevirtual #22                 // Method java/io/PrintStream.println:(Z)V
      11: iload_2
      12: ifeq          22
      15: getstatic     #16                 // Field java/lang/System.out:Ljava/io/PrintStream;
      18: iload_2
      19: invokevirtual #22                 // Method java/io/PrintStream.println:(Z)V
      22: iload_2
      23: ifne          33
      26: getstatic     #16                 // Field java/lang/System.out:Ljava/io/PrintStream;
      29: iload_2
      30: invokevirtual #22                 // Method java/io/PrintStream.println:(Z)V
      33: return

সংশ্লিষ্ট লাইন নম্বর টেবিল:

 LineNumberTable:
   line 6: 0
   line 7: 2
   line 10: 4
   line 15: 11
   line 16: 15
   line 18: 22
   line 19: 26
   line 21: 33

আমরা লাইন সোর্স কোড দেখতে 12, 13, 14বাইট কোডে মনে হচ্ছে না। কারণ এটা iহল trueএবং এটি রাষ্ট্রীয় পরিবর্তন করবে না। এইভাবে এই কোডটি অ্যাক্সেসযোগ্য নয় (আরও উত্তর ) একই কারণে লাইনে 9কোডটিও খুব মিস করে। রাষ্ট্রটি নিশ্চিত iহওয়ার কারণে এটি মূল্যায়ন করতে হবে না true

অন্যদিকে যদিও পরিবর্তনশীল উপর jহয় কার্যকরভাবে চূড়ান্ত এটি একই ভাবে প্রক্রিয়া করা হচ্ছে। এ জাতীয় কোনও অপ্টিমাইজেশন প্রয়োগ করা হয়নি। রাষ্ট্রটির jদু'বার মূল্যায়ন করা হয়। বাইটকোড একই নির্বিশেষে jহচ্ছে কার্যকরভাবে চূড়ান্ত


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

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

-6

যাইহোক, জাভা এসই 8 এ শুরু করে, একটি স্থানীয় শ্রেণি চূড়ান্ত বা কার্যকরভাবে চূড়ান্ত যে> এনকোলেসিং ব্লকের স্থানীয় পরিবর্তনগুলি এবং প্যারামিটারগুলি অ্যাক্সেস করতে পারে।

এটি জাভা 8 এ শুরু হয়নি, আমি এটি দীর্ঘকাল থেকেই ব্যবহার করি। এই কোডটি (জাভা 8 এর আগে) আইনী হওয়ার জন্য ব্যবহৃত হয়েছিল:

String str = ""; //<-- not accesible from anonymous classes implementation
final String strFin = ""; //<-- accesible 
button.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
         String ann = str; // <---- error, must be final (IDE's gives the hint);
         String ann = strFin; // <---- legal;
         String str = "legal statement on java 7,"
                +"Java 8 doesn't allow this, it thinks that I'm trying to use the str declared before the anonymous impl."; 
         //we are forced to use another name than str
    }
);

2
বিবৃতিটি এই বিষয়টি বোঝায় যে <জাভা 8-এ কেবল final ভেরিয়েবলগুলি অ্যাক্সেস করা যায় তবে জাভা 8- এও কার্যকরভাবে চূড়ান্ত are
আন্টি হাপালা

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