একটি স্ট্যাটিক এবং একটি অ স্ট্যাটিক সূচনা কোড ব্লকের মধ্যে পার্থক্য কী


357

আমার প্রশ্নটি স্থির কীওয়ার্ডের একটি বিশেষ ব্যবহার সম্পর্কে। staticকোনও ক্লাসের মধ্যে কোনও কোড ব্লকটি coverাকতে কীওয়ার্ড ব্যবহার করা সম্ভব যা কোনও ফাংশনের সাথে সম্পর্কিত নয়। উদাহরণস্বরূপ নিম্নলিখিত কোড সংকলন:

public class Test {
    private static final int a;    
    static {
        a = 5;
        doSomething(a);
    }
    private static int doSomething(int x) {
        return (x+5);
    }
}

আপনি মুছে ফেলেন staticশব্দ এটা অভিযোগ কারণ পরিবর্তনশীল aহয় final। তবে উভয় finalএবং staticকীওয়ার্ড মুছে ফেলা এবং এটি সংকলন করা সম্ভব।

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

উত্তর:


403

স্ট্যাটিক মডিফায়ার সহ কোড ব্লক একটি শ্রেণি সূচককে বোঝায় ; স্ট্যাটিক মডিফায়ার ছাড়াই কোড ব্লক হ'ল একটি ইনস্ট্যান্সিমাইজার izer

শ্রেণি প্রবর্তকগুলি শ্রেণিটি লোড হওয়ার পরে (নীচে, কেবল সাধারণ পরিবর্তনশীল আরম্ভকারীদের মতো) সংজ্ঞায়িত ক্রমে কার্যকর করা হয় (আসলে, যখন এটি সমাধান হয় তবে এটি প্রযুক্তিগত)।

ক্লাস তাত্ক্ষণিকভাবে নির্ধারিত ক্রমে ইনস্ট্যান্স ইনিশিয়ালাইজারগুলি নির্বাহ করা হয়, সুপার কনস্ট্রাক্টরের অনুরোধের সাথে সাথেই কনস্ট্রাক্টর কোডটি কার্যকর করার আগেই।

আপনি যদি এখান staticথেকে সরিয়ে থাকেন তবে int aএটি একটি পরিবর্তনশীল হয়ে যায়, যা আপনি স্ট্যাটিক আরম্ভকারী ব্লক থেকে অ্যাক্সেস করতে সক্ষম নন। এটি ত্রুটিটি "অ স্থিতিশীল ভেরিয়েবল এ স্থির প্রসঙ্গ থেকে রেফারেন্স করা যায় না" দিয়ে সংকলন করতে ব্যর্থ হবে।

আপনি যদি staticআরম্ভকারী ব্লক থেকেও সরিয়ে থাকেন তবে এটি পরে ইনসেন্ট ইনিশিয়ালাইজার হয়ে যায় এবং তাই int aএটি নির্মাণে আরম্ভ হয়।


স্ট্যাটিক ইনিশিয়ালাইজারটি আসলে ক্লাসটি আরম্ভ করার পরে, যখন এটি লোড করা এবং সংযুক্ত হওয়ার পরে ডাকা হয়। আপনি যখন ক্লাসের কোনও অবজেক্ট ইনস্ট্যান্ট করেন বা ক্লাসে একটি স্ট্যাটিক ভেরিয়েবল বা পদ্ধতি অ্যাক্সেস করেন তখন তা ঘটে। বাস্তবে আপনার যদি স্ট্যাটিক ইনিশিয়ালাইজার এবং একটি পদ্ধতি সহ একটি ক্লাস public static void staticMethod(){}থাকে, যদি আপনি নির্বাহ করেন TestStatic.class.getMethod("staticMethod");। স্ট্যাটিক ইনিশিয়ালাইজারটি চাওয়া হবে না। এখানে আরও তথ্য docs.oracle.com/javase/specs/jvms/se10/html/...
Toto

