Menu
Coddy logo textTech
flag Ar iconالعربيةdown icon

نمط Try With Resources

جزء من قسم البرمجة كائنية التوجه في رحلة Java على Coddy. الدرس 62 من 87.

عند العمل مع موارد مثل تدفقات file أو اتصالات connection، يجب عليك دائمًا إغلاقها عند الانتهاء. وإلا فإنك تخاطر بتسريبات الذاكرة. يستخدم approach التقليدي كتلة finally، لكنه مطوّل ومعرّض للأخطاء.

تغلق عبارة try-with-resources في Java الموارد تلقائيًا عند اكتمال block. يمكن استخدام أي class implements واجهة AutoCloseable مع هذه الصياغة:

// النهج التقليدي - مطول ومحفوف بالمخاطر
BufferedReader reader = null;
try {
    reader = new BufferedReader(new FileReader("file.txt"));
    String line = reader.readLine();
} finally {
    if (reader != null) {
        reader.close();  // قد يرمي استثناءً أيضاً!
    }
}

// Try-with-resources - نظيف وآمن
try (BufferedReader reader = new BufferedReader(new FileReader("file.txt"))) {
    String line = reader.readLine();
}  // يتم الإغلاق تلقائياً هنا

يمكنك إدارة الموارد Multiple عن طريق فصلها بفواصل منقوطة. ويتم إغلاقها بترتيب عكسي للإعلان عنها:

try (FileReader fr = new FileReader("input.txt");
     BufferedReader br = new BufferedReader(fr)) {
    // استخدم كلا الموردين
}  // يُغلق br أولاً، ثم fr

لإنشاء فئة AutoCloseable خاصة بك، نفّذ الواجهة AutoCloseable وطريقتها الوحيدة close():

public class DatabaseConnection implements AutoCloseable {
    public DatabaseConnection() {
        System.out.println("Connection opened");
    }
    
    @Override
    public void close() {
        System.out.println("Connection closed");
    }
}

يضمن هذا النمط تحرير الموارد بشكل صحيح دائمًا، حتى في حال حدوث استثناءات أثناء المعالجة.

challenge icon

التحدي

سهل

لنبنِ نظامًا لإدارة الموارد يوضّح قوة try-with-resources! ستنشئ فئات مخصّصة قابلة للإغلاق تلقائيًا تحاكي إدارة الاتصالات والجلسات، مع ضمان تنظيفها دائمًا بطريقة صحيحة.

ستُنظّم الشيفرة الخاصة بك عبر ثلاثة ملفات:

  • Connection.java: أنشئ فئة تحاكي اتصالًا بقاعدة بيانات. يجب أن تطبّق فئة Connection الواجهة AutoCloseable. وتحتاج إلى field خاص لاسم الاتصال (String)، وconstructor يأخذ الاسم ويطبع [name] connection opened، وmethod باسم query(String sql) يطبع Executing on [name]: [sql]، وmethod close() المطلوب الذي يطبع [name] connection closed.
  • Session.java: أنشئ فئة أخرى قابلة للإغلاق تلقائيًا تحاكي جلسة مستخدم. يجب أن تطبّق فئة Session أيضًا الواجهة AutoCloseable. أضِف field خاصًا لاسم المستخدم (String)، وconstructor يأخذ اسم المستخدم ويطبع Session started for [username]، وmethod باسم performAction(String action) يطبع [username] performed: [action]، وmethod باسم close() يطبع Session ended for [username].
  • Main.java: اجمع نظام إدارة الموارد الخاص بك! ستتلقى ثلاث مدخلات: اسم اتصال، واسم مستخدم، وaction لتنفيذه.

    أولًا، أظهِر إدارة مورد واحد. اطبع === Single Resource ===، ثم استخدم try-with-resources لإنشاء Connection بالاسم المعطى. Inside كتلة try، استدعِ query("SELECT * FROM users"). يجب أن يُغلق الاتصال تلقائيًا عند انتهاء الكتلة.

    بعد ذلك، أظهِر إدارة موارد متعددة. اطبع سطرًا فارغًا، ثم === Multiple Resources ===. استخدم try-with-resources مع كلٍّ من Connection (باستخدام الاسم نفسه) وSession (باستخدام اسم المستخدم)، مع التصريح عنهما بهذا الترتيب باستخدام الفواصل المنقوطة. Inside كتلة try، استدعِ أولًا query("INSERT INTO logs") على الاتصال، ثم استدعِ performAction مع input action على الجلسة. لاحظ كيف تُغلق الموارد بترتيب عكسي!

ستتلقى ثلاث مدخلات بالترتيب: اسم الاتصال (String)، واسم المستخدم (String)، وaction (String).

لاحظ كيف يلغي try-with-resources الحاجة إلى استدعاءات close الصريحة وكتل finally. ويُضمن إغلاق الموارد حتى عند حدوث استثناءات، كما تُغلق الموارد المتعددة بترتيب عكسي لترتيب التصريح!

جرّب بنفسك

import java.util.Scanner;

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String connectionName = scanner.nextLine();
        String username = scanner.nextLine();
        String action = scanner.nextLine();
        
        // === Single Resource ===
        // TODO: اطبع العنوان
        // TODO: استخدم try-with-resources لإنشاء Connection
        // TODO: Inside the try block, call query("SELECT * FROM users")
        
        // === Multiple Resources ===
        // TODO: اطبع سطرًا فارغًا والعنوان
        // TODO: استخدم try-with-resources مع كل من Connection و Session
        // TODO: داخل كتلة try:
        //       - Call query("INSERT INTO logs") on the connection
        //       - استدعِ performAction مع إجراء الإدخال action على session
        
    }
}
quiz iconاختبر نفسك

يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.

جميع دروس البرمجة كائنية التوجه

تدرّب بنفسك: مترجم Java عبر الإنترنت