CodeGym /בלוג Java /Random-HE /בחינת שאלות ותשובות מראיון עבודה למשרת מפתח Java. חלק 2
John Squirrels
רָמָה
San Francisco

בחינת שאלות ותשובות מראיון עבודה למשרת מפתח Java. חלק 2

פורסם בקבוצה
שוב שלום לכולם! אנו ממשיכים לחפש תשובות לשאלות למפתחי Java זוטרים, בינוניים ובכירים. השאלות סופר מעניינות. אני אישית אוהב לנתח אותם, כי זה עוזר לי למצוא פערים בידע התיאורטי שלי, ובמקומות הכי לא צפויים לפעמים. בחינת שאלות ותשובות מראיון עבודה למשרת מפתח Java.  חלק 2 - 1את החלק הקודם ניתן למצוא במאמר זה . אבל לפני שנתחיל, אני רוצה להזכיר לך ש:
  1. אדלג על השאלות החופפות לסדרת המאמרים הזו כדי לא לשכפל מידע שלא לצורך. אני ממליץ לקרוא מאמרים אלה מכיוון שהם מכסים את שאלות הראיונות הנפוצות ביותר (הפופולריות) של Java Core.
  2. יכולתי לתאר את התשובות ביתר פירוט, אבל לא, כי אז כל תשובה יכולה להתארך לאורך כל המאמר. ואף אחד לא יבקש ממך את רמת הפירוט הזו בשום ראיון עבודה.
אם תרצה אשאיר קישורים למחקר המעמיק יותר. בוא נעוף!

11. שם את כל השיטות של מחלקת Object

למחלקה Object יש 11 שיטות:
  1. Class<?> getClass() - קבל את המחלקה של האובייקט הנוכחי;

  2. int hashCode() - קבל את קוד ה-hash של האובייקט הנוכחי;

  3. boolean equals(Object obj) - השווה את האובייקט הנוכחי עם אובייקט אחר;

  4. Object clone() - צור והחזר עותק של האובייקט הנוכחי;

  5. String toString() - קבל את ייצוג המחרוזת של האובייקט;

  6. void notify() — התעורר שרשור אחד ממתין בצג של אובייקט זה (בחירת השרשור היא אקראית);

  7. void notifyAll() — תעיר את כל השרשורים הממתינים בצג של אובייקט זה;

  8. void wait() - גרם לשרשור הנוכחי להמתין בצג הנוכחי (הקפיא את השרשור הנוכחי) עד ששיחת notify או notifyAll תעיר את השרשור (עובד רק בבלוק מסונכרן);

  9. void wait (זמן קצוב ארוך) - לגרום לשרשור הנוכחי להמתין בצג הנוכחי (בבלוק המסונכרן הנוכחי), אך עם פסק זמן ליציאה ממצב המתנה (או שוב, עד ששיחה של notify או notifyAll תעיר את השרשור);

  10. void wait (פסק זמן ארוך, int nanos) - שיטה זו היא כמו השיטה הקודמת, אך עם פסק זמן מדויק יותר;

  11. void finalize() - שיטה זו נקראת (סוף סוף) לפני שהאובייקט מוסר על ידי אספן האשפה. הוא משמש לניקוי משאבים שנרכשו.

כדי להשתמש בשיטות hashCode , equals , clone , toString , ולסיים בצורה נכונה, יש לעקוף אותן בהתאם לפרטים הספציפיים של המשימה הנוכחית.

12. מה ההבדל בין try-with-resources לבין try-catch-finally בעבודה עם משאבים?

