סופי לעומת גמר אפקטיבי בג'אווה

1. הקדמה

אחת התכונות המעניינות ביותר שהוצגו בג'אווה 8 היא למעשה סופית. זה מאפשר לנו לא לכתוב את סופי שינוי עבור משתנים, שדות ופרמטרים המטופלים ביעילות ומשמשים כמו סופיים.

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

2. מקור סופי למעשה

במילים פשוטות, אובייקטים או ערכים פרימיטיביים הם סופיים למעשה אם לא נשנה את ערכיהם לאחר האתחול. במקרה של אובייקטים, אם איננו משנים את הפניה של אובייקט, הרי שהוא למעשה סופי - גם אם מתרחש שינוי במצב של האובייקט שהפניה אליו.

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

שיעורים אנונימיים הם מחלקות פנימיות והם אינם יכולים לגשת למשתנים שאינם סופיים או שאינם אפקטיביים סופיים או למוטט אותם בטווחי הסגירה שלהם כמפורט ב- JLS 8.1.3. אותה מגבלה חלה על ביטויים למבדה, מכיוון שיש גישה עלולה לייצר בעיות במקביל.

3. סופי לעומת סופי ביעילות

הדרך הפשוטה ביותר להבין האם משתנה סופי הוא למעשה סופי היא לחשוב האם הסרת ה- סופי מילת המפתח תאפשר לקוד להתקבץ ולהריץ:

ממשק ציבורי @FunctionalInterface FunctionalInterface {void testEffectivelyFinal (); מבחן חלל ברירת מחדל () {int effectiveFinalInt = 10; FunctionalInterface functionalInterface = () -> System.out.println ("ערך המשתנה האפקטיבי הוא:" + effektivFinalInt); }} 

הקצאת ערך מחדש או מוטציה של המשתנה הסופי האמור לעיל, יהפכו את הקוד ללא חוקי ללא קשר למקומו.

3.1. טיפול במהדר

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

מהדר Java אינו מבצע אופטימיזציה נוספת למשתנים סופיים ביעילות, בניגוד לזה שעושה סופי משתנים.

בואו ניקח בחשבון דוגמה פשוטה שמצהירה על שתיים מחרוזת סופית משתנים אך משתמש בהם רק לשרשור:

ריק סטטי ציבורי main (String [] args) {final String hello = "hello"; עולם מחרוזת סופי = "עולם"; מבחן מחרוזת = שלום + "" + עולם; System.out.println (מבחן); } 

המהדר ישנה את הקוד המבוצע ב- רָאשִׁי השיטה לעיל ל:

חלל סטטי ציבורי main (String [] var0) {String var1 = "שלום עולם"; System.out.println (var1); }

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

4. שינוי אטומי

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

כבר יש לנו הדרכה המסבירה את השיטות המומלצות בשימוש בביטויי למבדה ואחרת המסבירה אנטי-דפוסים נפוצים כאשר אנו משנים אותם. אבל יש גישה חלופית שמאפשרת לנו לשנות משתנים במקרים כאלה שמשיגה בטיחות חוטים באמצעות אטומיות.

החבילה java.util.concurrent.atomic מציע שיעורים כגון AtomicReference ו AtomicInteger. אנו יכולים להשתמש בהם לשינוי אטומי של משתנים בתוך ביטויים למבדה:

ריק סטטי ציבורי ראשי (String [] args) {AtomicInteger effectiveFinalInt = AtomicInteger חדש (10); FunctionalInterface functionalInterface = effectiveFinalInt :: incrementAndGet; }

5. מסקנה

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


$config[zx-auto] not found$config[zx-overlay] not found