স্থিতি সংশোধক কীভাবে এই কোডটিকে প্রভাবিত করে?


109

আমার কোডটি এখানে:

class A {
    static A obj = new A();
    static int num1;
    static int num2=0;

    private A() {
        num1++;
        num2++;
    }
    public static A getInstance() {
        return obj;
    }
}

public class Main{
    public static void main(String[] arg) {
        A obj = A.getInstance();
        System.out.println(obj.num1);
        System.out.println(obj.num2);
    }
}

আউটপুটটি 1 0কিন্তু আমি বুঝতে পারি না।

কেউ আমাকে এটা ব্যাখ্যা করতে পারেন?


10
সুন্দর প্রশ্ন! এ থেকে আমাদের কী শিখতে হবে: এটি করবেন না! ;)
isnot2bad

উত্তর:


116

জাভাতে দুটি পর্যায় অনুষ্ঠিত হয়: ১. পরিচয়, ২

  1. ভিতরে সনাক্তকরণ ফেজ সব স্ট্যাটিক ভেরিয়েবল সনাক্ত করা এবং ডিফল্ট মান সক্রিয়া করা হয়।

    সুতরাং এখন মানগুলি:
    A obj=null
    num1=0
    num2=0

  2. দ্বিতীয় ধাপ, কার্যকর , উপর থেকে নীচে শুরু হয়। জাভাতে, প্রথম স্থিতিশীল সদস্যদের থেকে ফাঁসি কার্যকর হয়।
    এখানে আপনার প্রথম স্ট্যাটিক ভেরিয়েবল static A obj = new A();, সুতরাং প্রথমে এটি সেই ভেরিয়েবলের অবজেক্ট তৈরি করবে এবং কনস্ট্রাক্টরকে কল করবে, সুতরাং এর মান num1এবং num2হয় 1
    এবং তারপরে আবার static int num2=0;মৃত্যুদন্ড কার্যকর করা হবে যা তৈরি করে num2 = 0;

এখন, ধরুন আপনার কনস্ট্রাক্টর এরকম:

 private A(){
    num1++;
    num2++;
    System.out.println(obj.toString());
 }

এটি এমন একটি নিক্ষেপ করবে NullPointerExceptionযা objএখনও পাওয়া যায়নি class A


11
আমি প্রসারিত করব: static A obj = new A();নীচের লাইনটি সরান static int num2=0;এবং আপনার 1 এবং 1 পাওয়া উচিত
থমাস

2
যা এখনও আমাকে বিভ্রান্ত করছে তা হ'ল নাম 1 এর স্পষ্ট সূচনা না থাকলেও এটি 0 (সূত্রে) সূচনা হয় 0 দিয়ে স্পষ্ট এবং অন্তর্নিহিত
সূচনাতে

@ isnot2bad "অন্তর্নিহিত সূচনা" ঘোষণার অংশ হিসাবে ঘটে। ঘোষণা কোন ব্যাপার কি আপনি তাদের উপস্থাপন অর্ডার নিয়োগ সামনে ঘটবে। A obj = new A(); int num1; int num2 = 0;এই পরিণত পরার: A obj; int num1; int num2; obj = new A(); num2 = 0;। জাভা এটি করে তাই num1, num2আপনি new A()কনস্ট্রাক্টর পৌঁছানোর সময় দ্বারা সংজ্ঞায়িত করা হয় ।
হ্যান্স জেড

31

staticভেরিয়েবল ডিক্লেয়ারেশনের ক্ষেত্রে প্রয়োগকারী যখন কী বোঝায় তা হ'ল ভেরিয়েবল একটি উদাহরণ ভেরিয়েবলের পরিবর্তে শ্রেণি পরিবর্তনশীল। অন্য কথায় ... কেবলমাত্র একটি num1ভেরিয়েবল এবং কেবল একটি num2ভেরিয়েবল।

(একদিকে: স্থিতিশীল ভেরিয়েবলটি অন্য কয়েকটি ভাষায় বৈশ্বিক চলকের মতো , এটির নাম সর্বত্র দৃশ্যমান নয় except এমনকি এটি ঘোষিত public staticহলেও, অযোগ্য নামটি কেবলমাত্র বর্তমান শ্রেণিতে বা সুপারক্লাসে ঘোষিত থাকলে তা দৃশ্যমান হয়) , বা যদি এটি স্ট্যাটিক আমদানি ব্যবহার করে আমদানি করা হয় That's তবে এটিই পার্থক্য A সত্যিকারের বিশ্বব্যাপী কোথাও যোগ্যতা ছাড়াই দৃশ্যমান))

সুতরাং যখন আপনি পড়ুন obj.num1এবং obj.num2, আপনি আসলে উল্লেখ করা হয় স্ট্যাটিক ভেরিয়েবল যার বাস্তব প্রশিক্ষণে হয় এবং । এবং একইভাবে, যখন কনস্ট্রাক্টর ইনক্রিমেন্ট হয় এবং এটি একই ভেরিয়েবলগুলি (যথাক্রমে) বৃদ্ধি করে।A.num1A.num2num1num2