בדרך כלל, כאשר משתמשים ב- try-catch-finally , הבלוק הסופי משמש לסגירת משאבים. Java 7 מציגה את ההצהרה החדשה של נסה עם משאבים . זה מקביל ל- try-catch-finally לפינוי משאבים, אבל יותר קומפקטי וקריא. בואו ניזכר איך נראה סוף סוף נסיון-תפוס :
String text = "some text......";
BufferedWriter bufferedWriter = null;
try {
   bufferedWriter = new BufferedWriter(new FileWriter("someFileName"));
   bufferedWriter.write(text);
} catch (IOException e) {
   e.printStackTrace();
} finally {
   try {
       bufferedWriter.close();
   } catch (IOException e) {
       e.printStackTrace();
   }
}
עכשיו בואו נשכתב את הקוד הזה, אבל באמצעות נסה עם משאבים :
String text = "some text......";
try(BufferedWriter bufferedWriter =new BufferedWriter(new FileWriter("someFileName"))) {
   bufferedWriter.write(text);
} catch (IOException e) {
   e.printStackTrace();
}
עכשיו זה איכשהו יותר פשוט, אתה לא חושב? בנוסף לקוד הפשוט יותר, יש לציין עוד כמה נקודות:
  1. ב- try-with-resources , המשאבים המוצהרים בסוגריים (משאבים שייסגרו) חייבים ליישם את הממשק AutoCloseable ואת שיטת close() היחידה שלו .

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

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

  2. בלוקים מבוצעים בסדר הזה:

    1. חסימת הניסיון .
    2. המרומז לבסוף לחסום.
    3. בלוק ה- catch , אשר לוכד חריגים המתרחשים בשלבים הקודמים.
    4. המפורש לבסוף לחסום.

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

תאר לעצמך שאתה משתמש ב- try-catch-finally ותקבל חריגה בבלוק ה- try . ואז בלוק ה- catch שצוין מתחיל מיד להתבצע, בו כתבנו חריג נוסף (לדוגמה, עם הודעה המתארת ​​את השגיאה ביתר פירוט), ואתה רוצה שהמתודה תזרוק את החריג הזה כלפי מעלה. ואז הבלוק לבסוף מבוצע, וגם בו נזרק חריג. אבל הפעם אחרת. איזה משני יוצאי דופן אלה תשליך בסופו של דבר שיטה זו? החריג שנזרק על ידי בלוק סוף סוף ! אבל עכשיו הגענו לנקודה נוספת לגבי ניסיון עם משאבים . הבה נבחן כיצד מתנהג נסה-עם-משאבים באותו מצב. אנו מקבלים חריג בבלוק try כאשר מנסים לסגור משאבים בשיטת close() כלומר ב-implicit finally block. איזה מהחריגים האלה יתפוס בלוק ה- catch ? זה שנזרק על ידי בלוק הניסיון ! החריג מהחסימה המרומזת finally (מתוך שיטת lose() תתעלם. התעלמות זו מחריגים נקראת גם דיכוי חריגים.

13. מהן פעולות סיביות?

פעולות סיביות הן פעולות על רצפים של ביטים. הם כוללים פעולות לוגיות ותזוזות סיביות. פעולות לוגיות:
  • AND - השוואת ערכי סיביות . כל ביט שהוגדר ל-0 (false) מגדיר את הביט המקביל בתוצאה ל-0. כלומר, אם ביט הוא 1 (true) בשני הערכים המושוואים, אז גם הביט המתקבל יהיה 1.

    מסומן כ- AND או &

    דוגמה: 10111101 & 01100111 = 00100101

  • bitwise OR - פעולה זו הפוכה מהקודמת. כל ביט שהוגדר ל-1 מגדיר את הביט המקביל בתוצאה ל-1. בהתאם לכך, אם הביט הוא 0 בשני הערכים המושוואים, אז גם הביט המתקבל יהיה 0.

    מסומן כ- OR או |

    דוגמה: 10100101 | 01100011 = 11100111

  • שיטת סיביות NOT - אופרטור זה מוחל על ערך בודד. זה הופך (הופך) את הפיסות. כלומר, הביטים שהיו 1 הופכים ל-0; ואלה שהיו 0 הופכים ל-1.

    מסומן כ- NOT או ~

    דוגמה: ~10100101 = 01011010

  • בלעדי סיביות OR - משווה ערכי סיביות. אם שני הסיביות הן 1, אז הביט המתקבל הוא 0. אם שתי הסיביות הן 0, אז הסיביות המתקבלות הן 0. במילים אחרות, כדי שהביט המתקבל יהיה 1, רק אחד מהסיביות חייב להיות 1, ו הביט השני חייב להיות 0.

    מסומן כ- XOR או ^

    דוגמה: 10100101 ^ 01100011 = 11000110

העברות סיביות ( >> ו << ) מעבירות את הסיביות של האופרנד לכיוון שצוין, במספר המקומות שצוין. משרות פנויות מלאות באפסים. לדוגמה:
  1. 01100011 >> 4 = 00000110
  2. 01100011 << 3 = 00011000
היוצא מן הכלל הוא כאשר אתה מעביר מספר שלילי ימינה. כזכור, הסיבית הראשונה של מספר חתום מציינת את הסימן. אם הביט הזה הוא 1, אז המספר שלילי. אם אתה מעביר מספר שלילי, המיקומים המתפנים לא מתמלאים באפסים, אלא באחדים, שכן יש לשמור על סיביות הסימן. לדוגמה: 10100010 >> 2 = 11101000 עם זאת, לג'אווה יש אופרטור שימור ימני לא חתום נוסף (>>>). אופרטור זה מקביל ל->>, אך כאשר מועברים, עמדות שהתפנו מתמלאות ב-0, ללא קשר אם האופרנד הוא מספר שלילי או מספר חיובי. לדוגמה: 10100010 >>> 2 = 00101000 קרא עוד על פעולות סיביות כאן . בחינת שאלות ותשובות מראיון עבודה למשרת מפתח Java.  חלק 2 - 2אתה יכול לקחת את שיטת hash() ב-HashMaps כדוגמה לשינויים סיביים ב-Java. שיטה זו משמשת לקביעת ה-hashcode הפנימי המיוחד של המפתח: בחינת שאלות ותשובות מראיון עבודה למשרת מפתח Java.  חלק 2 - 3שיטה זו מאפשרת לך להפיץ באופן שווה את הנתונים ב-HashMap, על מנת למזער את מספר ההתנגשויות.

14. אילו אובייקטים סטנדרטיים בלתי ניתנים לשינוי יש בג'אווה?

אובייקט אינו ניתן לשינוי אם הוא אינו מאפשר לערכים המקוריים שלו להשתנות. ייתכן שיש לו שיטות המחזירות אובייקטים חדשים מאותו סוג עם ערכים שונים. כמה אובייקטים סטנדרטיים בלתי ניתנים לשינוי כוללים:
  • ללא ספק, הסוג הבלתי ניתן לשינוי המפורסם ביותר של Java הוא String;
  • מופעים של מחלקות העטיפה העוטפות סוגים סטנדרטיים: Boolean, Character, Byte, Short, Integer, Long, Double, Float;
  • אובייקטים BigInteger ו-BigDecimal, המשמשים בדרך כלל עבור מספרים BIG במיוחד;
  • אובייקטים של StackTraceElement המרכיבים עקבות מחסנית (לדוגמה, עקבות מחסנית של חריג);
  • אובייקט של מחלקת File - הוא יכול לשנות קבצים, אבל באותו זמן האובייקט עצמו נשאר ללא שינוי;
  • UUIDs, המשמשים לעתים קרובות לזיהוי ייחודי של אלמנטים;
  • כל האובייקטים של מחלקות בחבילת java.time;
  • אובייקטים מקומיים, המשמשים לזיהוי אזור גיאוגרפי, פוליטי או תרבותי.

15. מהם היתרונות של אובייקט בלתי משתנה על פני אובייקטים רגילים?

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

  2. אובייקטים בלתי ניתנים לשינוי טובים כמפתחות במפה. אם אתה משתמש באובייקט שניתן לשינוי כמפתח HashMap ואז מצב האובייקט משתנה, מבנה הנתונים עלול להתבלבל: האובייקט עדיין יהיה קיים, אבל אם תשתמש ב-containsKey(), ייתכן שלא תמצא אותו.

  3. אובייקטים בלתי ניתנים לשינוי הם מצוינים לאחסון נתונים בלתי ניתנים לשינוי (קבוע) שאסור לשנות אותם בזמן שהתוכנית פועלת.

  4. יתרון נוסף הוא אטומיות כישלון. אם אובייקט בלתי ניתן לשינוי זורק חריג, הוא לא יישאר במצב לא רצוי (שבור).

  5. קל לבדוק את השיעורים האלה.

  6. אינך זקוק למנגנונים נוספים כגון בנאי העתקות או יישום של שיבוט אובייקטים.

שאלות על OOP

16. מהם היתרונות של OOP באופן כללי ובהשוואה לתכנות פרוצדורלי?

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

  2. יישומים שנכתבו עם OOP הם הרבה יותר קל לשנות (כאשר עקרונות העיצוב נשמרים כראוי).

  3. מכיוון שגם הנתונים וגם פעולות הנתונים יוצרים ישות אחת, הם לא נמרחים על כל האפליקציה (מה שקורה לרוב בתכנות פרוצדורלי).

  4. עקרון האנקפסולציה מגן על הנתונים הקריטיים ביותר מהמשתמש.

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

  6. ירושה ופולימורפיזם גם מאפשרים לך לעשות שימוש חוזר ולהרחיב את הקוד הקיים (במקום לשכפל פונקציונליות דומה).

  7. הרחבת בקשה פשוטה יותר מאשר בגישה פרוצדורלית.

  8. גישת ה-OOP מאפשרת להסיר פרטי יישום.

17. ספר לנו אילו חסרונות יש ל-OOP

למרבה הצער, הם קיימים גם:
  1. OOP דורש הרבה ידע תיאורטי שיש לשלוט בו לפני שתוכל לכתוב משהו.

  2. רעיונות OOP אינם כל כך קלים להבנה ויישום בפועל (אתה צריך להיות פילוסוף קטן בנשמה).

  3. OOP מפחית מעט את ביצועי התוכנית בשל המורכבות המוגברת של המערכת.

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

  5. הזמן הנדרש לניתוח הראשוני גדול יותר מאשר לגישה פרוצדורלית.

18. מהו פולימורפיזם סטטי לעומת פולימורפיזם דינמי?

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

19. ספק הגדרה של עקרון ההפשטה ב-OOP

ב-OOP, הפשטה היא דרך לבודד קבוצה של מאפיינים משמעותיים של אובייקט, תוך אי הכללת פרטים חסרי משמעות. כלומר, כאשר מעצבים תוכנית בגישת OOP, מתמקדים במודלים כלליים, מבלי להיכנס לפרטי היישום שלהם. ב-Java, ההפשטה מתממשת באמצעות ממשקים . למשל, יש לך מכונית וזה יהיה ממשק. והאינטראקציות השונות איתו - למשל, התנעת המנוע, העברת הילוכים - הן פונקציות שאנו משתמשים בהן מבלי להתעמק בפרטי יישום. ואכן, כשאתה נוהג, אתה לא חושב איך בדיוק תיבת ההילוכים ממלאת את ייעודה, או איך המפתח מתניע את המנוע, או איך בדיוק ההגה מסובב את הגלגלים. ואם תחליף יישום של פונקציונליות כלשהי (לדוגמה, המנוע), אולי אפילו לא תשים לב לזה. זה לא משנה לך: אתה לא מתעמק בפרטי היישום. מה שחשוב לך הוא שהפעולה תתבצע. בעצם, הפשטת פרטי היישום הזו. בשלב זה נעצור היום: להמשך!
הערות
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION