JavaRush /مدونة جافا /Random-AR /التعيين والتهيئة في جافا
Viacheslav
مستوى

التعيين والتهيئة في جافا

نشرت في المجموعة

مقدمة

الغرض الرئيسي من برامج الكمبيوتر هو معالجة البيانات. لمعالجة البيانات تحتاج إلى تخزينها بطريقة أو بأخرى. أقترح أن نفهم كيفية تخزين البيانات.
التعيين والتهيئة في Java - 1

المتغيرات

المتغيرات هي الحاويات التي تخزن أي بيانات. دعونا نلقي نظرة على البرنامج التعليمي الرسمي من Oracle: الإعلان عن متغيرات الأعضاء . وفقا لهذا البرنامج التعليمي، هناك عدة أنواع من المتغيرات:
  • الحقول : المتغيرات المعلنة في الفصل؛
  • المتغيرات المحلية : المتغيرات في أسلوب أو كتلة من التعليمات البرمجية؛
  • المعلمات : المتغيرات في إعلان الطريقة (في التوقيع).
يجب أن تحتوي كافة المتغيرات على نوع متغير واسم متغير.
  • يشير نوع المتغير إلى البيانات التي يمثلها المتغير (أي البيانات التي يمكنه تخزينها). كما نعلم، يمكن أن يكون نوع المتغير بدائيًا (primitives primitives ) أو كائنًا غير بدائي (Non-primitive). مع متغيرات الكائنات، يتم وصف نوعها بواسطة فئة معينة.
  • يجب أن يكون اسم المتغير صغيرًا، في حالة الجمل. يمكنك قراءة المزيد عن التسمية في " المتغيرات:التسمية ".
أيضًا، إذا كان متغير مستوى الفصل، على سبيل المثال. هو حقل فئة، ويمكن تحديد معدل الوصول له. راجع التحكم في الوصول إلى أعضاء الفصل للحصول على مزيد من التفاصيل .

إعلان متغير

لذلك، علينا أن نتذكر ما هو المتغير. من أجل البدء في العمل مع متغير، عليك أن تعلن عنه. أولا، دعونا ننظر إلى متغير محلي. بدلًا من بيئة التطوير المتكاملة (IDE)، من أجل الراحة، سوف نستخدم الحل عبر الإنترنت من موقع تعليمي: Online IDE . لنقم بتشغيل هذا البرنامج البسيط في بيئة التطوير المتكاملة الخاصة بهم عبر الإنترنت:
public class HelloWorld{
    public static void main(String []args){
        int number;
        System.out.println(number);
    }
}
لذا، كما ترون، قمنا بتعريف متغير محلي بالاسم numberوالنوع int. نضغط على زر "تنفيذ" ونحصل على الخطأ:
HelloWorld.java:5: error: variable number might not have been initialized
        System.out.println(number);
ماذا حدث؟ لقد أعلنا عن متغير، لكننا لم نقم بتهيئة قيمته. ومن الجدير بالذكر أن هذا الخطأ لم يحدث في وقت التنفيذ (أي ليس في وقت التشغيل)، ولكن في وقت الترجمة. يتحقق المترجم الذكي مما إذا كان سيتم تهيئة المتغير المحلي قبل الوصول إليه أم لا. ولذلك تترتب على ذلك الأقوال التالية:
  • يجب ألا يتم الوصول إلى المتغيرات المحلية إلا بعد تهيئتها؛
  • لا تحتوي المتغيرات المحلية على قيم افتراضية؛
  • يتم فحص قيم المتغيرات المحلية في وقت الترجمة.
لذلك، قيل لنا أنه يجب تهيئة المتغير. تهيئة المتغير هي تعيين قيمة للمتغير. دعونا بعد ذلك معرفة ما هو ولماذا.

تهيئة المتغير المحلي

تعد تهيئة المتغيرات أحد أصعب المواضيع في Java، لأن... يرتبط ارتباطًا وثيقًا بالعمل مع الذاكرة وتنفيذ JVM ومواصفات JVM وأشياء أخرى مخيفة وصعبة بنفس القدر. ولكن يمكنك محاولة معرفة ذلك إلى حد ما على الأقل. دعنا ننتقل من البسيط إلى المعقد. لتهيئة المتغير، سوف نستخدم عامل الإسناد ونغير السطر في الكود السابق:
int number = 2;
في هذا الخيار لن يكون هناك أي أخطاء وسيتم عرض القيمة على الشاشة. ما يحدث في هذه الحالة؟ دعونا نحاول التفكير. إذا أردنا تعيين قيمة لمتغير، فإننا نريد أن يقوم هذا المتغير بتخزين قيمة. اتضح أنه يجب تخزين القيمة في مكان ما، ولكن أين؟ على القرص؟ لكن هذا بطيء جدًا وقد يفرض قيودًا علينا. لقد اتضح أن المكان الوحيد الذي يمكننا من خلاله تخزين البيانات بسرعة وكفاءة "هنا والآن" هو الذاكرة. هذا يعني أننا بحاجة إلى تخصيص بعض المساحة في الذاكرة. هذا صحيح. عند تهيئة متغير ما، سيتم تخصيص مساحة له في الذاكرة المخصصة لعملية جافا التي سيتم تنفيذ برنامجنا من خلالها. تنقسم الذاكرة المخصصة لعملية جافا إلى عدة مناطق أو مناطق. يعتمد أي منهم سيخصص مساحة على نوع المتغير الذي تم الإعلان عنه. تنقسم الذاكرة إلى الأقسام التالية: الكومة والمكدسة وغير الكومة . لنبدأ بالذاكرة المكدسة. تتم ترجمة المكدس على أنه مكدس (على سبيل المثال، كومة من الكتب). إنها بنية بيانات LIFO (آخر دخول يخرج أولاً). أي مثل كومة من الكتب. عندما نضيف إليها كتبًا، نضعها في الأعلى، وعندما نزيلها، نأخذ الكتاب العلوي (أي الذي تمت إضافته مؤخرًا). لذلك، نطلق برنامجنا. كما نعلم، يتم تنفيذ برنامج Java بواسطة JVM، أي جهاز Java الظاهري. يجب أن يعرف JVM أين يجب أن يبدأ تنفيذ البرنامج. للقيام بذلك، نعلن عن طريقة رئيسية تسمى "نقطة الدخول". للتنفيذ في JVM، يتم إنشاء مؤشر ترابط رئيسي (موضوع). عند إنشاء مؤشر ترابط، يتم تخصيص مكدس خاص به في الذاكرة. تتكون هذه المكدس من الإطارات. عند تنفيذ كل طريقة جديدة في سلسلة رسائل، سيتم تخصيص إطار جديد لها وإضافته إلى أعلى المكدس (مثل كتاب جديد في مجموعة كتب). سيحتوي هذا الإطار على إشارات إلى الكائنات والأنواع البدائية. نعم، نعم، سيتم تخزين int الخاص بنا على المكدس، لأن ... int هو نوع بدائي. قبل تخصيص إطار، يجب أن يفهم JVM ما يجب حفظه هناك. ولهذا السبب سنتلقى الخطأ "ربما لم تتم تهيئة المتغير"، لأنه إذا لم تتم تهيئته، فلن يتمكن JVM من إعداد المكدس لنا. لذلك، عند تجميع البرنامج، سيساعدنا المترجم الذكي على تجنب ارتكاب الأخطاء وكسر كل شيء. (!) من أجل الوضوح، أوصي بمقالة فائقة المخادع : " Java Stack and Heap: البرنامج التعليمي لتخصيص ذاكرة Java ". يرتبط بمقطع فيديو رائع بنفس القدر:
بعد اكتمال تنفيذ إحدى الطرق، سيتم حذف الإطارات المخصصة لهذه الطرق من مكدس مؤشر الترابط، وسيتم مسح الذاكرة المخصصة لهذا الإطار مع جميع البيانات.

تهيئة متغيرات الكائنات المحلية

دعونا نغير الكود الخاص بنا مرة أخرى إلى شيء أكثر صعوبة:
public class HelloWorld{

    private int number = 2;

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

}
ماذا سيحدث هنا؟ دعونا نتحدث عن ذلك مرة أخرى. يعرف JVM المكان الذي يجب عليه تنفيذ البرنامج منه، أي. ترى الطريقة الرئيسية. يقوم بإنشاء خيط، وتخصيص الذاكرة له (بعد كل شيء، يحتاج الخيط إلى تخزين البيانات اللازمة للتنفيذ في مكان ما). في هذا الموضوع، تم تخصيص إطار للطريقة الرئيسية. بعد ذلك نقوم بإنشاء كائن HelloWorld. لم يعد يتم إنشاء هذا الكائن على المكدس، ولكن على الكومة. لأن الكائن ليس نوعًا بدائيًا، ولكنه نوع كائن. وسوف تقوم المكدس فقط بتخزين مرجع للكائن الموجود في الكومة (يجب علينا الوصول بطريقة ما إلى هذا الكائن). بعد ذلك، في حزمة الطريقة الرئيسية، سيتم تخصيص الإطارات لتنفيذ طريقة println. بعد تنفيذ الطريقة الرئيسية، سيتم تدمير جميع الإطارات. إذا تم تدمير الإطار، سيتم تدمير كافة البيانات. لن يتم تدمير كائن الكائن على الفور. أولاً، سيتم تدمير المرجع إليه وبالتالي لن يشير أحد إلى كائن الكائن بعد الآن ولن يعد الوصول إلى هذا الكائن في الذاكرة ممكنًا. لدى JVM الذكي آليته الخاصة لهذا - جامع البيانات المهملة (جامع البيانات المهملة أو GC للاختصار). ثم يقوم بعد ذلك بإزالة الكائنات من الذاكرة التي لا يشير إليها أي شخص آخر. تم وصف هذه العملية مرة أخرى في الرابط المذكور أعلاه. حتى أن هناك فيديو مع شرح.