আপনার উদাহরণে বিভ্রান্তিকর কুঁচকে ক্লাস ইনিশিয়েশন। স্ট্যাটিক ভেরিয়েবলগুলির প্রথমটি ডিফল্ট আরম্ভ করে এবং তারপরে ক্লাসে প্রদর্শিত ক্রম হিসাবে ঘোষিত স্ট্যাটিক ইনিশিয়ালাইজার (এবং স্ট্যাটিক ইনিশিয়ালাইজার ব্লক) কার্যকর করে একটি শ্রেণি সূচনা হয় । এই ক্ষেত্রে, আপনার এটি রয়েছে:

static A obj = new A();
static int num1;
static int num2=0;

এটি এরকম ঘটে:

  1. স্ট্যাটিকগুলি তাদের ডিফল্ট প্রাথমিক মানগুলি দিয়ে শুরু হয়; A.objহয় nullএবং A.num1/ A.num2শূন্য হয়।

  2. প্রথম ঘোষণাটি ( A.obj) একটি উদাহরণ তৈরি করে A(), এবং Aবর্ধিতকরণের জন্য A.num1এবং নির্মাণকারী A.num2। যখন ঘোষণা সম্পূর্ণ হলে, A.num1এবং A.num2উভয় 1, এবং A.objনবনির্মিত বোঝায় Aউদাহরণস্বরূপ।

  3. দ্বিতীয় ঘোষণায় ( A.num1) এর কোনও আরম্ভকারী নেই, সুতরাং A.num1পরিবর্তন হয় না।

  4. তৃতীয় ঘোষণাপত্রে ( A.num2) এর একটি ইনিশিয়ালাইজার রয়েছে যা শূন্যকে নির্ধারিত করে A.num2

সুতরাং, ক্লাস আরম্ভের শেষে, A.num1হয় 1এবং A.num2হয় 0... এবং এটিই আপনার মুদ্রণ বিবৃতিগুলি দেখায়।

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


16

1,0 সঠিক।

শ্রেণিটি লোড করা হলে সমস্ত স্থিতিশীল ডেটা ওডার দিয়ে শুরু করা হয় তারা ঘোষিত হয়। ডিফল্ট হিসাবে int 0 হয়।

  • প্রথম এ তৈরি করা হয়। num1 এবং num2 1 এবং 1 হয়ে উঠছে
  • চেয়ে static int num1;কিছুই না
  • চেয়ে static int num2=0;এই num2 0 লিখেছেন

9

এটি স্ট্যাটিক ইনিশিয়েলাইজারদের ক্রমের কারণে হয়। ক্লাসে স্ট্যাটিক এক্সপ্রেশনগুলি একটি শীর্ষ-নীচে ক্রমে মূল্যায়ন করা হয়।

প্রথম যেটিকে বলা হবে তার Aনির্মাতা, যা সেট করে num1এবং num2উভয়কে 1:

static A obj = new A();

তারপর,

static int num2=0;

বলা হয় এবং আবার num2 = 0 সেট করে।

এজন্য num11 এবং num20 হয়।

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


6

জেএলএসে একটি বিভাগ পাওয়া যাবে: .412.4.2

বিস্তারিত সূচনা প্রক্রিয়া:

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

সুতরাং তিনটি স্থিতিশীল ভেরিয়েবল একের পর এক পাঠ্যক্রম অনুসারে আরম্ভ করা হবে।

সুতরাং

static A obj = new A();
//num1 = 1, num2 = 1;
static int num1;
//this is initilized first, see below.
static int num2=0;
//num1 = 1, num2 = 0;

আমি যদি আদেশটি পরিবর্তন করি:

static int num1;
static int num2=0;
static A obj = new A();

ফলাফল হবে 1,1

নোট করুন যে এটি static int num1;কোনও পরিবর্তনশীল আরম্ভকারী নয় কারণ ( §8.3.2 ):

যদি কোনও ফিল্ড ডিক্লেয়ারারে একটি ভেরিয়েবল ইনিশিয়ালাইজার থাকে, তবে এটিতে ঘোষিত ভেরিয়েবলের কাছে একটি অ্যাসাইনমেন্ট (§15.26) শব্দার্থ রয়েছে, এবং: যদি ডিক্লেয়ারটি একটি শ্রেণি ভেরিয়েবলের (অর্থাৎ, একটি স্ট্যাটিক ক্ষেত্রের) জন্য হয়, তবে চলক আরম্ভকারীটি হয় ক্লাস আরম্ভ করা হয়, যখন মূল্যায়ন এবং অ্যাসাইনমেন্ট ঠিক একবার সঞ্চালিত

