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

نمط Try With Resources

جزء من قسم Object Oriented Programming في رحلة Java على Coddy — الدرس 62 من 87.

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

تقوم جملة try-with-resources في Java بإغلاق الموارد تلقائيًا عند انتهاء الكتلة البرمجية. يمكن استخدام أي فئة تقوم بتنفيذ الواجهة 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();
}  // يتم الإغلاق تلقائياً هنا

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

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

لإنشاء فئة (class) خاصة بك قابلة للإغلاق تلقائيًا، قم بتنفيذ واجهة 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! ستقوم بإنشاء فئات مخصصة قابلة للإغلاق التلقائي (auto-closeable) تحاكي إدارة الاتصالات والجلسات، مما يضمن تنظيفها دائمًا بشكل صحيح.

ستقوم بتنظيم الكود الخاص بك عبر ثلاثة ملفات:

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

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

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

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

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

ورقة مرجعية

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

try (BufferedReader reader = new BufferedReader(new FileReader("file.txt"))) {
    String line = reader.readLine();
}  // تُغلق تلقائيًا هنا

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

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

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

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

جرّب بنفسك

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();
        
        // === مورد واحد ===
        // TODO: اطبع الترويسة
        // TODO: استخدم try-with-resources لإنشاء Connection
        // TODO: داخل كتلة try، استدعِ query("SELECT * FROM users")
        
        // === موارد متعددة ===
        // TODO: اطبع سطراً فارغاً والترويسة
        // TODO: استخدم try-with-resources مع كل من Connection و Session
        // TODO: داخل كتلة try:
        //       - استدعِ query("INSERT INTO logs") على الـ connection
        //       - استدعِ performAction مع action المدخل على الـ session
        
    }
}
quiz iconاختبر نفسك

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

جميع دروس Object Oriented Programming