JavaRush /בלוג Java /Random-HE /ניתוח שאלות ותשובות מראיונות למפתח Java. חלק 11

ניתוח שאלות ותשובות מראיונות למפתח Java. חלק 11

פורסם בקבוצה
שלום! אפילו הספינה המהירה ביותר ללא מסלול פשוט תיסחף לאורך הגלים. אם אתה קורא את המאמר שלי עכשיו, בהחלט יש לך מטרה. העיקר לא ללכת שולל, אלא לעקוב אחרי הקו שלך עד הסוף - להפוך למפתח ג'אווה. היום אני רוצה להמשיך את הניתוח שלי של 250+ שאלות למפתחי Java, שיעזרו לכם לכסות חלק מהפערים בתיאוריה. ניתוח שאלות ותשובות מראיונות למפתח Java.  חלק 11 - 1

97. האם מוטלים תנאים להגדרה מחדש של הסכם בעת הגדרה מחדש של Equals?

שיטת העקיפה equals() חייבת לעמוד בתנאים (הכללים) הבאים:
  • רפלקסיביות - עבור כל ערך x, ביטוי כמו x.equals(x) צריך תמיד להחזיר true (כאשר x != null ).

  • סימטריה - עבור כל ערכים של x ו- y, ביטוי של הצורה x.equals(y) חייב להחזיר true רק אם y.equals(x) מחזיר true .

  • טרנזיטיביות - עבור כל ערכים של x , y ו- z , אם x.equals(y) מחזירה true ו- y.equals(z) גם מחזירה true , אז x.equals(z) חייב להחזיר true .

  • עקביות - עבור כל ערכים של x ו- y, קריאה חוזרת ל- x.equals(y) תמיד תחזיר את הערך של הקריאה הקודמת לשיטה זו, בתנאי שהשדות ששימשו להשוואה בין שני האובייקטים לא השתנו בין הקריאות .

  • comparison null - עבור כל ערך x, קריאה ל- x.equals(null) תחזיר false .

98. מה קורה אם לא תעקוף את Equals ואת HashCode?

במקרה זה, hashCode() יחזיר מספר שנוצר על סמך מיקום הזיכרון שבו מאוחסן האובייקט הנתון. כלומר, שני אובייקטים בעלי אותם שדות בדיוק יקבלו ערכים שונים בעת קריאה ל- hashCode() שאינו נדחק (אחרי הכל, הם מאוחסנים במיקומי זיכרון שונים). ה-Unoverridden equals() משווה הפניות כדי לראות אם הן מצביעות על אותו אובייקט או לא. כלומר, ההשוואה מתבצעת דרך == , ובמקרה של אובייקטים עם אותם שדות היא תמיד תחזיר false . נכון יהיה רק ​​כאשר משווים הפניות לאותו אובייקט. לפעמים יש היגיון בכך שלא לעקוף את השיטות הללו. לדוגמה, אתה רוצה שכל האובייקטים של מחלקה מסוימת יהיו ייחודיים ועקיפה של שיטות אלה רק תקלקל את ההיגיון של הייחודיות. העיקר הוא להבין את הניואנסים של שיטות דחוקות ושאינן מבוטלות ולהשתמש בשתי הגישות בהתאם למצב.

99. מדוע סימטריה נכונה רק אם x.equals(y) מחזירה true?

שאלה קצת מוזרה. אם אובייקט A שווה לאובייקט B, אז אובייקט B שווה לאובייקט A. אם B אינו שווה לאובייקט A, אז איך ייתכן ההפך? זה היגיון פשוט. ניתוח שאלות ותשובות מראיונות למפתח Java.  חלק 11 - 2

100. מהי התנגשות ב-HashCode? איך להתמודד עם זה?

התנגשות hashCode היא מצב שבו לשני אובייקטים שונים יש ערך hashCode זהה . איך זה אפשרי? העובדה היא שקוד hash ממופה לסוג Integer , שבתורו יש טווח שבין -2147483648 ל-2147483647, כלומר כ-4 מיליארד מספרים שלמים שונים. הטווח הזה הוא עצום, עם זאת, הוא לא אינסופי. לכן, מצבים אפשריים כאשר לשני אובייקטים שונים לחלוטין יש קוד hash זהה. זה מאוד לא סביר, אבל אפשרי. פונקציית Hash מיושמת בצורה גרועה יכולה גם להגביר את התדירות של קודי Hash זהים, שיחזירו למשל מספרים בטווח קטן, מה שיגדיל את הסיכוי להתנגשויות. כדי להילחם בהתנגשות, יש צורך ביישום טוב של שיטת ה-hashCode כך שהתפשטות הערכים תהיה מקסימלית והסיכוי לחזור על ערכים מינימלי.

