Menu
CoddyTech

מילת המפתח final

חלק מהיחידה תכנות מונחה עצמים במסלול ה-Java של Coddy. שיעור 13 מתוך 87.

מילת המפתח final ב-Java מונעת שינוי. אפשר להחיל אותה על משתנים, מתודות ומחלקות, ולכל אחד מהם יש השפעה שונה.

כשמחילים את המשתנה, final הופך אותו לקבוע — לאחר שמקצים לו ערך, אי אפשר לשנות אותו:

public class Circle {
    private final double PI = 3.14159;
    private final double radius;
    
    public Circle(double radius) {
        this.radius = radius;  // אפשר להקצות ערך פעם אחת בבנאי
    }
    
    public void setRadius(double r) {
        // this.radius = r;  // שגיאה! אי אפשר להקצות מחדש ערך למשתנה final
    }
}

יש לאתחל משתנה final בעת ההכרזה עליו או בבנאי. לאחר מכן, כל ניסיון להקצות לו ערך מחדש יגרום לשגיאת קומפילציה.

עבור טיפוסי הפניה, final פירושו שההפניה אינה יכולה להצביע על אובייקט אחר, אבל תוכן האובייקט עדיין יכול להשתנות:

private final StringBuilder name = new StringBuilder("John");

// name = new StringBuilder("Jane");  // שגיאה! אי אפשר להקצות מחדש
name.append(" Doe");  // בסדר! התוכן של האובייקט יכול להשתנות

שימוש ב־final עם שדות מבטא בבירור את הכוונה — הוא מבהיר למפתחים אחרים שהערך הזה לעולם לא אמור להשתנות לאחר האתחול. הדבר שימושי במיוחד עבור ערכי תצורה, מזהים או כל נתון שצריך להישאר קבוע לאורך כל חיי האובייקט.

מתודה מסוג final אינה יכולה להידרס במחלקת משנה:

class Base {
    public final void greet() {
        System.out.println("Hi");
    }
}
class Child extends Base {
    // public void greet() { }  // שגיאה! greet() היא final ב-Base
}

אי אפשר להרחיב מחלקה final כלל. String היא מחלקה סופית, ולכן אף מחלקה לא יכולה להרחיב אותה:

final class Config { }
// class MyConfig extends Config { }  // שגיאה! Config היא final
challenge icon

אתגר

קל

בואו נבנה מערכת רישום של Student שמשתמשת במילת המפתח final כדי להגן על נתונים שאסור לשנות לאחר רישום סטודנט.

תיצרו שני קבצים כדי לארגן את הקוד שלכם:

  • Student.java: צרו מחלקת Student שבה מידע מסוים ננעל לצמיתות לאחר הגדרתו:
    • שדה final בשם studentId (String) — מוקצה בעת יצירת האובייקט ואי אפשר לשנות אותו לעולם
    • שדה final בשם enrollmentYear (int) — השנה שבה הסטודנט נרשם, וגם היא קבועה
    • שדה פרטי רגיל בשם name (String) — אפשר לעדכן אותו אם הסטודנט משנה את שמו
    • בנאי שמקבל את שלושת הערכים ומאתחל את השדות
    • getter בשם getStudentId() עבור מזהה הסטודנט
    • getter בשם getEnrollmentYear() עבור שנת ההרשמה
    • getter בשם getName() ו-setter בשם setName() עבור השם
    • מתודה בשם getInfo() שמחזירה: "ID: [studentId] | Name: [name] | Enrolled: [enrollmentYear]"
  • Main.java: צרו אובייקט Student, לאחר מכן עדכנו את שמו והציגו את המידע שלו. תקבלו ארבע קלטים: מזהה הסטודנט, השם ההתחלתי, שנת ההרשמה ושם חדש לעדכון. הדפיסו שתי שורות:
    • פרטי הסטודנט לפני שינוי השם
    • פרטי הסטודנט אחרי שינוי השם

תקבלו ארבעה קלטים לפי הסדר: studentId (String), name (String), enrollmentYear (int) ו-newName (String).

שימו לב איך שדות final מגינים על מזהה הסטודנט ועל שנת ההרשמה — אלה רשומות קבועות שלא אמורות להשתנות, בעוד שאפשר לעדכן את השם באמצעות ה-setter שלו.

נסו בעצמכם

import java.util.Scanner;

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        // קרא את הקלטים
        String studentId = scanner.nextLine();
        String name = scanner.nextLine();
        int enrollmentYear = scanner.nextInt();
        scanner.nextLine(); // צרוך את תו השורה החדשה
        String newName = scanner.nextLine();
        
        // TODO: צור אובייקט Student עם הערכים ההתחלתיים
        
        // TODO: הדפס את פרטי התלמיד לפני שינוי השם
        
        // TODO: עדכן את שם התלמיד באמצעות ה-setter
        
        // TODO: הדפס את פרטי התלמיד לאחר שינוי השם
    }
}
quiz iconבחנו את עצמכם

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

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

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