1. אתחול סד כפול
אתחול באמצעות סוגרים כפולים (
להלן כפולים כפולים ) הוא כלי ג'אווה ליצירת אוספים כגון רשימה, סט ומפה בו-זמנית עם ההצהרה שלהם.
כאשר אתה צריך רשימות עם אלמנטים קבועים, כגון רשימה של מוצרים או מטבעות נתמכים, הצהרת הרשימה במקביל לאתחול שלה משפרת את קריאות הקוד. זו הסיבה שאתחול Double brace צובר פופולריות, מכיוון שאין שיטות סטנדרטיות אחרות ליצירת אוספים עם אתחול סימולטני בקוד. למרבה הצער, בניגוד לשפות תכנות אחרות, Java אינה תומכת באוספים של מילים. בשל מגבלה זו, יצירת רשימה בלתי ניתנת לשינוי אפילו
עם מספר קטן של אלמנטים מאלצת אותנו לכתוב שורות קוד רבות בצורה של קריאות חוזרות ונשנות
add()
כדי להוסיף את האלמנטים הרצויים עם גלישה סופית:
List<Integer> list = new ArrayList<>();
list.add(2);
list.add(3);
list.add(5);
list.add(7);
List<Integer> unmodifiableList = Collections.unmodifiableList(list);
זהו תיאור מיותר שלא לצורך שניתן לפשט אותו. בואו נמלא רשימות סטטיות בצורה נוחה לנו, כלומר ישירות בבלוקים סטטיים בזמן האתחול, ובזה
Double brace
האתחול יעזור לנו, ויאפשר לנו לכתוב הכל בשורה אחת:
List<Integer> list = Collections.unmodifiableList(new ArrayList<Integer>() {{
add(2);
add(3);
add(5);
}});
באופן דומה,
Double brace
אתחול יעזור לנו למלא ערכים ו
HashMap
:
Map<Integer, String> intToString = new HashMap<Integer, String>(){{
put(1, "one");
put(2, "two");
put(3, "three");
}};
הכל נראה כל כך אלגנטי, אבל יש לו חסרונות, שהופכים את אתחול הפלטה הכפולה לאנטי-דפוס. נסתכל עליהם עוד יותר בפרק הבא.
יתרונות וחסרונות של אתחול סד כפול.
Double
אתחול סד משתמש ביצירת מחלקה
פנימית אנונימית . עם זאת, מה שמוסתר בתחילה על פני השטח,
Double brace
האתחול יוצר מחלקה עם אתחול נוסף של המופע שלו בכל פעם שאתה משתמש בו. בנוסף, נעשה שימוש בהתייחסות נסתרת לשיעור פרטי זה, שיכול להוביל אותנו לדליפות זיכרון אפשריות. אתה גם לא יכול להשתמש באופרטור הרפאים לגנריות (אופרטור יהלומים < >), מכיוון שאיננו יכולים לגשת לחלק הפנימי של מחלקה אנונימית.
(מהמתרגם: שוב בפירוט רב יותר:
לאחר הראשון { נוצרת מחלקה אנונימית פנימית, לאחר השנייה { מתרחשת אתחול בעת יצירת מופע של המחלקה, בו יש לנו גישה לשדות ולשיטות של החיצוני ( יחסית לכיתה האנונימית). |
יתרונות:
- הקטנת שורות בקוד
- יצירה ואתחול בביטוי אחד.
מינוסים:
- יצירת כיתה אנונימית מוסתרת ממך.
- מה שעולה לנו עלויות נוספות עבור המופע שלו בכל פעם שאנו משתמשים בו.
- בכל פעם נוצרת התייחסות נסתרת אליו, שעלולה להוביל לדליפות זיכרון.
פסק דין: בשל החסרונות לעיל וקיומן של חלופות ל-Double brace, האתחול נתפס כאנטי-דפוס בעולם הג'אווה.
חלופות לאתחול כפול סד ב-Java
החדשות הטובות הן שיש דרכים אחרות להשיג את אותן מטרות בג'אווה. אנו יכולים ליישם בשורת קוד אחת את היצירה והאתחול של ArrayList באמצעות הבנאי Copy מהמחלקה Collection כפי שמוצג להלן:
List<Integer> list = Collections.unmodifiableList(new ArrayList<>(Arrays.asList(2, 3, 5)));
Arrays.asList()
יחזיר לנו רשימה באורך קבוע שהועבר לבנאי
ArrayList
ההעתקה. זכור את ההבדל בין רשימות באורך קבוע המוחזרות מ-
Arrays.asList()
ו
Collections.unmodifiableList()
: אינך יכול להוסיף או להסיר אלמנטים
ArrayList
של - , אך אתה יכול לשנות אלמנט לפי אינדקס באמצעות
set()
, מה שלא תוכל לעשות עם רשימה המוחזרת על ידי
Collections.unmodifiableList()
. אם אתה רוצה לקבל רשימה קטנה, זו הדרך הטובה ביותר, למרות שהיא תהיה פחות שקופה עבור
Set
אוספים אחרים, אז תצטרך ליצור אותה
List
לפני יצירת
Set
-a. אבל זה עדיין עדיף על אתחול Double brace, מכיוון שבמקרה זה לא נוצרת מחלקה אנונימית פנימית נוספת בכל פעם שמשתמשים בה. אם אתה מריץ Java 8 יש לך שיטה חלופית אחרת. ה-API של JDK 8 Stream יעזור לך ליצור אוספים קטנים על ידי שילוב
Stream Factory
שיטות פלט לאוסף
List
:
List<String> list = Collections.unmodifiableList(Stream.of("abc", "bcd", "cde").collect(toList()));
שכן
Set
אתה יכול להשתמש
Collectors.toSet()
בשיטה במקום
Collectors.toList()
כמו להלן:
Set<String> set = Collections.unmodifiableSet(Stream.of("abc", "bcd", "cde").collect(toSet()));
אגב,
Stream collect
השיטות לא מבטיחות שהאוספים שהן מייצרות מוגנים מפני שינויים. ב-Java 8, האוספים שהם החזירו (כגון -
ArrayList
,
HashSet
, ו-
HashMap
) נפוצים למדי (נוכל לשנות אותם), אך ייתכן שעובדה זו תתוקן במהדורות עתידיות של JDK. זה הכל לעת עתה לגבי
Double brace
אתחול ב-Java. תבנית זו מקובלת לבדיקות והדגמות, אך אינה טובה מספיק לשימוש בייצור. בשל החסרונות הטבועים בו, אתחול ה-Double brace הפך לאנטי-דפוס בימינו, במיוחד לאור החלופות הקיימות. אני עצמי עדיין משתמש בבנייה הזו כדי לאתחל מפות סטטיות וזהו. שכן
List
אני מעדיף ליצור
Collections
על ידי שילוב עם יצירה
Array.asList
בקונסטרוקטור שלו. ואם אני משתמש ב-Java 8 - עיצוב באמצעות ה- Stream API ו-
collect()
.
מאמרים קשורים: אם נהנית ממדריך זה וברצונך ללמוד עוד על דפוסי תכנות, עקרונות ושיטות עבודה מומלצות של Java, ייתכן שתרצה גם לעיין במאמרים האחרים באתר
שלנו .
קריאה מומלצת: אם אתה רוצה ללמוד עוד על דפוסים ושיטות עבודה מומלצות, עליך לקרוא
תכנות אפקטיבי מאת ג'ושוע בלוך , שום ספר לא יכול לתפוס את מקומו. ואם אתם כבר בקיאים בג'אווה ומחפשים ספר על דפוסי עיצוב, שסגנון ההצגה ההומוריסטי שלו מעניין וקל לקריאה, שימו לב
ל"ראש ראשון. תבניות עיצוב" .
מהמתרגם: בכוונה סיפקתי קישור לספרו המקורי של בלוך, מכיוון שתרגומו לרוסית לא מוצלח (לדוגמה, Builder = constructor). |
תרגום המאמר מהי אתחול Double Brace ב-Java? דוגמה נגד תבנית (פורסם באוקטובר 2015).
GO TO FULL VERSION