java - কেন আমার ক্ষেত্রগুলি শূন্য বা শূন্যের ডিফল্ট মানতে যখন আমার ক্লাসের কনস্ট্রাক্টরে তাদের ঘোষনা এবং আরম্ভ করেছি?




constructor field (3)

এটি হ'ল সমস্যাটি ছায়াময় হওয়ার ফল যেখানে একই ধরণের প্রশ্নের জন্য একটি প্রৌ .় প্রশ্ন এবং উত্তর হতে বোঝানো হয়।

আমি আমার ক্লাসে দুটি ক্ষেত্র সংজ্ঞায়িত করেছি, একটি রেফারেন্স টাইপের একটি এবং একটি আদিম ধরণের। ক্লাসের কনস্ট্রাক্টরে, আমি এগুলি কিছু কাস্টম মানগুলিতে আরম্ভ করার চেষ্টা করি।

আমি পরে যখন এই ক্ষেত্রগুলির মানগুলির জন্য জিজ্ঞাসা করি, তখন তারা জাভার ডিফল্ট মানগুলি নিয়ে তাদের কাছে ফিরে আসবে, রেফারেন্স টাইপের জন্য null এবং আদিম ধরণের জন্য 0 হবে। এটি কেন ঘটছে?

এখানে একটি পুনরুত্পাদনযোগ্য উদাহরণ:

public class Sample {
    public static void main(String[] args) throws Exception {
        StringArray array = new StringArray();
        System.out.println(array.getCapacity()); // prints 0
        System.out.println(array.getElements()); // prints null
    }
}

class StringArray {
    private String[] elements;
    private int capacity;
    public StringArray() {
        int capacity = 10;
        String[] elements;
        elements = new String[capacity];
    }
    public int getCapacity() {
        return capacity;
    }
    public String[] getElements() {
        return elements;
    }
}

আমি প্রত্যাশা getCapacity() 10 মানটি ফিরে আসবে এবং getElements() একটি সঠিকভাবে আরম্ভ করা অ্যারের উদাহরণটি ফিরে আসবে।


জাভা / সি / সি ++ এ ভেরিয়েবল ব্যবহারের দুটি অংশ রয়েছে। একটি হ'ল ভেরিয়েবল ঘোষণা করা এবং অন্যটি ভেরিয়েবলটি ব্যবহার করা (কোনও মান নির্ধারণ করা বা গণনায় এটি ব্যবহার করা)।

আপনি যখন কোনও ভেরিয়েবল ঘোষণা করেন আপনাকে অবশ্যই এর প্রকারটি ঘোষণা করতে হবে। সুতরাং আপনি ব্যবহার করবে

int x;   // to declare the variable
x = 7;   // to set its value

কোনও ভেরিয়েবল ব্যবহার করার সময় আপনাকে পুনরায় ঘোষণা করতে হবে না:

int x;
int x = 7;   

যদি ভেরিয়েবল একই সুযোগে থাকে তবে আপনি একটি সংকলক ত্রুটি পাবেন; তবে, আপনি যেমনটি সন্ধান করছেন, ভেরিয়েবলটি যদি অন্য কোনও স্কোপে থাকে তবে আপনি প্রথম ঘোষণাকে মুখোশ করুন।


জাভা প্রোগ্রামে সংজ্ঞায়িত সংস্থাগুলি (প্যাকেজ, প্রকার, পদ্ধতি, ভেরিয়েবল ইত্যাদি) এর names । এগুলি কোনও প্রোগ্রামের অন্যান্য অংশগুলিতে সেই সত্তাগুলি উল্লেখ করতে ব্যবহৃত হয়।

জাভা ভাষা প্রতিটি নামের জন্য একটি scope ব্যাখ্যা করে

একটি ঘোষণার সুযোগটি সেই প্রোগ্রামের অঞ্চল যেখানে ঘোষণাপত্র দ্বারা ঘোষিত সত্তা কোনও সরল নাম ব্যবহার করে উল্লেখ করা যেতে পারে তবে শর্ত থাকে (provided6.4.1)।

অন্য কথায় স্কোপ একটি সংকলন সময় ধারণা যা কোনও প্রোগ্রামের সত্তাকে উল্লেখ করার জন্য কোনও নাম কোথায় ব্যবহার করা যেতে পারে তা নির্ধারণ করে।

আপনার পোস্ট করা প্রোগ্রামটির একাধিক ঘোষণা রয়েছে। চলো আমরা শুরু করি

private String[] elements;
private int capacity;

এগুলি হল field ঘোষণাগুলি, যাকে ইনস্ট্যান্স ভেরিয়েবলও বলা হয় ie শ্রেণীর সংস্থায় ঘোষিত এক ধরণের সদস্য। জাভা ভাষার উল্লেখ উল্লেখ করে

শ্রেণীর ধরণের C (§8.1.6) দ্বারা উত্তরাধিকার সূত্রে ঘোষণা করা বা এমের উত্তরাধিকার সূত্রে সদস্যের ঘোষণার সুযোগটি কোনও নেস্টেড ধরণের ঘোষণাসহ C এর পুরো সংস্থা body

এর অর্থ আপনি সেই ক্ষেত্রগুলি উল্লেখ করতে StringArray শরীরে নাম elements এবং capacity ব্যবহার করতে পারেন।

আপনার কনস্ট্রাক্টর বডিতে দুটি প্রথম বিবৃতি

public StringArray() {
    int capacity = 10;
    String[] elements;
    elements = new String[capacity];
}

আসলে স্থানীয় পরিবর্তনশীল ঘোষণা বিবৃতি

একটি স্থানীয় পরিবর্তনশীল ঘোষণা বিবৃতি এক বা একাধিক স্থানীয় চলক নাম ঘোষণা করে।

এই দুটি বিবৃতি আপনার প্রোগ্রামে দুটি নতুন নাম পরিচয় করিয়ে দেয়। এটি ঠিক তাই ঘটে যে names নামগুলি আপনার ক্ষেত্রের মতো। আপনার উদাহরণস্বরূপ, capacity জন্য স্থানীয় পরিবর্তনশীল ঘোষণার মধ্যে একটি ইনিশিয়ালাইজার রয়েছে যা সেই স্থানীয় ভেরিয়েবলকে আরম্ভ করে , একই নামের ক্ষেত্র নয়। আপনার ক্ষেত্রের নাম capacity এর ধরণের জন্য ডিফল্ট মান থেকে শুরু করা হয়, যেমন। মান 0

elements ক্ষেত্রে কিছুটা আলাদা। স্থানীয় ভেরিয়েবল ডিক্লেয়ারেশন স্টেটমেন্টটি একটি নতুন নামের সাথে পরিচয় করিয়ে দেয় তবে অ্যাসাইনমেন্ট এক্সপ্রেশন সম্পর্কে কী বলা যায়?

elements = new String[capacity];

elements কোন সত্তাকে উল্লেখ করছে?

স্কোপ স্টেটের নিয়ম

একটি ব্লকের স্থানীয় ভেরিয়েবল ঘোষণার সুযোগ (.414.4) যেখানে ব্লকের বাকী অংশে ঘোষণাপত্রটি উপস্থিত হয় তার নিজস্ব আরম্ভকারী দিয়ে শুরু করে এবং স্থানীয় ভেরিয়েবল ঘোষণার বিবৃতিতে ডানদিকে আরও কোনও ঘোষককে অন্তর্ভুক্ত করে।

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

জাভা scope ধারণাটি প্রবর্তন করে।

কিছু ঘোষণাপত্র একই নামের আরেকটি ঘোষণার দ্বারা তাদের ক্ষেত্রের অংশে ছায়াযুক্ত হতে পারে, সেক্ষেত্রে ঘোষিত সত্তাকে উল্লেখ করার জন্য একটি সাধারণ নাম ব্যবহার করা যায় না।

(একটি সাধারণ নাম একটি একক সনাক্তকারী, উদাহরণস্বরূপ elements ।)

ডকুমেন্টেশন এছাড়াও উল্লেখ করে

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

এর অর্থ স্থানীয় ভেরিয়েবল নামযুক্ত elements ক্ষেত্রের নামযুক্ত elements চেয়ে বেশি অগ্রাধিকার নেয় takes এখনও বিক্রয়ের জন্য

elements = new String[capacity];

সুতরাং ক্ষেত্র নয়, স্থানীয় ভেরিয়েবল আরম্ভ করছে। ক্ষেত্রটি এর ধরণের জন্য ডিফল্ট মান থেকে শুরু করা হয়, যেমন। মান null

আপনার পদ্ধতির getCapacity এবং getCapacity অভ্যন্তরে, আপনি তাদের নিজ নিজ return বিবৃতিতে যে নামগুলি ব্যবহার করেন সেগুলি ক্ষেত্রগুলিকে উল্লেখ করে যেহেতু তাদের ঘোষণাগুলি প্রোগ্রামের সেই নির্দিষ্ট পয়েন্টে কেবলমাত্র সুযোগের পরিধি থাকে। যেহেতু ক্ষেত্রগুলি 0 এবং null আরম্ভ করা হয়েছিল, সেগুলি প্রত্যাবর্তিত মান।

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

public StringArray() {
    capacity = 10;
    elements = new String[capacity];
}

কনস্ট্রাক্টর পরামিতিগুলির সাথে শেডিং

উপরে বর্ণিত অবস্থার অনুরূপ, আপনার একই নামের সাথে ক্ষেত্রের ছায়াযুক্ত ফর্মাল (নির্মাণকারী বা পদ্ধতি) পরামিতি থাকতে পারে। উদাহরণ স্বরূপ

public StringArray(int capacity) {
    capacity = 10; 
}

ছায়ার বিধি রাষ্ট্র

ক্ষেত্রের একটি ঘোষণার d বা n শ্যাডো নামক আনুষ্ঠানিক প্যারামিটার, d এর পরিধি জুড়ে, n নামের অন্য যে কোনও ভেরিয়েবলের ঘোষণাপত্র যেখানে d হয় তার বিন্দুতে রয়েছে named

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

একটি যোগ্য নাম একটি নাম দিয়ে থাকে, একটি "।" টোকেন, এবং একটি সনাক্তকারী।

এই ক্ষেত্রে, আমরা উদাহরণটি পরিবর্তনশীল উল্লেখ করতে ক্ষেত্রের অ্যাক্সেস এক্সপ্রেশনটির অংশ হিসাবে প্রাথমিক অভিব্যক্তিটি এটি ব্যবহার করতে পারি। উদাহরণ স্বরূপ

public StringArray(int capacity) {
    this.capacity = 10; // to initialize the field with the value 10
    // or
    this.capacity = capacity; // to initialize the field with the value of the constructor argument
}

প্রতিটি ধরণের পরিবর্তনশীল , পদ্ধতি এবং প্রকারের জন্য শেডিং বিধি রয়েছে।

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


int capacity = 10; আপনার কনস্ট্রাক্টর একটি স্থানীয় পরিবর্তনশীল capacity ঘোষণা করছে যা শ্রেণীর ক্ষেত্রকে ছায়া দেয়।

প্রতিকারটি হ'ল int

capacity = 10;

এটি ক্ষেত্রের মান পরিবর্তন করবে। ক্লাসে অন্য ক্ষেত্রের জন্য দিতো।

আপনার আইডিই আপনাকে এই ছায়ার বিষয়ে সতর্ক করে দেয়নি?