101. מה קורה אם אלמנט המשתתף בחוזה HashCode משנה את ערכו?

אם אלמנט שמעורב בחישוב קוד ה-hash שונה, אזי ישתנה קוד ה-hash של האובייקט עצמו (אם פונקציית ה-hash טובה). לכן, ב- HashMap מומלץ להשתמש באובייקטים בלתי ניתנים לשינוי (בלתי ניתנים לשינוי) כמפתח, מכיוון שלא ניתן לשנות את המצב הפנימי (שדות) שלהם לאחר היצירה. בהתאם, גם קוד ה-hash שלהם אינו מומר לאחר היצירה. אם אתה משתמש באובייקט שניתן לשינוי כמפתח, אז כאשר אתה משנה את השדות של אובייקט זה, קוד ה-hash שלו ישתנה, וכתוצאה מכך, אתה יכול לאבד את הצמד הזה ב- HashMap . אחרי הכל, הוא יישמר ב-bucket של קוד ה-hash המקורי, ולאחר שינוי זה יבוצע חיפוש בדלי אחר. ניתוח שאלות ותשובות מראיונות למפתח Java.  חלק 11 - 3

102. כתוב שיטות Equals ו-HashCode לכיתת הסטודנט, המורכבת משדות שם מחרוזת ושדות גיל int

public class Student {
int age;
String name;

 @Override
 public boolean equals(final Object o) {
   if (this == o) {
     return true;
   }
   if (o == null || this.getClass() != o.getClass()) {
     return false;
   }

   final Student student = (Student) o;

   if (this.age != student.age) {
     return false;
   }
   return this.name != null ? this.name.equals(student.name) : student.name == null;
 }

 @Override
 public int hashCode() {
   int result = this.age;
   result = 31 * result + (this.name != null ? this.name.hashCode() : 0);
   return result;
 }
}
שווים:
  • ראשית, אנו משווים את הקישורים ישירות, כי אם הקישורים הם לאותו אובייקט, מה הטעם להמשיך בבדיקה? הכל יהיה נכון בכל מקרה .

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

  • יציקת אובייקט הארגומנט לסוג אחד (במקרה שהיה אובייקט מסוג האב).

  • השוואה של שדה מחלקה פרימיטיבי (בכל זאת, השוואה דרך =! מספיקה בשביל זה ), אם השדה לא שווה - שקר .

  • בדיקת שדה לא פרימיטיבי עבור null ושווה ( במחרוזת השיטה מוחקת ותשוווה נכון), אם שני השדות הם null או שווים , אז הסימון מסתיים והשיטה מחזירה true .

HashCode:
  • הגדרת ערך קוד ה-hash הראשוני לפרימיטיבי הגיל של האובייקט .

  • הכפלת קוד ה-hash הנוכחי ב-31 (לפיזור גדול יותר) והוספת אליו את קוד ה-hash של שדה מחרוזת לא פרימיטיבי (אם הוא אינו null).

  • מחזיר את התוצאה.

  • כתוצאה מעקיפה זו של קוד ה-hash, אובייקטים בעלי אותו שם וערכי int יחזירו תמיד את אותו הערך.

103. מה ההבדל בין שימוש ב- if (instanceof Student) לבין if (getClass() == obj.getClass())?

בואו נסתכל מה עושה כל גישה:
  • instanceof בודק האם הפניה לאובייקט בצד שמאל היא מופע מהסוג בצד ימין או תת-סוג כלשהו שלו.

  • getClass() == ... בודק את זהות הסוג.

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

104. תן תיאור קצר של שיטת clone() .

