הקלד Erasure ב- Java הסביר

1. סקירה כללית

במאמר מהיר זה נדון ביסודות של מנגנון חשוב בגנריות של ג'אווה המכונה מחיקת סוגים.

2. מהי מחיקת סוג?

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

לדוגמה:

בוליאני סטטי ציבורי מכיל אלמנט (E [] אלמנטים, אלמנט E) {עבור (E e: יסודות) {אם (e.equals (element)) {return true; }} להחזיר שקר; }

המהדר מחליף את הסוג הלא מאוגד ה עם סוג ממשי של לְהִתְנַגֵד:

בוליאני סטטי ציבורי כולל Element (Object [], Element Object) {עבור (Object e: elements) {if (e.equals (element)) {return true; }} להחזיר שקר; }

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

3. סוגי מחיקת סוגים

מחיקת סוגים יכולה להתרחש ברמות המחלקה (או המשתנה) והשיטה.

3.1. מחיקת סוג כיתה

ברמת המחלקה, המהדר משליך את פרמטרי הסוג בכיתה ומחליף אותם בתחומה הראשונה, או לְהִתְנַגֵד אם פרמטר הסוג אינו מאוגד.

בואו ליישם א לַעֲרוֹם באמצעות מערך:

מחלקה ציבורית Stack {private E [] stackContent; מחסנית ציבורית (קיבולת int) {this.stackContent = (E []) אובייקט חדש [קיבולת]; } דחיפת חלל ציבורית (נתוני E) {// ..} פופ ציבורי E () {// ..}}

לאחר הידור, המהדר מחליף את פרמטר הסוג הלא מאוגד ה עם לְהִתְנַגֵד:

מחלקה ציבורית Stack {Private Object [] stackContent; מחסנית ציבורית (קיבולת int) {this.stackContent = (אובייקט []) אובייקט חדש [קיבולת]; } דחיפת חלל ציבורית (נתוני אובייקט) {// ..} פופ אובייקט ציבורי () {// ..}}

במקרה בו פרמטר הסוג ה קשור:

בכיתה ציבורית BoundStack {פרטי E [] stackContent; BoundStack ציבורי (קיבולת int) {this.stackContent = (E []) אובייקט חדש [קיבולת]; } דחיפת חלל פומבית (נתוני E) {// ..} פופ ציבורי E () {// ..}}

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

מחלקה ציבורית BoundStack {private Comparable [] stackContent; BoundStack ציבורי (קיבולת int) {this.stackContent = (השוואה []) אובייקט חדש [קיבולת]; } דחיפת חלל ציבורית (נתונים דומים) {// ..} פופ השוואה ציבורי () {// ..}}

3.2. מחיקת סוג השיטה

למחיקת סוג ברמת השיטה, פרמטר הסוג של השיטה אינו מאוחסן אלא מומר לסוג האב שלו לְהִתְנַגֵד אם זה לא מאוגד או שהוא מחלקה ראשונה כאשר הוא מאוגד.

בואו ניקח בחשבון שיטה להצגת התוכן של כל מערך נתון:

public static void printArray (E [] array) {for (E element: array) {System.out.printf ("% s", element); }}

לאחר הידור, המהדר מחליף את פרמטר הסוג ה עם לְהִתְנַגֵד:

public static void printArray (Object [] array) {for (Element element: array) {System.out.printf ("% s", element); }}

לפרמטר סוג שיטה מאוגד:

סטטי ציבורי  בטל printArray (E [] מערך) {עבור (רכיב E: מערך) {System.out.printf ("% s", אלמנט); }}

יהיה לנו את פרמטר הסוג ה נמחק והוחלף ב ניתן להשוות:

public static void printArray (Comparable [] array) {עבור (Comparable element: array) {System.out.printf ("% s", element); }}

4. מארזי קצה

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

בואו ניצור מחלקה חדשה המרחיבה את היישום הקודם שלנו לַעֲרוֹם. שים לב זה מתייחס ל לַעֲרוֹם כיתה שיצרנו ב סעיף 3.1, ולא ערימה.

מחלקה ציבורית IntegerStack מרחיב את Stack {public IntegerStack (קיבולת int) {super (קיבולת); } דחיפת חלל ציבורית (ערך שלם) {super.push (value); }}

עכשיו בואו נסתכל על הקוד הבא:

IntegerStack integerStack = IntegerStack חדש (5); מחסנית מחסנית = מספר שלם; stack.push ("שלום"); נתונים שלמים = integerStack.pop ();

לאחר מחיקת סוג, יש לנו:

IntegerStack integerStack = IntegerStack חדש (5); Stack stack = (IntegerStack) integerStack; stack.push ("שלום"); נתונים שלמים = (String) integerStack.pop ();

שימו לב איך אנחנו יכולים לדחוף א סטרינג על IntegerStack - כי IntegerStack ירש לדחוף (אובייקט) מכיתת ההורים לַעֲרוֹם. זה, כמובן, לא נכון - שכן צריך להיות מספר שלם מאז integerStack הוא לַעֲרוֹם סוּג.

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

4.1. שיטות גשר

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

בדוגמה שלנו לעיל, מהדר Java שומר על פולימורפיזם של סוגים גנריים לאחר מחיקה בכך שהוא מבטיח אי התאמה בין חתימת השיטה בין IntegerStackשל לדחוף (שלם) שיטה ו לַעֲרוֹםשל לדחוף (אובייקט) שיטה.

לפיכך, המהדר יוצר כאן שיטת גשר:

class class IntegerStack מרחיב את שיטת Stack {// Bridge שנוצרת על ידי המהדר public void push (ערך אובייקט) {push ((Integer)); } דחיפת חלל ציבורית (ערך שלם) {super.push (value); }}

כתוצאה מכך, לַעֲרוֹם כיתות לִדחוֹף שיטה לאחר מחיקת סוג, נציג למקור לִדחוֹף שיטה של IntegerStack מעמד.

5. מסקנה

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

תוכלו לקרוא עוד על מושגים אלה:

  • מפרט שפת Java: הקלד Erasure
  • היסודות של Java Generics

כמו תמיד, קוד המקור שמלווה מאמר זה זמין באתר GitHub.


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