יש מילת מפתח ב-java -
final
. ניתן ליישם אותו על מחלקות, שיטות, משתנים (כולל ארגומנטים של מתודה). עבור מחלקה, זה אומר שלמחלקה לא יהיו תת מחלקות, כלומר. ירושה אסורה. זה שימושי בעת יצירת immutable
אובייקטים (בלתי ניתנים לשינוי), למשל מחלקה String
המוצהרת כ final
.
public final class String{
}
class SubString extends String{ //Compilation error
}
כמו כן, יש לציין שלא ניתן להחיל את השינוי על מחלקות מופשטות (עם מילת המפתח abstract
), final
כי אלו מושגים סותרים זה את זה. עבור שיטה final
פירושו שלא ניתן לעקוף אותה בתתי מחלקות. זה שימושי כאשר אנו רוצים שהיישום המקורי לא יעקוף.
public class SuperClass{
public final void printReport(){
System.out.println("Report");
}
}
class SubClass extends SuperClass{
public void printReport(){ //Compilation error
System.out.println("MyReport");
}
}
עבור משתנים מסוג פרימיטיבי, זה אומר שברגע שהוקצו, לא ניתן לשנות את הערך. עבור משתני התייחסות, המשמעות היא שברגע שהוקצו אובייקט, לא ניתן לשנות את ההתייחסות לאובייקט זה. זה חשוב! לא ניתן לשנות את הקישור, אך ניתן לשנות את מצב האובייקט. עם java 8 הופיע המושג - effectively final
. זה חל רק על משתנים (כולל ארגומנטים של שיטה). הנקודה היא שלמרות ההיעדר הברור של מילת המפתח final
, הערך של המשתנה לא משתנה לאחר האתחול. במילים אחרות, אתה יכול להחליף מילה במשתנה כזה final
ללא שגיאת קומפילציה. effectively final
ניתן להשתמש במשתנים בתוך מחלקות מקומיות ( Local Inner Classes
), מחלקות אנונימיות ( Anonymous Inner Classes
), זרמים (Stream API).
public void someMethod(){
// In the example below, both a and b are effectively final, since the values are set once:
int a = 1;
int b;
if (a == 2) b = 3;
else b = 4;
// c is NOT effectively final because value changes
int c = 10;
c++;
Stream.of(1, 2).forEach(s-> System.out.println(s + a)); //Ок
Stream.of(1, 2).forEach(s-> System.out.println(s + c)); //Compilation error
}
עכשיו בואו נעשה ראיון קטן. אחרי הכל, המטרה בקורס JavaRush היא להפוך למפתח Java ולקבל עבודה מעניינת ומשתלמת היטב. אז בואו נתחיל.
-
מה אתה יכול לומר על מערך כאשר הוא מוכרז
final
? -
ידוע שהמחלקה
String
היאimmutable
, המחלקה מוצהרתfinal
, הערך של המחרוזת מאוחסן במערךchar
, המסומן במילת המפתחfinal
.
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final char value[];
האם ניתן להחליף ערך של אובייקט String
(מבלי לשנות את ההתייחסות לאובייקט)? אלו שאלות ראיונות אמיתיות. וכפי שמראה בפועל, רבים עונים עליהם בצורה שגויה. הבנת השימוש במילת המפתח final
, במיוחד עבור משתני התייחסות, חשובה מאוד. בזמן שאתה חושב, סטייה מהירה לצוות JavaRush. אנא הוסף בלוק בעורך הטקסט שלך המאפשר לך להסתיר את התוכן, וכשתלחץ עליו, הצג את התוכן הזה. תשובות:
-
כי מערך הוא אובייקט, מה
final
שאומר שאחרי הקצאת הפניה לאובייקט, לא ניתן עוד לשנות אותו, אך ניתן לשנות את מצב האובייקט.final int[] array = {1,2,3,4,5}; array[0] = 9; //ok, because change the contents of the array - {9,2,3,4,5} array = new int[5]; //compile error
-
כן אתה יכול. המפתח הוא להבין את השימוש במילה הדוקרנית
final
עם חפצים. משתמש ב-ReflectionAPI כדי להחליף את הערך.
import java.lang.reflect.Field;
class B {
public static void main(String[] args) throws Exception {
String value = "Old value";
System.out.println(value);
//Get the value field in the String class
Field field = value.getClass().getDeclaredField("value");
//Let's change it
field.setAccessible(true);
//Set new value
field.set(value, "JavaRush".toCharArray());
System.out.println(value);
/* Вывод:
* Old value
* JavaRush
*/
}
}
שימו לב שאם ננסה לשנות את המשתנה הסופי של טיפוס פרימיטיבי בדרך זו, שום דבר לא יעבוד. אני מציע לך לשכנע את עצמך בכך: צור מחלקת Java, למשל, עם final int
שדה ותנסה לשנות את הערך שלו דרך ה-Reflection API. בהצלחה לכולם!
GO TO FULL VERSION