Menu
Coddy logo textTech

תבנית Try With Resources

חלק מהיחידה תכנות מונחה עצמים במסלול ה-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

כדי ליצור מחלקה משלך שניתנת לסגירה אוטומטית, יש לממש את הממשק 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. עליה לכלול שדה פרטי עבור שם החיבור (String), בנאי שמקבל את השם ומדפיס [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 מייתר קריאות מפורשות ל-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: בתוך בלוק ה-try, קרא ל-query("SELECT * FROM users")
        
        // === Multiple Resources ===
        // TODO: הדפס שורה ריקה ואת הכותרת
        // TODO: השתמש ב-try-with-resources עם Connection ו-Session
        // TODO: בתוך בלוק ה-try:
        //       - קרא ל-query("INSERT INTO logs") על החיבור
        //       - קרא ל-performAction עם הפעולה שהתקבלה כקלט על ה-session
        
    }
}
quiz iconבחנו את עצמכם

השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.

כל השיעורים ביחידה תכנות מונחה עצמים

תרגלו בעצמכם: קומפיילר Java אונליין