@ টোটো: হ্যাঁ, ক্লাসের রেজোলিউশনে এটিই অন্তর্ভুক্ত ছিল (কমপক্ষে তারা এটিকে লিংকটি + ইন হিসাবে "রেজোলিউশন" হিসাবে উল্লেখ করত যখন ফিরে আসবে)। আমি বিস্মিত না আপনি কিছু আবিষ্কার প্রতিফলন ব্যবহার করতে পারেন সম্পর্কে এটা মীমাংসা না করে একটি বর্গ।
লরেন্স ডল

166

Uff! স্ট্যাটিক ইনিশিয়ালাইজার কী?

স্ট্যাটিক ইনিশিয়ালাইজারটি static {}জাভা ক্লাসের অভ্যন্তরে কোডের একটি ব্লক এবং কনস্ট্রাক্টর বা মূল পদ্ধতি বলার আগে কেবল একবারে চালানো হয়।

ঠিক আছে! আমাকে আরো বল...

  • static { ... }কোনও জাভা ক্লাসের ভিতরে কোডের একটি ব্লক । এবং ক্লাস বলা হয় যখন ভার্চুয়াল মেশিন দ্বারা চালিত।
  • কোনও returnবিবৃতি সমর্থন করা হয় না।
  • কোন যুক্তি সমর্থন করা হয় না।
  • না thisবা superসমর্থিত।

হুম আমি কোথায় এটি ব্যবহার করতে পারি?

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

শুধু ছাল না! উদাহরণ কোথায়?

package com.example.learnjava;

import java.util.ArrayList;

public class Fruit {

    static {
        System.out.println("Inside Static Initializer.");

        // fruits array
        ArrayList<String> fruits = new ArrayList<>();
        fruits.add("Apple");
        fruits.add("Orange");
        fruits.add("Pear");

        // print fruits
        for (String fruit : fruits) {
            System.out.println(fruit);
        }
        System.out.println("End Static Initializer.\n");
    }

    public static void main(String[] args) {
        System.out.println("Inside Main Method.");
    }
}

আউটপুট ???

স্ট্যাটিক ইনিশিয়ালাইজারের ভিতরে।

আপেল

কমলা

নাশপাতি

শেষ স্ট্যাটিক ইনিশিয়ালাইজার।

মেন মেথডের ভিতরে।

আশাকরি এটা সাহায্য করবে!


ধন্যবাদ মদন! স্ট্যাটিক ব্লক পরিবর্তে ব্যবহার করা যেতে পারে afterPropertiesSet()এর InitializingBean?
আলেকজান্ডার সুর্যাপেল

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

57

staticব্লক একটি "স্ট্যাটিক সূচনাকারী" হয়।

শ্রেণিটি লোড হয়ে গেলে এটি স্বয়ংক্রিয়ভাবে আহ্বান জানানো হয় এবং এটিকে আহ্বান করার কোনও উপায় নেই (এমনকি প্রতিচ্ছবি দ্বারাও নয়)।

আমি জেএনআই কোড লেখার সময় ব্যক্তিগতভাবে কেবল এটি ব্যবহার করেছি:

class JNIGlue {
    static {
        System.loadLibrary("foo");
    }
}

6
নাহ, এটি আহ্বান করার কোনও সুস্পষ্ট উপায় নয়, শ্রেণি শুরুর দিকটি কখনই কোনও Methodউদাহরণ দ্বারা প্রতিনিধিত্ব করা হয় না তবে কেবল জাভা ভার্চুয়াল মেশিন দ্বারা ডাকে ।
রাফায়েল শীতকালীন

46

এটি সরাসরি http://www.programcreek.com/2011/10/java-class-instance-initializer/ থেকে এসেছে

1. কার্যকর করার আদেশ

নিম্নলিখিত শ্রেণীর দিকে তাকান, আপনি কি জানেন যে কোনটি প্রথমে মৃত্যুদন্ড কার্যকর করা হয়?

public class Foo {

    //instance variable initializer
    String s = "abc";

    //constructor
    public Foo() {
        System.out.println("constructor called");
    }

    //static initializer
    static {
        System.out.println("static initializer called");
    }

    //instance initializer
    {
        System.out.println("instance initializer called");
    }