এবং ক্লাসটি তৈরি হওয়ার সাথে সাথে এই শ্রেণীর ভেরিয়েবলটি আরম্ভ করা হয়। এটি প্রথম ঘটে ( §4.12.5 )।

প্রোগ্রামের প্রতিটি ভেরিয়েবলের মানটি ব্যবহারের আগে অবশ্যই একটি মান থাকতে হবে: প্রতিটি শ্রেণি ভেরিয়েবল, উদাহরণ পরিবর্তনশীল, বা অ্যারে উপাদান তৈরি হওয়ার সাথে সাথে একটি ডিফল্ট মান দিয়ে শুরু করা হয় (§15.9, §15.10): টাইপ বাইটের জন্য, ডিফল্ট মান শূন্য, যা, (বাইট) 0 এর মান। সংক্ষিপ্ত প্রকারের জন্য, ডিফল্ট মান শূন্য, যা (সংক্ষিপ্ত) 0 এর মান। টাইপ ইন্টের জন্য, ডিফল্ট মান শূন্য, যেটি, 0 দীর্ঘ টাইপের জন্য, ডিফল্ট মান শূন্য, যে 0L হয়। টাইপ ফ্লোটের জন্য, ডিফল্ট মানটি ধনাত্মক শূন্য, অর্থাৎ 0.0f হয়। টাইপ ডাবলের জন্য, ডিফল্ট মানটি ধনাত্মক শূন্য, অর্থাৎ 0.0d হয়। টাইপ চরের জন্য, ডিফল্ট মান হ'ল শূন্য অক্ষর, অর্থাৎ '\ u0000'। টাইপ বুলিয়ানের জন্য, ডিফল্ট মানটি মিথ্যা। সমস্ত রেফারেন্স ধরণের (§4.3) জন্য, ডিফল্ট মানটি শূন্য হয়।


2

সম্ভবত এটি এটি এইভাবে ভাবতে সহায়তা করবে।

ক্লাসগুলি বস্তুর জন্য ব্লুপ্রিন্ট।

যখন তারা তাত্ক্ষণিক হয় তখন অবজেক্টের ভেরিয়েবল থাকতে পারে।

ক্লাসেও ভেরিয়েবল থাকতে পারে। এগুলি স্থির হিসাবে ঘোষণা করা হয়। সুতরাং তারা বস্তুর উদাহরণগুলির চেয়ে ক্লাসে সেট করা আছে।

আপনি কেবলমাত্র প্রত্যেকটিতে একটি অ্যাপ্লিকেশনে যে কোনও শ্রেণীর একটি থাকতে পারেন তাই এটি বিশেষত class শ্রেণীর জন্য বৈশ্বিক স্টোরেজগুলির মতো। এই স্থিতিশীল ভেরিয়েবলগুলি অবশ্যই আপনার আবেদনের যে কোনও জায়গা থেকে অ্যাক্সেস এবং সংশোধন করা যেতে পারে (ধরে নিলে তারা সর্বজনীন।

এখানে একটি "কুকুর" শ্রেণীর উদাহরণ রয়েছে যা এটি তৈরির উদাহরণগুলির সংখ্যা ট্র্যাক করতে স্থির পরিবর্তনশীল ব্যবহার করে।

"কুকুর" শ্রেণিটি মেঘ যখন অরেঞ্জ বাক্সগুলি "কুকুর" উদাহরণস্বরূপ।

কুকুরের ক্লাস

আরও পড়ুন

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

আপনি যদি কিছু ট্রিভিয়ার মতো মনে করেন তবে এই ধারণাটি প্রথম প্লেটো দ্বারা প্রবর্তিত হয়েছিল


1

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

http://www.javatpoint.com/static-keyword-in-java


0

উপরের অনেক উত্তর সঠিক are কী ঘটছে তা বোঝাতে আমি নীচে কিছু ছোট পরিবর্তন করেছি mod

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

class A {
    static A obj = new A();
    static int num1;
    static int num2;
    static {
        System.out.println("Setting num2 to 0");
        num2 = 0;
    }

    private A() {
        System.out.println("Constructing singleton instance of A");
        num1++;
        num2++;
    }

    public static A getInstance() {
        return obj;
    }
}

public class Main {

    public static void main(String[] arg) {
        A obj = A.getInstance();
        System.out.println(obj.num1);
        System.out.println(obj.num2);
    }
}

আউটপুট হয়

Constructing singleton instance of A
Setting num2 to 0
1
0

0

জাভা কোনও স্ট্যাটিক বা নন স্ট্যাটিক ডেটা সদস্যের কল না করা পর্যন্ত এটি আরম্ভ করে না তবে এটি তৈরি করে।

সুতরাং এখানে যখন num1 এবং num2 মূলত কল করা হবে তখন এটি মানগুলির সাথে আরম্ভ হবে

num1 = 0 + 1; এবং

num2 = 0;

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