مقدمة من أكاديمية حسوب
دورة تطوير التطبيقات باستخدام لغة JavaScript
في هذه الدورة ستتعلم لغة جافا سكريبت, استخدام مكتبة React.js, بناء API الموقع بواسطة Node.js, تطوير تطبيق جوال باستخدام React Native, و في نهاية الدورة ستتعلم تطوير تطبيق محادثة شبيه بتطبيق WhatsApp.
دورة تطوير واجهات المستخدم
في هذه الدورة ستتعلم لغة HTML و لغة CSS و لغة JavaScript. من ناحية التطبيق العملي ستتعلم طريقة بناء واجهة متجر إلكتروني مكون من ست صفحات, تحويل خمسة تصاميم PSD إلى صفحات ويب, بناء واجهة مستخدم تشبه موقع يوتيوب, بناء لوحة تحكم إحترافية.
دورة تطوير تطبيقات الجوال باستخدام تقنيات الويب
في هذه الدورة ستتعلم أساسيات منصة كوردوفا و كيف تستخدمها لتطوير تطبيقات متعددة المنصات, بناء تطبيق لموقع Wordpress, تطوير تطبيق قائمة مهام, تطوير تطبيق حالة الطقس, تطوير تطبيق لمطعم باستخدام إطار العمل Ionic 4.
دورة تطوير تطبيقات الويب باستخدام لغة PHP
في هذه الدورة ستتعلم لغة PHP من الصفر, استخدام إطار العمل Laravel بشرح مفصّل و عملي, كيفية تطوير شبكة اجتماعية تشبه Instagram, بناء API لتطبيق جوال وفق أسلوب RESTful, تطوير موقع إعلانات مبوبة, تطوير نظام إدارة محتوى CMS كامل.
دورة تطوير تطبيقات الويب باستخدام لغة Ruby
في هذه الدورة ستتعلم البرمجة بلغة Ruby إنطلاقاً من أبسط المفاهيم وحتى بناء تطبيق حقيقي, إستخدام إطار العمل Ruby on Rails بشرح مفصّل و عملي, بناء تطبيق حقيقي عبارة عن شبكة اجتماعية تشبه تويتر, تطوير مجتمع الكتروني يشبه حسوب I/O.
دورة علوم الحاسوب
هذه الدورة معدة لتكون مدخل لعلوم الحاسوب و لغات البرمجة حيث ستتعرف فيها على أنظمة التشغيل و ستتعمق في نظام لينكس و في كيفية التعامل معه من خلال موجه الأوامر, بالإضافة إلى قواعد البيانات و أساسيات الشبكات و الخوادم و مبادئ الحماية والأمان في الويب.

أنواع المراجع في لغة جافا

لغة جافا هي لغة كائنية التوجه (Object Oriented Programming) تسمح بإنشاء الكائنات و التعامل معها و كأنها نوع بيانات (Data Type) جديد.

الكائنات في جافا يتم إنشاءها بإستخدام الكلمة المفتاحية new التي تقوم بحجز مكان لها في الذاكرة (RAM) و تحديداً في المساحة التي تسمى Heap.

البرنامج بدوره يمتلك مراجع (References) للكائنات التي يتم تخزينها في الـHeap بحيث يستطيع الوصول إليها من خلالها.

في هذا المقال سنتعرف على المراجع و أنواعها و طريقة عملها.

 

مفهوم المراجع و طريقة عملها

المراجع تستخدم للإشارة للكائنات الموجودة في الـ Heap و هي شبيهة بالمؤشرات (Pointers) في لغة C فهي تقوم فقط بتخزين عنوان الكائن في الذاكرة و ليس بيانات الكائن نفسه.

في المثال التالي p يعتبر مرجع للكائن Player الذي تم إنشاؤه في الذاكرة.

Player p = new Player();

بالطبع من خلال المرجع p يمكننا التعامل مع الكائن الموجود في الذاكرة.

ملاحظة: في الشروحات نقول عادةً الكائن p بهدف أن يكون الشرح أسهل و غير معقد و لكن فعلياً p هو مجرد مرجع للكائن الموجود في الذاكرة.

القيمة الإفتراضية لأي مرجع هي null فمثلاً اذا قمت بتعريف الكائن فقط بدون تخزين كائن موجود في الذاكرة فيه فإن قيمته ستكون null لأنه لا يشير لأي شيء في الذاكرة. و بالتالي في حال حاولت إستدعاء دالة أو متغير منه سيتم رمي الإستثناء NullPointerException كما سيحدث في المثال التالي.

public static void main(String[] args){
    Player p = new Player("Waleed");
    p.score = 0;
	
    Player reference = p;  // p يشير لنفس الكائن الذي يشير له المرجع  reference هنا قمنا بجعل
    p.score = 20;          // p من خلال المرجع score هنا قمنا بتغيير قيمة المتغير
    
    System.out.println(reference.score);  // reference من خلال المرجع score هنا قمنا بعرض قيمة المتغير
}

يمكن التأكد من أن مرجعان يشيران لنفس الكائن من خلال عامل المساواة المزدوجة == كالتالي.

public static void main(String[] args) {
    Player p = new Player("Waleed");
	
    Player reference = p;  // p يشير لنفس الكائن الذي يشير له المرجع  reference هنا قمنا بجعل
    
    System.out.println(p == reference);  // reference يساوي المرجع الذي يشير له p لأن المرجع الذي يشير له true هنا سيتم طباعة
}

 

الفرق بين المراجع و الأنواع البدائية

بعد أن تحدثنا عن مراجع الكائنات لا بد من التحدث عن الفرق بينها وبين أنواع البيانات البدائية (Primitive Types).

بدايةً أنواع البيانات البدائية ليست كائنات – و لذلك لا تُعد لغة جافا كائنية بالكامل – حيث أنه عند تخزين قيمة بدائية في متغير سيقوم المتغير بحفظ قيمتها مباشرةً, و لا يمكن تخزين القيمة null في متغير.

المصفوفات في لغة جافا بشكل عام تعتبر كائنات حتى لو كانت تخزن بيانات بدائية.

 

أنواع المراجع

1- المراجع القوية (Strong References)

تعد أقوى المراجع, و هي التي نستخدمها في العادة.

تعد قوية لأن جامع القمامة لا يمكنه إزالة الكائن من الـHeap إن كان هناك أي مرجع قوي يشير له, فالمرجع القوي يعني أن الكائن مهم جداً حتى يعمل البرنامج بالشكل الصحيح.

منذ قليل عرفنا كيف يمكننا تخزين مراجع للكائنات و لكن كيف نزيل هذه المراجع؟

  • عند إسناد null لمرجع سيتم مسح عنوان الكائن الذي يشير إليه.
  • عن تعريف المرجع الذي يشير لكائن كمرجع محلي (Local), أي عند تعريفه بداخل بلوك (أي الكود القابل للتنفيذ و المحصور بين القوسين {} مثل الدوال و جمل if و for و while إلخ, و لا يعتبر الكلاس بلوك) لأنه بمجرد إنتهاء الأوامر الموجودة في البلوك سيتم حذفه بشكل تلقائي.
  • في حال كان المرجع الخاص بالكائن موضوع بداخل كائن آخر كحقل (Field أو Attribute) و قام جامع القمامة بإزالة الكائن الأساسي من الذاكرة سيتم إزالة المرجع معه أيضاً.

إذا بعد إزالة جميع المراجع القوية للكائن سيتم إزالة ذلك الكائن من الـHeap, و لكن هناك حالة شاذة لهذه القاعدة و هي أن يكون هناك كائنان (أو أكثر) لهما حقلان يحويان على مرجعين لبعضهما, فهنا إن لم يعد البرنامج يملك مرجعاً لأي من هذين الكائنين سيتم إزالتهما معاً, و تسمى هذه الحالة Circular Reference.

مثال يوضح كيف تنطبق الحالة على الكائنين x و y:

class X {
    Y y;
}

class Y {
    X x;
}

public class Test{
    public static void main(String[] args) {
        Y y = new Y();
        X x = new X();
        y.x = x;
        x.y = y;
        y = null;
        x = null;
        System.out.println("Now we don't have any reference to x and y and they could be removed");
    }
}

 

2- المراجع اللينة (Soft References)

تستخدم هذه المراجع للإشارة للكائنات بليونة, و يعني ذلك أن جامع القمامة قد يزيل الكائن (إن لم يكن هناك أي مرجع قوي يشير له) حتى و إن كان يوجد مرجع ليّن يشير له.

في العادة يبقي جامع القمامة على الكائنات التي يشار إليها من مراجع لينة حتى تمتلئ الذاكرة, و بدلاً من إطلاق الخطأ OutOfMemoryError بسبب إمتلاء الذاكرة سيحاول قبلها مسح الكائنات التي تشير إليها المراجع اللينة مع الإشارة إلى أنه لن يمسحها في حال كان يوجد مراجع قوية تشير لنفس الكائنات المشار إليها بواسطة المراجع الليّنة.

يتم إنشاء مرجع ليّن من خلال الكلاس SoftReference و تمرير الكائن الذي سيشير إليه للكونستركتور الخاص به, و عندها يمكننا إستدعاء الكائن من خلال الدالة get(), و في حال قرر جامع القمامة أنه يجب إزالة الكائن من الذاكرة سيقوم بتنفيذ الدالة finalize() على الكائن ثم يزيل المرجع الليّن (و سترجع الدالة get() عند إستدعائها null) ثم سيزيل الكائن من الذاكرة, و لإزالة المرجع يمكنك إستدعاء الدالة clear().

SoftReference<Student> soft = new SoftReference<>(new Student("Rami"));
Student rami = soft.get();

إن كان لديك مجموعة من المراجع الليّنة و أردت معرفة الوقت الذي يقرر فيه جامع القمامة إزالة الكائن الذي يشير إليه أحد المراجع فيمكنك إستخدام طابور المراجع ReferenceQueue, و بعد تمرير كائن الطابور لكونستركتور الـ SoftReference يمكنك تنفيذ الدالة remove() و التي ستنتظر حتى يتم إزالة أي من المراجع لتعيده, وهذا مثال يوضح ذلك:

public class Test {

    public static void main(String[] args) throws InterruptedException {
        ReferenceQueue queue = new ReferenceQueue();
        SoftReference reference = new SoftReference(new Test(), queue);
        queue.remove();
        System.out.println("now Test object is removed from the heap");
    }

}

قد تسأل عن فائدة كائن يمكن أن يختفي فجأة أثناء تنفيذ برنامجك!
تكون المراجع اللينة مفيدة في حفظ البيانات المؤقتة و غير الضرورية, فمثلاً عندما تقوم بإغلاق تبويب لموقع هرمش في المتصفح عن غير قصد و تقوم بفتح الرابط بسرعة يمكن أن يكون المتصفح قد خزّن بيانات الصفحة بمرجع ليّن بحيث إن كان الكائن الذي يمثّل صفحة الويب لم يتم إزالته و عندها سيتم عرض الصفحة مرة أخرى بسرعة دون الحاجة لتحميلها.

 

3- المراجع الضعيفة (Weak References)

هذه المراجع أضعف من المراجع اللينة, و عندما ينشط جامع القمامة ويجد أن أحد الكائنات له مراجع ضعيفة فقط فسيتم إزالته مباشرة, و يتم  إنشاء مرجع ضعيف بنفس الطريقة التي يتم فيها إنشاء مرجع ليّن إلا أن الكلاس الذي نستخدمه لذلك هو WeakReference.

 

4- المراجع الوهمية (Phantom References)

المراجع الوهمية تستخدم فقط لمعرفة متى سيتم إزالة الكائن, و لا يمكن الوصول من خلالها للكائن فالدالة get() الخاصة بالكلاس PhantomReference ترجع دائماً null عند إستدعائها.

لذلك يجب تمرير طابور المراجع كمعامل و إلا فلا فائدة من المراجع الوهمية.
يتم إدخال المرجع الوهمي إلى الطابور قبل تنفيذ الدالة finalize() على الكائن على عكس أنواع المراجع السابقة, و السبب وراء ذلك أن المراجع الوهمية برمجت بالأساس لإستبدال عمل الدالة finalize() على الكائن, وهذا مثال يوضح ذلك بشكل بسيط:

public class Test {

    public static void main(String[] args) throws InterruptedException {
        ReferenceQueue queue = new ReferenceQueue();
        PhantomReference reference = new PhantomReference(new Test(), queue);
        Reference clearedReference = queue.remove();
        if(reference == clearedReference){
            System.out.println("we can write finalizing code here for Test object");
        }
    }

}

مشكلة كتابة الكود داخل الدالة finalize() هي أنه يمكن للمبرمج إنقاذ الكائن من الإزالة أثناء تنفيذ الدالة!
يتم ذلك عبر عمل مرجع جديد لنفس الكائن, و هذا قد يكون مقصوداً في حالات نادرة إلا أن فعل ذلك عن غير قصد سيتسبب بتسرب الذاكرة (Memory Leak) و قد ينتهي الأمر بإظهار خطأ OutOfMemoryError.

نبّهني عن
guest
5 تعليقات
الآراء المضمنة
شاهد جميع التعليقات
waleed smadi
waleed smadi
7 شهور سابقاً

استاااااااااااااذ رامي شكرا لك <3 والله يوفقك يا رب ويسعدك دنيا واخرة 🙂 ^_^ <3 <3 <3

احمد
احمد
6 شهور سابقاً

لوسمحت انا مبتدا ابدا بالخورزميات ولا بالجافا

azmiradi Radiation
azmiradi Radiation
6 شهور سابقاً

أستاذ رامي ايه الفائده من استخدام الsoft. و weak والخ

جميع الحقوق محفوظة للموقع   ٢٠٢٠ - ٢٠١٤ ©
DMCA.com Protection Status

محتوى الموقع يخضع لرخصة (CC BY-NC-ND 4.0) التي لا تسمح باستخدام الشروحات لأغراض تجارية, إجراء تعديل عليها و نشرها في موقع آخر, وضع الشروحات في تطبيق أو في كتاب إلا في حال أخذ موافقة صريحة من إدارة الموقع.

© 2020 Harmash. All Content is licensed under CC BY-NC-ND 4.0 unless mentioned otherwise.