تهيئة الحقول

تتم تهيئة الحقول المحددة في الفصل بطريقة خاصة اعتمادًا على ما إذا كان الحقل ثابتًا أم لا. إذا كان الحقل يحتوي على الكلمة الأساسية ثابتة، فسيشير هذا الحقل إلى الفئة نفسها، وإذا لم يتم تحديد الكلمة الثابتة، فسيشير هذا الحقل إلى مثيل للفئة. دعونا ننظر إلى هذا مع مثال:
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);
    }
}
في هذا المثال، تتم تهيئة الحقول في أوقات مختلفة. ستتم تهيئة حقل الرقم بعد إنشاء كائن فئة HelloWorld. ولكن سيتم تهيئة حقل العد عندما يتم تحميل الفصل بواسطة جهاز Java الظاهري. يعد تحميل الفصل موضوعًا منفصلاً، لذا لن نخلطه هنا. من المفيد معرفة أنه تتم تهيئة المتغيرات الثابتة عندما يصبح الفصل معروفًا في وقت التشغيل. هناك شيء آخر أكثر أهمية هنا، وقد لاحظت ذلك بالفعل. لم نحدد القيمة في أي مكان، لكنها تعمل. وحقيقة. المتغيرات التي هي حقول، إذا لم يكن لها قيمة محددة، تتم تهيئتها بقيمة افتراضية. بالنسبة للقيم الرقمية، يكون هذا 0 أو 0.0 بالنسبة لأرقام الفاصلة العائمة. بالنسبة للمنطق هذا غير صحيح. وبالنسبة لجميع متغيرات نوع الكائن، ستكون القيمة فارغة (سنتحدث عن هذا لاحقًا). يبدو، لماذا هذا؟ ولكن لأنه يتم إنشاء الكائنات في الكومة (في الكومة). يتم تنفيذ العمل مع هذه المنطقة في وقت التشغيل. ويمكننا تهيئة هذه المتغيرات في وقت التشغيل، على عكس المكدس، الذي يجب تحضير الذاكرة له قبل التنفيذ. هذه هي الطريقة التي تعمل بها الذاكرة في جافا. ولكن هناك ميزة أخرى هنا. تمس هذه القطعة الصغيرة زوايا مختلفة من الذاكرة. كما نتذكر، يتم تخصيص إطار في ذاكرة المكدس للطريقة الرئيسية. يخزن هذا الإطار مرجعًا لكائن في ذاكرة الكومة. ولكن أين يتم تخزين العد بعد ذلك؟ كما نتذكر، تتم تهيئة هذا المتغير على الفور، قبل إنشاء الكائن في الكومة. هذا سؤال صعب حقا. قبل Java 8، كانت هناك منطقة ذاكرة تسمى PERMGEN. بدءًا من Java 8، تغيرت هذه المنطقة وأصبحت تسمى METASPACE. في الأساس، المتغيرات الثابتة هي جزء من تعريف الفئة، أي. البيانات الوصفية الخاصة به. ولذلك، فمن المنطقي أن يتم تخزينها في مستودع البيانات التعريفية، 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 هي مرجع خاص لا يشير إلى أي مكان وإلى أي كائن. لذلك، يمكن أن يكون متغير الكائن فقط فارغًا. الشيء الثاني المهم أن نفهمه هو أن القيمة الخالية هي مرجع. وأشير أيضا أن وزنهم. في هذا الموضوع، يمكنك قراءة السؤال حول تدفق المكدس: " هل يتطلب المتغير الفارغ مساحة في الذاكرة ".

كتل التهيئة

عند النظر في تهيئة المتغيرات، سيكون من الخطيئة عدم النظر في كتل التهيئة. تبدو هكذا:
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