    public static void main(String[] args) {
        new Foo();
        new Foo();
    }
}

আউটপুট:

স্ট্যাটিক ইনিশিয়ালাইজার বলা হয়

উদাহরণস্বরূপ আরম্ভকারী বলা হয়

কনস্ট্রাক্টর ডেকে আনে

উদাহরণস্বরূপ আরম্ভকারী বলা হয়

কনস্ট্রাক্টর ডেকে আনে

২. জাভা দৃষ্টান্তের আরম্ভকারী কীভাবে কাজ করে?

উপরের উদাহরণের সূচনাতে মুদ্রণ বিবৃতি রয়েছে। এটি কীভাবে কাজ করে তা বোঝার জন্য, আমরা এটিকে একটি পরিবর্তনশীল অ্যাসাইনমেন্ট স্টেটমেন্ট, যেমন,, হিসাবে বিবেচনা করতে পারি b = 0। এটি এটি আরও স্পষ্ট করে বুঝতে পারে।

পরিবর্তে

int b = 0, আপনি লিখতে পারে

int b;
b = 0;

অতএব, উদাহরণের সূচনা এবং উদাহরণ পরিবর্তনশীল আরম্ভকারীগুলি বেশ একই রকম।

৩. উদাহরণস্বরূপ আরম্ভকারীরা কখন কার্যকর হয়?

উদাহরণস্বরূপ ইনিশিয়ালাইজারগুলির ব্যবহার বিরল, তবে তবুও এটি উদাহরণ পরিবর্তনশীল ইনিশিয়ালাইজারগুলির দরকারী বিকল্প হতে পারে যদি:

  1. প্রারম্ভক কোডটি অবশ্যই ব্যতিক্রমগুলি পরিচালনা করবে
  2. হিসাব সম্পাদন করুন যা উদাহরণের পরিবর্তনশীল আরম্ভকারী দিয়ে প্রকাশ করা যায় না।

অবশ্যই, এই জাতীয় কোড কনস্ট্রাক্টরগুলিতে লেখা যেতে পারে। তবে যদি কোনও শ্রেণীর একাধিক কনস্ট্রাক্টর থাকে তবে আপনাকে প্রতিটি কনস্ট্রাক্টরে কোডটি পুনরাবৃত্তি করতে হবে।

উদাহরণস্বরূপ ইনিশিয়ালাইজারের সাহায্যে আপনি একবারে কোডটি লিখতে পারেন, এবং নির্ধারকটি তৈরির জন্য কোন বস্তু তৈরির জন্য নির্ধারিত হবে তা নির্বাহ করা হবে। (আমার ধারণা এটি কেবল একটি ধারণা এবং এটি প্রায়শই ব্যবহৃত হয় না))

আর একটি ক্ষেত্রে যার উদাহরণস্বরূপ আরম্ভকারীরা দরকারী তা বেনামে অভ্যন্তরীণ শ্রেণি, যা কোনও নির্মাতাকেই ঘোষণা করতে পারে না। (লগিং ফাংশন রাখার জন্য এটি কি ভাল জায়গা হবে?)

ধন্যবাদ ডেরহেইনকে।

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


12

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


8

আপনি কোনও স্থিতিশীল ব্লকে কোড লিখবেন না যা আপনার প্রোগ্রামের যে কোনও জায়গায় ডাকা উচিত। কোডটির উদ্দেশ্যটি যদি চাওয়া হয় তবে আপনাকে অবশ্যই এটি একটি পদ্ধতিতে স্থাপন করতে হবে।

ক্লাসটি লোড হয়ে গেলে আপনি স্ট্যাটিক ভেরিয়েবল শুরু করতে স্ট্যাটিক ইনিশিয়ালাইজার ব্লক লিখতে পারেন তবে এই কোডটি আরও জটিল হতে পারে ..

কোনও স্ট্যাটিক ইনিশিয়ালাইজার ব্লক কোনও পদ্ধতির মতো দেখায় যার নাম নেই, কোনও আর্গুমেন্ট নেই এবং কোনও রিটার্ন টাইপ নেই। যেহেতু আপনি কখনই এটি কল করেন না এটির কোনও নামের প্রয়োজন নেই। যখন ভার্চুয়াল মেশিনটি ক্লাসটি লোড করে তখন কেবলমাত্র এটির নাম।


6

যখন কোনও বিকাশকারী ইনিশিয়ালার ব্লক ব্যবহার করেন, জাভা সংকলক প্রারম্ভিককে বর্তমান বর্গের প্রতিটি নির্মাণকারীর মধ্যে অনুলিপি করে।

উদাহরণ:

নিম্নলিখিত কোড:

class MyClass {

    private int myField = 3;
    {
        myField = myField + 2;
        //myField is worth 5 for all instance
    }

    public MyClass() {
        myField = myField * 4;
        //myField is worth 20 for all instance initialized with this construtor
    }

    public MyClass(int _myParam) {
        if (_myParam > 0) {
            myField = myField * 4;
            //myField is worth 20 for all instance initialized with this construtor
            //if _myParam is greater than 0
        } else {
            myField = myField + 5;
            //myField is worth 10 for all instance initialized with this construtor
            //if _myParam is lower than 0 or if _myParam is worth 0
        }
    }

    public void setMyField(int _myField) {
        myField = _myField;
    }


    public int getMyField() {
        return myField;
    }
}

public class MainClass{

    public static void main(String[] args) {
        MyClass myFirstInstance_ = new MyClass();
        System.out.println(myFirstInstance_.getMyField());//20
        MyClass mySecondInstance_ = new MyClass(1);
        System.out.println(mySecondInstance_.getMyField());//20
        MyClass myThirdInstance_ = new MyClass(-1);
        System.out.println(myThirdInstance_.getMyField());//10
    }
}

সমান:

class MyClass {

    private int myField = 3;

    public MyClass() {
        myField = myField + 2;
        myField = myField * 4;
        //myField is worth 20 for all instance initialized with this construtor
    }

    public MyClass(int _myParam) {
        myField = myField + 2;
        if (_myParam > 0) {
            myField = myField * 4;
            //myField is worth 20 for all instance initialized with this construtor
            //if _myParam is greater than 0
        } else {
            myField = myField + 5;
            //myField is worth 10 for all instance initialized with this construtor
            //if _myParam is lower than 0 or if _myParam is worth 0
        }
    }

    public void setMyField(int _myField) {
        myField = _myField;
    }


    public int getMyField() {
        return myField;
    }
}

public class MainClass{

    public static void main(String[] args) {
        MyClass myFirstInstance_ = new MyClass();
        System.out.println(myFirstInstance_.getMyField());//20
        MyClass mySecondInstance_ = new MyClass(1);
        System.out.println(mySecondInstance_.getMyField());//20
        MyClass myThirdInstance_ = new MyClass(-1);
        System.out.println(myThirdInstance_.getMyField());//10
    }
}

আমি আশা করি আমার উদাহরণটি বিকাশকারীরা বুঝতে পেরেছেন।


4

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


ফলোআপ হিসাবে, যদি আমি অবজেক্টটির কোনও উদাহরণ তৈরি না করি তবে পরিবর্তে আমি একটি পাবলিক স্ট্যাটিক ফাংশন বলি। এটি কি বোঝায় যে এই ব্লকটি এই সর্বজনীন ফাংশন কলের আগে সম্পাদন করার গ্যারান্টিযুক্ত? ধন্যবাদ।
Szere Dyeri

আপনি যদি ক্লাসের সর্বজনীন স্ট্যাটিক ফাংশনটিকে কল করেন তবে ক্লাসটি প্রথমে লোড করা দরকার, তাই হ্যাঁ, স্ট্যাটিক ইনিশিয়ালাইজার প্রথমে কার্যকর করবে।
পল টমলিন

যদি না এটি শ্রেণি সূচনা হয় যা (পরোক্ষভাবে) কোডটি বলে যা এটি ব্যবহারের চেষ্টা করছে। IFYSWIM। বিজ্ঞপ্তি নির্ভরতা এবং সমস্ত।
টম হাটিন - ২১ শে

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