জাভাতে স্ট্যাটিক ব্লক কার্যকর করা হয়নি


87
class Test {
    public static void main(String arg[]) {    
        System.out.println("**MAIN METHOD");
        System.out.println(Mno.VAL); // SOP(9090);
        System.out.println(Mno.VAL + 100); // SOP(9190);
    }

}

class Mno {
    final static int VAL = 9090;
    static {
        System.out.println("**STATIC BLOCK OF Mno\t: " + VAL);
    }
}

আমি জানি যে staticক্লাস লোড হওয়ার পরে একটি ব্লক কার্যকর করা হয়েছিল। তবে এক্ষেত্রে বর্গের ভিতরে উদাহরণটি পরিবর্তনশীলMno হয় finalকারণ যে, staticব্লক নির্বাহ করা হয় না।

কেন যে এত? এবং যদি আমি অপসারণ করি final, এটি কি ঠিক কাজ করবে?

কোন স্মৃতি প্রথমে বরাদ্দ করা হবে, এর static final পরিবর্তনশীল বা staticব্লক?

যদি finalঅ্যাক্সেস মডিফায়ারের কারণে ক্লাসটি লোড হয় না, তবে ভেরিয়েবল কীভাবে মেমরি পেতে পারে?


4
সঠিক ত্রুটি এবং বার্তাটি আপনি কী পান?
পাতাসু

@ পাতাসু, কোনও ত্রুটি নেই, এটি একটি সন্দেহ
স্থিতা

উত্তর:


135
  1. একটি static final intক্ষেত্র একটি সংকলন-সময় ধ্রুবক এবং এর মানটির উত্সের উল্লেখ ছাড়াই গন্তব্য শ্রেণিতে হার্ডকোড করা হয়;
  2. অতএব আপনার প্রধান শ্রেণীর ক্ষেত্রটি সহ ক্লাসের লোডটি ট্রিগার করে না;
  3. সুতরাং class শ্রেণীর স্ট্যাটিক ইনিশিয়ালাইজার কার্যকর হয় না।

নির্দিষ্ট বিশদে, সংকলিত বাইটকোড এটির সাথে মিলে যায়:

public static void main(String arg[]){    
    System.out.println("**MAIN METHOD");
    System.out.println(9090)
    System.out.println(9190)
}

যত তাড়াতাড়ি আপনি সরান final, এটি আর একটি সংকলন-সময় ধ্রুবক নয় এবং উপরে বর্ণিত বিশেষ আচরণ প্রযোজ্য নয়। Mnoশ্রেণী হিসেবে আশা এবং লোড হয়, executes সূচনাকারী তার স্ট্যাটিক।


4
তবে, তাহলে ক্লাসে লোড না করে ক্লাসে চূড়ান্ত ভেরিয়েবলের মান কীভাবে মূল্যায়ন করা হয়?
সুমিত দেশাই

18
সমস্ত মূল্যায়ন সংকলন সময়ে ঘটে এবং শেষের ফলাফলটি সমস্ত স্থানে হার্ডকোড করা হয় যা পরিবর্তনশীল উল্লেখ করে।
মার্কো টপলনিক

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

4
মার্কো, সুমিতের সন্দেহও ঠিক যদি আদিম পরিবর্তে এটি কিছু অবজেক্ট হয় তবে এই জাতীয় হার্ডকোডিং সম্ভব হবে না। তাই না? সুতরাং, সেক্ষেত্রে সেই শ্রেণিটি কী লোড হবে এবং স্ট্যাটিক ব্লকটি কার্যকর হবে?
স্থিতা

8
@ সুমিতডেসাই ঠিক, এটি কেবল আদিম মান এবং স্ট্রিং আক্ষরিক জন্য কাজ করে। পুরো বিশদের জন্য জাভা ভাষার নির্দিষ্টকরণের সম্পর্কিত অধ্যায়টি
মার্কো টপলনিক

8

কারণ বর্গ লোড করা হয় না যে VALহয় final এবং এটা ইনিশিয়ালাইজ করা হয় একটি ধ্রুবক অভিব্যক্তি (9090)। যদি, এবং কেবল যদি, দুটি শর্ত পূরণ করা হয় তবে সংযোগের সময় ধ্রুবকটি মূল্যায়ন করা হয় এবং যেখানে প্রয়োজন সেখানে "হার্ডকোডযুক্ত"।

সংকলন সময়ে (এবং জেভিএমকে আপনার শ্রেণীর বোঝা চাপিয়ে দেওয়ার জন্য) অভিব্যক্তিটি মূল্যায়ন করা থেকে বিরত রাখতে আপনি হয় করতে পারেন:

  • চূড়ান্ত কীওয়ার্ডটি সরান:

    static int VAL = 9090; //not a constant variable any more
    
  • বা ডান হাতের অভিব্যক্তিটি অবিরাম কিছুতে পরিবর্তন করুন (চলক এখনও চূড়ান্ত হলেও):

    final static int VAL = getInt(); //not a constant expression any more
    static int getInt() { return 9090; }
    

5

আপনি যদি বাইটোকড ব্যবহার করে জেনারেট করে দেখেন তবে javap -v Test.classমূল () এর মতো বেরিয়ে আসে:

public static void main(java.lang.String[]) throws java.lang.Exception;
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=1, args_size=1
         0: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
         3: ldc           #3                  // String **MAIN METHOD
         5: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
         8: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
        11: sipush        9090
        14: invokevirtual #5                  // Method java/io/PrintStream.println:(I)V
        17: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
        20: sipush        9190
        23: invokevirtual #5                  // Method java/io/PrintStream.println:(I)V
        26: return        

আপনি পরিষ্কারভাবে দেখতে পাবেন "11: sipush 9090 যে স্থিতিশীল চূড়ান্ত মানটি সরাসরি ব্যবহৃত হয়, কারণ ম্নোভাল একটি সংকলনের সময় ধ্রুবক। সুতরাং এমএনও ক্লাস লোড করার প্রয়োজন নেই। সুতরাং মন্নোর স্ট্যাটিক ব্লক কার্যকর করা হয় না।

আপনি ম্যানুয়ালি নিচের মত লোড করে স্ট্যাটিক ব্লক কার্যকর করতে পারেন:

class Test{
    public static void main(String arg[]) throws Exception {
        System.out.println("**MAIN METHOD");
        Class.forName("Mno");                 // Load Mno
        System.out.println(Mno.VAL);
        System.out.println(Mno.VAL+100);
    }

}

class Mno{
    final static int VAL=9090;
    static{
        System.out.println("**STATIC BLOCK OF Mno\t:"+VAL);
    }
}

1
  1. আসলে আপনি সেই এমএনও ক্লাসটি প্রসারিত করেন নি তাই সংকলন শুরু করার সাথে সাথে এটি ভেরিয়েবল VAL এর ধ্রুবক উত্পন্ন করবে এবং যখন ভেরিয়েবলটির স্মৃতি থেকে তার লোডের প্রয়োজন হয় যখন কার্যকরকরণ শুরু হয়। সুতরাং এটির প্রয়োজন নেই যে আপনার শ্রেণি রেফারেন্স যাতে স্থির বক কার্যকর হয় না।

  2. যদি শ্রেণি ক্লাসকে Aপ্রসারিত করে Mno, স্ট্যাটিক ব্লকটি শ্রেণিতে অন্তর্ভুক্ত করা হয় Aযদি আপনি এটি করেন তবে স্ট্যাটিক ব্লকটি কার্যকর করা হবে। উদাহরণ স্বরূপ..

    public class A extends Mno {
    
        public static void main(String arg[]){    
            System.out.println("**MAIN METHOD");
            System.out.println(Mno.VAL);//SOP(9090);
            System.out.println(Mno.VAL+100);//SOP(9190);
        }
    
    }
    
    class Mno {
        final static int VAL=9090;
        static {
            System.out.println("**STATIC BLOCK OF Mno\t:"+VAL);
        }
    }
    

0

আমি যতদূর জানি, এটি উপস্থিতির ক্রমে কার্যকর করা হবে। এই ক্ষেত্রে :

 public class Statique {
     public static final String value1 = init1();

     static {
         System.out.println("trace middle");
     }
     public static final String value2 = init2();


     public static String init1() {
         System.out.println("trace init1");
         return "1";
     }
     public static String init2() {
         System.out.println("trace init2");
         return "2";
     }
 }

মুদ্রণ করবে

  trace init1
  trace middle
  trace init2

আমি কেবল এটি পরীক্ষা করেছি এবং স্ট্যাটিকগুলি প্রাথমিক (=> মুদ্রণ) করা হয় যখন "স্ট্যাটিক" ক্লাসটি আসলে ব্যবহার করা হয় এবং কোডের অন্য অংশে "মৃত্যুদন্ড কার্যকর করা হয়" (আমার ক্ষেত্রে আমি "নতুন স্ট্যাটিক ()" দিয়েছিলাম)।


4
আপনি এই আউটপুটটি পাচ্ছেন কারণ আপনি Statiqueক্লাসটি লোড করে করছেন new Statique()। প্রশ্ন করা প্রশ্নে, Mnoক্লাস মোটেও বোঝা হয় না।
আরএএস

@ ফ্যাবইন, যদি আমি পরীক্ষার ক্লাসে এমএনও-র অবজেক্ট তৈরি করছি: এমএনও আনসি = নিউ এমএনও (); তবে এটির সূক্ষ্ম, তবে বর্তমান পরিস্থিতি আমি এটি করছি না, আমার সন্দেহ হ'ল যদি আমি চূড়ান্ত অপসারণ করি তবে স্থির ব্লক জরিমানা কার্যকর করে অন্যথায় এটি কার্যকর হয় না, কেন ??
স্থিতা

4
হ্যাঁ উত্তর নীচে নিখুঁত। মেইন.ক্লাসের বাইটকোডে (ম্নো.ওয়াল ব্যবহার করে), 9090 টি হার্ড কোডেড পাওয়া গেছে। চূড়ান্ত সরান, সংকলন করুন, তারপরে জাভাপ মেইন ব্যবহার করুন, আপনি গেসট্যাটিক দেখতে পাবেন # 16; // ফিল্ড স্ট্যাটিক.ওয়াল: আই । চূড়ান্ত পিছনে রাখুন, সংকলন করুন, তারপরে জাভাপ মেইন ব্যবহার করুন, আপনি শিপুশ 9090 দেখতে পাবেন
Fabyen

4
এটি মেইনক্লাসে হার্ডকোডযুক্ত থাকার কারণে ক্লাস এমএনও লোড করার কোনও কারণ নেই, সুতরাং স্থিতিশীল কোনও আরম্ভ নেই।
Fabyen

এটি দ্বিতীয় প্রশ্নের উত্তর দেয়: "প্রথমে কোন মেমরি বরাদ্দ করা হবে, স্ট্যাটিক চূড়ান্ত পরিবর্তনশীল বা স্ট্যাটিক ব্লক?" (লিক্সিকাল অর্ডার)
হউক ইঙ্গমার শ্মিত
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.