Clone() היא שיטה של ​​המחלקה Object , שמטרתה ליצור ולהחזיר שיבוט של האובייקט הנוכחי (עותק של האובייקט הנוכחי). ניתוח שאלות ותשובות מראיונות למפתח Java.  חלק 11 - 4כדי להשתמש בו, עליך ליישם את ממשק הסמן שניתן לשבוט :
Student implements Cloneable
ועקוף את שיטת clone() עצמה :
@Override
protected Object clone() throws CloneNotSupportedException {
 return super.clone();
}
אחרי הכל, במחלקת Object הוא מוגן, כלומר, הוא יהיה גלוי רק בכיתה Student עצמה , אך לא גלוי לכיתה מבחוץ.

105. מהי הייחודיות של שיטת clone() בעבודה עם השדות של אובייקט מסוג הפניה?

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

חריגים

106. מה ההבדל בין טעות לחריגה?

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

107. מה ההבדל בין מסומן לבלתי מסומן, חריג, זריקה, זריקה.

כפי שאמרתי קודם, חריג הוא שגיאה במהלך הפעלת התוכנית ובמהלך הקומפילציה שהתרחשה בקוד שנכתב על ידי המפתח (בגלל מצב לא נורמלי כלשהו). מסומן הוא סוג של חריג שתמיד יש לטפל בו באמצעות מנגנון ה- try-catch או לזרוק אותו לשיטות שלמעלה. Throws משמש בכותרת השיטה כדי לציין חריגים אפשריים שנזרקה על ידי השיטה. כלומר, זהו המנגנון ל"השלכת" חריגים לשיטות לעיל. לא מסומן הוא סוג של חריג שאין צורך לטפל בו ובדרך כלל הוא פחות צפוי וסביר פחות להתרחש. עם זאת, ניתן גם לעבד אותם אם תרצה. Throw משמש בעת זריקת חריגה באופן ידני, לדוגמה:
throw new Exception();

108. מהי ההיררכיה של חריגים?

היררכיית החריגים היא מאוד גדולה ונרחבת, אפילו נרחבת מכדי לספר עליה הכל כאן. לכן, נשקול רק את הקישורים המרכזיים שלו: ניתוח שאלות ותשובות מראיונות למפתח Java.  חלק 11 - 6כאן ממש בראש ההיררכיה אנו רואים את המחלקה - Throwable - מחלקה כללית, האב הקדמון של היררכיית החריג, אשר בתורה מחולקת ל:
  • שגיאה - שגיאות קריטיות שאינן ניתנות לסימון.
  • חריגה - חריגים מסומנים.
חריגים מחולקים לחריגים שונים בזמן ריצה לא מסומנים וחריגים מסומנים שונים.

109. מה זה חריג מסומן ולא מסומן?

כמו שאמרתי קודם:
  • מסומנים - חריגים שאתה חייב איכשהו לטפל בהם, כלומר, לעבד אותם ב- try-catch block , או "להעביר" אותם לשיטה שלמעלה. לשם כך, בחתימת השיטה, לאחר פירוט ארגומנטי המתודה, עליך להשתמש במילת המפתח trows <exception type> , אשר מציינת למשתמשי השיטה שהשיטה יכולה לזרוק את החריג הזה (משהו כמו אזהרה) ומעבירה את אחריות לטפל בחריג למשתמשים בשיטה זו.

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

101. כתבו דוגמה של יירוט וטיפול בחריג בבלוק try-catch של שיטה

try{                                                 // начало блока перехвата
 throw new Exception();                             // ручной бросок исключения
} catch (Exception e) {                              // данное исключение и его потомки будут перехватываться
 System.out.println("Упс, что-то пошло не так =("); // вывод некоторого исключения в консоль
}

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

ראשית, בואו נכתוב מחלקה חריגה משלנו, שיורשת מ- Exception ותעקוף את הבנאי שלו בהודעת שגיאה:
public class CustomException extends Exception {

 public CustomException(final String message) {
   super(message);
 }
}
ובכן, אז נזרוק אותו ידנית וניירט אותו כמו בשאלה הקודמת:
try{
 throw new CustomException("Упс, что-то пошло не так =(");
} catch (CustomException e) {
 System.out.println(e.getMessage());
}
ושוב, כאשר תפעיל אותו, תקבל את הפלט הבא לקונסולה:
אופס, משהו השתבש =(
Разбор вопросов и ответов с собеседований на Java-разработчика. Часть 11 - 7אתה יכול לברר עוד על החריגים כאן . ובכן, זה הכל להיום! נתראה בחלק הבא!
הערות
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION