JavaRush /جاوا بلاگ /Random-UR /جاوا میں تفویض اور آغاز
Viacheslav
سطح

جاوا میں تفویض اور آغاز

گروپ میں شائع ہوا۔

تعارف

کمپیوٹر پروگراموں کا بنیادی مقصد ڈیٹا پروسیسنگ ہے۔ ڈیٹا پر کارروائی کرنے کے لیے آپ کو اسے کسی نہ کسی طرح ذخیرہ کرنے کی ضرورت ہے۔ میں یہ سمجھنے کی تجویز پیش کرتا ہوں کہ ڈیٹا کو کیسے ذخیرہ کیا جاتا ہے۔
جاوا میں تفویض اور آغاز - 1

متغیرات

متغیر کنٹینرز ہیں جو کسی بھی ڈیٹا کو ذخیرہ کرتے ہیں. آئیے اوریکل سے آفیشل ٹیوٹوریل دیکھیں: ممبر متغیرات کا اعلان کرنا ۔ اس ٹیوٹوریل کے مطابق، متغیرات کی کئی اقسام ہیں:
  • فیلڈز : کلاس میں اعلان کردہ متغیر؛
  • مقامی متغیرات : کسی طریقہ یا کوڈ کے بلاک میں متغیر؛
  • پیرامیٹرز : طریقہ کے اعلان میں متغیر (دستخط میں)۔
تمام متغیرات میں متغیر کی قسم اور متغیر کا نام ہونا ضروری ہے۔
  • متغیر کی قسم بتاتی ہے کہ متغیر کس ڈیٹا کی نمائندگی کرتا ہے (یعنی یہ کون سا ڈیٹا اسٹور کر سکتا ہے)۔ جیسا کہ ہم جانتے ہیں، متغیر کی قسم پرائمیٹو (آدمی قدیم ) یا آبجیکٹ ، غیر قدیم (غیر قدیم) ہو سکتی ہے۔ آبجیکٹ متغیر کے ساتھ، ان کی قسم کو ایک مخصوص کلاس کے ذریعہ بیان کیا جاتا ہے۔
  • متغیر کا نام اونٹ کے کیس میں چھوٹے حروف میں ہونا چاہیے۔ آپ نام کے بارے میں مزید پڑھ سکتے ہیں " متغیرات: نام دینا " میں۔
نیز، اگر کلاس لیول کا متغیر، یعنی ایک کلاس فیلڈ ہے، اس کے لیے ایک رسائی موڈیفائر کی وضاحت کی جا سکتی ہے۔ مزید تفصیلات کے لیے کلاس کے اراکین تک رسائی کو کنٹرول کرنا دیکھیں ۔

متغیر اعلامیہ

تو، ہمیں یاد ہے کہ متغیر کیا ہے۔ متغیر کے ساتھ کام شروع کرنے کے لیے، آپ کو اس کا اعلان کرنا ہوگا۔ سب سے پہلے، ایک مقامی متغیر کو دیکھتے ہیں۔ IDE کے بجائے، سہولت کے لیے، ہم ٹیوٹوریل پوائنٹ سے آن لائن حل استعمال کریں گے: آن لائن IDE ۔ آئیے اس سادہ پروگرام کو ان کے آن لائن IDE میں چلائیں:
public class HelloWorld{
    public static void main(String []args){
        int number;
        System.out.println(number);
    }
}
لہذا، جیسا کہ آپ دیکھ سکتے ہیں، ہم نے نام numberاور قسم کے ساتھ ایک مقامی متغیر کا اعلان کیا ہے int۔ ہم "Execute" بٹن دباتے ہیں اور غلطی حاصل کرتے ہیں:
HelloWorld.java:5: error: variable number might not have been initialized
        System.out.println(number);
کیا ہوا؟ ہم نے متغیر کا اعلان کیا، لیکن اس کی قدر شروع نہیں کی۔ یہ بات قابل غور ہے کہ یہ ایرر ایگزیکیوشن کے وقت نہیں ہوا (یعنی رن ٹائم میں نہیں) بلکہ کمپائلیشن کے وقت۔ سمارٹ کمپائلر نے چیک کیا کہ آیا مقامی متغیر تک رسائی سے پہلے اسے شروع کیا جائے گا یا نہیں۔ لہذا، اس سے مندرجہ ذیل بیانات ہیں:
  • مقامی متغیرات کو شروع کرنے کے بعد ہی ان تک رسائی حاصل کی جانی چاہیے۔
  • مقامی متغیرات کی ڈیفالٹ اقدار نہیں ہوتی ہیں۔
  • مقامی متغیرات کی قدریں مرتب وقت پر چیک کی جاتی ہیں۔
لہذا، ہمیں بتایا گیا ہے کہ متغیر کو شروع کرنا ضروری ہے۔ متغیر کو شروع کرنا متغیر کو قدر تفویض کرنا ہے۔ آئیے پھر معلوم کریں کہ یہ کیا ہے اور کیوں۔

مقامی متغیر کو شروع کرنا

متغیرات کو شروع کرنا جاوا میں سب سے مشکل عنوانات میں سے ایک ہے، کیونکہ... میموری کے ساتھ کام کرنے، JVM کے نفاذ، JVM تفصیلات اور اسی طرح کی دیگر خوفناک اور مشکل چیزوں سے بہت گہرا تعلق ہے۔ لیکن آپ اسے کم از کم کسی حد تک معلوم کرنے کی کوشش کر سکتے ہیں۔ آئیے سادہ سے پیچیدہ کی طرف چلتے ہیں۔ متغیر کو شروع کرنے کے لیے، ہم اسائنمنٹ آپریٹر کا استعمال کریں گے اور اپنے پچھلے کوڈ میں لائن کو تبدیل کریں گے:
int number = 2;
اس آپشن میں کوئی ایرر نہیں ہوگا اور ویلیو اسکرین پر ظاہر ہوگی۔ اس معاملے میں کیا ہوتا ہے؟ آئیے استدلال کرنے کی کوشش کرتے ہیں۔ اگر ہم کسی متغیر کو ویلیو تفویض کرنا چاہتے ہیں، تو ہم چاہتے ہیں کہ وہ متغیر کسی ویلیو کو اسٹور کرے۔ معلوم ہوا کہ قدر کہیں ذخیرہ ہونی چاہیے، لیکن کہاں؟ ڈسک پر؟ لیکن یہ بہت سست ہے اور ہم پر پابندیاں عائد کر سکتا ہے۔ یہ پتہ چلتا ہے کہ واحد جگہ جہاں ہم "یہاں اور ابھی" ڈیٹا کو تیزی سے اور مؤثر طریقے سے ذخیرہ کرسکتے ہیں وہ میموری ہے۔ اس کا مطلب ہے کہ ہمیں میموری میں کچھ جگہ مختص کرنے کی ضرورت ہے۔ یہ حقیقت ہے. جب ایک متغیر شروع کیا جاتا ہے، تو اس کے لیے جاوا پروسیس کے لیے مختص کردہ میموری میں جگہ مختص کی جائے گی جس کے اندر ہمارا پروگرام چلایا جائے گا۔ جاوا عمل کے لیے مختص میموری کو کئی علاقوں یا زونز میں تقسیم کیا جاتا ہے۔ ان میں سے کون جگہ مختص کرے گا اس پر منحصر ہے کہ متغیر کو کس قسم کا اعلان کیا گیا تھا۔ میموری کو درج ذیل حصوں میں تقسیم کیا گیا ہے: ہیپ، اسٹیک اور نان ہیپ ۔ آئیے اسٹیک میموری کے ساتھ شروع کریں۔ اسٹیک کا ترجمہ اسٹیک کے طور پر کیا جاتا ہے (مثال کے طور پر، کتابوں کا ڈھیر)۔ یہ LIFO (لاسٹ ان، فرسٹ آؤٹ) ڈیٹا ڈھانچہ ہے۔ یعنی کتابوں کے ڈھیر کی طرح۔ جب ہم اس میں کتابیں شامل کرتے ہیں، تو ہم انہیں سب سے اوپر رکھتے ہیں، اور جب ہم انہیں لے جاتے ہیں، تو ہم سب سے اوپر لے جاتے ہیں (یعنی وہ جسے حال ہی میں شامل کیا گیا تھا)۔ تو ہم اپنا پروگرام شروع کرتے ہیں۔ جیسا کہ ہم جانتے ہیں، جاوا پروگرام کو JVM، یعنی ایک جاوا ورچوئل مشین کے ذریعے عمل میں لایا جاتا ہے۔ JVM کو معلوم ہونا چاہیے کہ پروگرام پر عمل کہاں سے شروع ہونا چاہیے۔ ایسا کرنے کے لیے، ہم ایک اہم طریقہ کا اعلان کرتے ہیں، جسے "انٹری پوائنٹ" کہا جاتا ہے۔ JVM میں عمل درآمد کے لیے، ایک مین تھریڈ (دھاگہ) بنایا جاتا ہے۔ جب کوئی تھریڈ بنتا ہے، تو اسے میموری میں اس کا اپنا اسٹیک مختص کیا جاتا ہے۔ یہ اسٹیک فریموں پر مشتمل ہے۔ جب ہر نئے طریقہ کو دھاگے میں انجام دیا جاتا ہے، تو اس کے لیے ایک نیا فریم مختص کیا جائے گا اور اسٹیک کے اوپری حصے میں شامل کیا جائے گا (جیسے کتابوں کے ڈھیر میں نئی ​​کتاب)۔ اس فریم میں اشیاء اور قدیم اقسام کے حوالے ہوں گے۔ ہاں، ہاں، ہمارا int اسٹیک پر محفوظ کیا جائے گا، کیونکہ... int ایک قدیم قسم ہے۔ ایک فریم مختص کرنے سے پہلے، JVM کو سمجھنا چاہیے کہ وہاں کیا بچانا ہے۔ یہ اس وجہ سے ہے کہ ہمیں غلطی موصول ہوگی "ممکنہ طور پر متغیر کو شروع نہیں کیا گیا ہے"، کیونکہ اگر اسے شروع نہیں کیا گیا ہے، تو JVM ہمارے لیے اسٹیک تیار نہیں کر سکے گا۔ لہذا، ایک پروگرام کو مرتب کرتے وقت، ایک سمارٹ کمپائلر ہمیں غلطیاں کرنے اور ہر چیز کو توڑنے سے بچنے میں مدد کرے گا۔ (!) وضاحت کے لیے، میں ایک سپر ڈوپر مضمون تجویز کرتا ہوں: " Java Stack and Heap: Java Memory Allocation Tutorial "۔ یہ مساوی طور پر ٹھنڈی ویڈیو سے لنک کرتا ہے:
طریقہ کار کے مکمل ہونے کے بعد، ان طریقوں کے لیے مختص کردہ فریموں کو تھریڈ کے اسٹیک سے حذف کر دیا جائے گا، اور ان کے ساتھ تمام ڈیٹا کے ساتھ اس فریم کے لیے مختص کردہ میموری کو بھی صاف کر دیا جائے گا۔

مقامی آبجیکٹ متغیرات کو شروع کرنا

آئیے اپنے کوڈ کو دوبارہ کچھ اور مشکل میں تبدیل کریں:
public class HelloWorld{

    private int number = 2;

    public static void main(String []args){
        HelloWorld object = new HelloWorld();
        System.out.println(object.number);
    }

}
یہاں کیا ہوگا؟ آئیے اس پر دوبارہ بات کرتے ہیں۔ JVM جانتا ہے کہ اسے پروگرام کہاں سے چلانا چاہیے، یعنی وہ اہم طریقہ دیکھتا ہے. یہ ایک تھریڈ بناتا ہے، اس کے لیے میموری مختص کرتا ہے (آخر کار، ایک تھریڈ کو کہیں پر عمل درآمد کے لیے درکار ڈیٹا کو ذخیرہ کرنے کی ضرورت ہوتی ہے)۔ اس دھاگے میں مرکزی طریقہ کے لیے ایک فریم مختص کیا گیا ہے۔ اگلا ہم ایک ہیلو ورلڈ آبجیکٹ بناتے ہیں۔ یہ شے اب اسٹیک پر نہیں بلکہ ہیپ پر بنائی گئی ہے۔ کیونکہ آبجیکٹ ایک قدیم قسم نہیں ہے بلکہ ایک آبجیکٹ کی قسم ہے۔ اور اسٹیک صرف ڈھیر میں آبجیکٹ کا حوالہ محفوظ کرے گا (ہمیں کسی نہ کسی طرح اس آبجیکٹ تک رسائی حاصل کرنی ہوگی)۔ اس کے بعد، مرکزی طریقہ کے اسٹیک میں، پرنٹ ایل این طریقہ کو انجام دینے کے لیے فریم مختص کیے جائیں گے۔ اہم طریقہ پر عمل کرنے کے بعد، تمام فریم تباہ ہو جائیں گے. اگر فریم تباہ ہو جائے تو تمام ڈیٹا تباہ ہو جائے گا۔ آبجیکٹ آبجیکٹ کو فوری طور پر تباہ نہیں کیا جائے گا۔ سب سے پہلے اس کا حوالہ ختم ہو جائے گا اور اس طرح اب کوئی بھی آبجیکٹ آبجیکٹ کا حوالہ نہیں دے گا اور میموری میں اس آبجیکٹ تک رسائی ممکن نہیں رہے گی۔ اس کے لیے ایک سمارٹ JVM کا اپنا طریقہ کار ہوتا ہے - ایک کوڑا اٹھانے والا (کوڑا اٹھانے والا یا مختصر طور پر GC)۔ اس کے بعد یہ میموری اشیاء سے ہٹاتا ہے جس کا کوئی اور حوالہ نہیں دیتا ہے۔ اس عمل کو دوبارہ اوپر دیئے گئے لنک میں بیان کیا گیا تھا۔ یہاں تک کہ وضاحت کے ساتھ ایک ویڈیو بھی ہے۔

فیلڈز کو شروع کرنا

کلاس میں مخصوص فیلڈز کی شروعات ایک خاص طریقے سے ہوتی ہے اس پر منحصر ہے کہ آیا فیلڈ جامد ہے یا نہیں۔ اگر کسی فیلڈ میں کلیدی لفظ static ہے، تو اس فیلڈ سے مراد خود کلاس ہے، اور اگر لفظ static کی وضاحت نہیں کی گئی ہے، تو اس فیلڈ سے مراد کلاس کی ایک مثال ہے۔ آئیے اس کو ایک مثال سے دیکھتے ہیں:
public class HelloWorld{
    private int number;
    private static int count;

    public static void main(String []args){
        HelloWorld object = new HelloWorld();
        System.out.println(object.number);
    }
}
اس مثال میں، فیلڈز کو مختلف اوقات میں شروع کیا جاتا ہے۔ ہیلو ورلڈ کلاس آبجیکٹ بننے کے بعد نمبر فیلڈ کو شروع کیا جائے گا۔ لیکن کاؤنٹ فیلڈ اس وقت شروع کی جائے گی جب جاوا ورچوئل مشین کے ذریعے کلاس کو لوڈ کیا جائے گا۔ کلاس لوڈنگ ایک الگ موضوع ہے، اس لیے ہم اسے یہاں نہیں ملاتے۔ یہ جاننے کے قابل ہے کہ جامد متغیرات شروع کیے جاتے ہیں جب کلاس رن ٹائم پر جانا جاتا ہے۔ یہاں کچھ اور اہم ہے، اور آپ نے اسے پہلے ہی محسوس کیا ہے۔ ہم نے کہیں بھی قدر کی وضاحت نہیں کی، لیکن یہ کام کرتا ہے۔ اور بے شک۔ متغیرات جو کہ فیلڈز ہیں، اگر ان کی کوئی قدر متعین نہیں ہے، تو وہ پہلے سے طے شدہ قدر کے ساتھ شروع کی جاتی ہیں۔ عددی اقدار کے لیے یہ فلوٹنگ پوائنٹ نمبرز کے لیے 0 یا 0.0 ہے۔ بولین کے لیے یہ غلط ہے۔ اور تمام آبجیکٹ قسم کے متغیرات کے لیے ویلیو null ہو جائے گی (ہم اس کے بارے میں بعد میں بات کریں گے)۔ ایسا لگتا ہے، ایسا کیوں ہے؟ لیکن کیونکہ اشیاء ہیپ (ڈھیر میں) میں بنتی ہیں۔ اس علاقے کے ساتھ کام رن ٹائم میں کیا جاتا ہے۔ اور ہم ان متغیرات کو رن ٹائم پر شروع کر سکتے ہیں، اسٹیک کے برعکس، میموری جس کے لیے عملدرآمد سے پہلے تیار ہونا ضروری ہے۔ جاوا میں میموری اس طرح کام کرتی ہے۔ لیکن یہاں ایک اور خصوصیت ہے۔ یہ چھوٹا سا ٹکڑا میموری کے مختلف گوشوں کو چھوتا ہے۔ جیسا کہ ہمیں یاد ہے، اسٹیک میموری میں مرکزی طریقہ کے لیے ایک فریم مختص کیا گیا ہے۔ یہ فریم ہیپ میموری میں کسی چیز کا حوالہ محفوظ کرتا ہے۔ لیکن پھر شمار کہاں محفوظ ہے؟ جیسا کہ ہمیں یاد ہے، یہ متغیر فوری طور پر شروع کیا جاتا ہے، اس سے پہلے کہ ہیپ میں آبجیکٹ بن جائے۔ یہ واقعی ایک مشکل سوال ہے۔ جاوا 8 سے پہلے، ایک میموری ایریا تھا جسے PERMGEN کہا جاتا تھا۔ جاوا 8 سے شروع کرتے ہوئے، یہ علاقہ بدل گیا ہے اور اسے METASPACE کہا جاتا ہے۔ بنیادی طور پر، جامد متغیرات کلاس کی تعریف کا حصہ ہیں، یعنی اس کا میٹا ڈیٹا۔ لہذا، یہ منطقی ہے کہ یہ میٹا ڈیٹا ریپوزٹری، METASPACE میں محفوظ ہے۔ میٹا اسپیس کا تعلق اسی نان ہیپ میموری ایریا سے ہے اور یہ اس کا حصہ ہے۔ یہ بھی ذہن میں رکھنا ضروری ہے کہ جس ترتیب میں متغیرات کا اعلان کیا جاتا ہے اسے مدنظر رکھا جاتا ہے۔ مثال کے طور پر، اس کوڈ میں ایک خرابی ہے:
public class HelloWorld{

    private static int b = a;
    private static int a = 1;

    public static void main(String []args){
        System.out.println(b);
    }

}

کالعدم کیا ہے۔

جیسا کہ اوپر بتایا گیا ہے، آبجیکٹ کی قسموں کے متغیرات، اگر وہ کسی کلاس کے فیلڈز ہیں، تو ڈیفالٹ ویلیو میں شروع کیے جاتے ہیں اور وہ ڈیفالٹ ویلیو null ہے۔ لیکن جاوا میں null کیا ہے؟ یاد رکھنے کی پہلی چیز یہ ہے کہ قدیم قسمیں کالعدم نہیں ہوسکتی ہیں۔ اور سب اس لیے کہ null ایک خاص حوالہ ہے جو کہیں بھی، کسی بھی چیز کا حوالہ نہیں دیتا۔ لہذا، صرف ایک آبجیکٹ متغیر null ہو سکتا ہے. دوسری چیز جو سمجھنا ضروری ہے وہ یہ ہے کہ null ایک حوالہ ہے۔ میرا حوالہ بھی ان کا وزن ہے۔ اس موضوع پر، آپ اسٹیک اوور فلو پر سوال پڑھ سکتے ہیں: " کیا null متغیر کو میموری میں جگہ کی ضرورت ہوتی ہے

ابتدائی بلاکس

متغیرات کی ابتداء پر غور کرتے وقت، ابتدائی بلاکس پر غور نہ کرنا گناہ ہوگا۔ ایسا لگتا ہے:
public class HelloWorld{

    static {
        System.out.println("static block");
    }

    {
        System.out.println("block");
    }

    public HelloWorld () {
        System.out.println("Constructor");
    }

    public static void main(String []args){
        HelloWorld obj = new HelloWorld();
    }

}
آؤٹ پٹ آرڈر ہو گا: سٹیٹک بلاک، بلاک، کنسٹرکٹر۔ جیسا کہ ہم دیکھ سکتے ہیں، کنسٹرکٹر سے پہلے ابتدائی بلاکس کو پھانسی دی جاتی ہے۔ اور بعض اوقات یہ ابتدا کا ایک آسان ذریعہ ہوسکتا ہے۔

نتیجہ

مجھے امید ہے کہ یہ مختصر جائزہ کچھ بصیرت فراہم کرنے میں کامیاب رہا ہے کہ یہ کیسے کام کرتا ہے اور کیوں۔ #ویاچسلاو
تبصرے
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION