JavaRush /จาวาบล็อก /Random-TH /การวิเคราะห์คำถามและคำตอบจากการสัมภาษณ์นักพัฒนา Java ตอนท...
Константин
ระดับ

การวิเคราะห์คำถามและคำตอบจากการสัมภาษณ์นักพัฒนา Java ตอนที่ 11

เผยแพร่ในกลุ่ม
สวัสดี! แม้แต่เรือที่เร็วที่สุดที่ไม่มีเส้นทางก็ยังล่องลอยไปตามคลื่น หากคุณกำลังอ่านบทความของฉันตอนนี้ แสดงว่าคุณมีเป้าหมายอย่างแน่นอน สิ่งสำคัญคืออย่าหลงทาง แต่ต้องติดตามคุณไปจนจบ - เพื่อเป็นนักพัฒนา Java วันนี้ฉันต้องการวิเคราะห์คำถามมากกว่า 250 ข้อสำหรับนักพัฒนา Java ต่อไป ซึ่งจะช่วยให้คุณครอบคลุมช่องว่างบางประการในทฤษฎี การวิเคราะห์คำถามและคำตอบจากการสัมภาษณ์นักพัฒนา Java  ตอนที่ 11 - 1

97. มีการบังคับใช้เงื่อนไขการกำหนดนิยามใหม่ของข้อตกลงเมื่อกำหนดนิยามใหม่เท่ากับหรือไม่

วิธีการ แทนที่ เท่ากับ ()จะต้องเป็นไปตามเงื่อนไข (กฎ) ต่อไปนี้:
  • การสะท้อนกลับ - สำหรับค่าx ใดๆ นิพจน์เช่นx.equals(x)ควรคืนค่าเป็นจริง เสมอ (เมื่อx != null )

  • สมมาตร - สำหรับค่าใดๆ ของxและyนิพจน์ในรูปแบบx.equals(y)จะต้องคืนค่าเป็นจริงก็ต่อเมื่อy.equals(x)ส่งคืนค่า trueเท่านั้น

  • การผ่านผ่าน - สำหรับค่าใดๆ ของx , yและzถ้าx.equals(y)ส่งคืนtrueและy.equals(z)ส่งคืนtrue ด้วย ดังนั้นx.equals(z)จะต้องส่งคืนtrue

  • ความสอดคล้อง - สำหรับค่าใด ๆ ของxและyการเรียกx.equals(y) ซ้ำ ๆ จะส่งกลับค่าของการเรียกครั้งก่อนหน้าเป็นวิธีนี้เสมอ โดยมีเงื่อนไขว่าฟิลด์ที่ใช้ในการเปรียบเทียบวัตถุทั้งสองจะไม่เปลี่ยนแปลงระหว่างการโทร .

  • การเปรียบเทียบ null - สำหรับค่าx ใดๆ การเรียกx.equals(null)จะส่งคืนค่าfalse

98. จะเกิดอะไรขึ้นถ้าคุณไม่แทนที่ Equals และ HashCode

ในกรณีนี้hashCode()จะส่งคืนตัวเลขที่สร้างขึ้นตามตำแหน่งหน่วยความจำที่จัดเก็บอ็อบเจ็กต์ที่กำหนด นั่นคือวัตถุสองชิ้นที่มีฟิลด์เหมือนกันทุกประการจะได้รับค่าที่แตกต่างกัน เมื่อเรียก hashCode ที่ไม่ได้แทนที่ () (หลังจากนั้นพวกมันจะถูกเก็บไว้ในตำแหน่งหน่วยความจำที่แตกต่างกัน) Unoverridden Equals()เปรียบเทียบการอ้างอิงเพื่อดูว่าชี้ไปที่วัตถุเดียวกันหรือไม่ นั่นคือการเปรียบเทียบจะดำเนินการผ่าน==และในกรณีของอ็อบเจ็กต์ที่มีฟิลด์เดียวกัน จะส่งคืนค่าfalseเสมอ Trueจะเกิดขึ้นเมื่อเปรียบเทียบการอ้างอิงกับออบเจ็กต์เดียวกันเท่านั้น บางครั้งก็มีตรรกะที่จะไม่เอาชนะวิธีการเหล่านี้ ตัวอย่างเช่น คุณต้องการให้อ็อบเจ็กต์ทั้งหมดของคลาสใดคลาสหนึ่งไม่ซ้ำกัน และการแทนที่เมธอดเหล่านี้จะทำให้ตรรกะของความเป็นเอกลักษณ์เสียไปเท่านั้น สิ่งสำคัญคือการเข้าใจความแตกต่างของวิธีการแทนที่และไม่ถูกแทนที่ และใช้ทั้งสองวิธีขึ้นอยู่กับสถานการณ์

99. เหตุใดความสมมาตรจึงเป็นจริงก็ต่อเมื่อ x.equals(y) ส่งกลับค่าจริงเท่านั้น

คำถามแปลกๆนิดหน่อย หากวัตถุ A เท่ากับวัตถุ B แล้ววัตถุ B ก็เท่ากับวัตถุ A ถ้า B ไม่เท่ากับวัตถุ A แล้วสิ่งที่ตรงกันข้ามเป็นไปได้อย่างไร นี่เป็นตรรกะง่ายๆ การวิเคราะห์คำถามและคำตอบจากการสัมภาษณ์นักพัฒนา Java  ตอนที่ 11 - 2

100. การชนกันใน HashCode คืออะไร? จะจัดการกับมันอย่างไร?

การชนกันของ hashCodeคือสถานการณ์ที่วัตถุสองชิ้นที่แตกต่างกันมี ค่า hashCode เหมือน กัน สิ่งนี้เป็นไปได้อย่างไร? ความจริงก็คือแฮชโค้ดถูกแมปกับ ประเภท Integerซึ่งมีช่วงตั้งแต่ -2147483648 ถึง 2147483647 ซึ่งก็คือจำนวนเต็มที่แตกต่างกันประมาณ 4 พันล้านจำนวน ช่วงนี้มีขนาดใหญ่มาก แต่ก็ไม่ได้ไม่มีที่สิ้นสุด ดังนั้น สถานการณ์จึงเป็นไปได้เมื่อวัตถุสองชิ้นที่ต่างกันโดยสิ้นเชิงมีรหัสแฮชเดียวกัน สิ่งนี้ไม่น่าเป็นไปได้อย่างมาก แต่ก็เป็นไปได้ ฟังก์ชันแฮชที่ใช้งานไม่ดียังช่วยเพิ่มความถี่ของรหัสแฮชที่เหมือนกัน ซึ่งจะส่งคืนตัวเลขในช่วงเล็กๆ ซึ่งจะเพิ่มโอกาสที่จะเกิดการชนกัน เพื่อต่อสู้กับการชนกัน คุณต้องมีการนำเมธอด hashCode ไปใช้อย่างดีเพื่อให้การแพร่กระจายของค่าสูงสุดและโอกาสที่จะเกิดค่าซ้ำมีน้อย

101. จะเกิดอะไรขึ้นหากองค์ประกอบที่เข้าร่วมในสัญญา HashCode เปลี่ยนแปลงมูลค่าของมัน?

หากองค์ประกอบที่เกี่ยวข้องกับการคำนวณรหัสแฮชมีการเปลี่ยนแปลง รหัสแฮชของออบเจ็กต์เองก็จะเปลี่ยนไป (หากฟังก์ชันแฮชดี) ดังนั้นในHashMapขอแนะนำให้ใช้ออบเจ็กต์ที่ไม่เปลี่ยนรูป (ไม่เปลี่ยนแปลง) เป็นคีย์ เนื่องจากสถานะภายใน (ฟิลด์) ไม่สามารถเปลี่ยนแปลงได้หลังจากการสร้าง ดังนั้น รหัสแฮชของพวกเขาจะไม่ถูกแปลงหลังการสร้างเช่นกัน หากคุณใช้ออบเจ็กต์ที่ไม่แน่นอนเป็นคีย์ เมื่อคุณเปลี่ยนฟิลด์ของออบเจ็กต์นี้ รหัสแฮชของมันจะเปลี่ยนไป และด้วยเหตุนี้ คุณอาจสูญเสียคู่นี้ในHashMap ท้ายที่สุดแล้ว มันจะถูกจัดเก็บไว้ในที่เก็บข้อมูลสำหรับรหัสแฮชดั้งเดิม และหลังจากเปลี่ยนแล้ว มันจะถูกค้นหาในที่เก็บข้อมูลอื่น การวิเคราะห์คำถามและคำตอบจากการสัมภาษณ์นักพัฒนา Java  ตอนที่ 11 - 3

102. เขียนเมธอด Equals และ HashCode สำหรับคลาส Student ซึ่งประกอบด้วยฟิลด์ String name และ int age

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;
 }
}
เท่ากับ:
  • อันดับแรกเราเปรียบเทียบลิงค์โดยตรง เพราะถ้าลิงค์ไปที่ object เดียวกัน จะตรวจสอบต่อไปทำไม? ทุก อย่าง จะเป็น จริงอยู่แล้ว

  • การตรวจสอบค่า null และประเภทคลาสที่ตรงกัน เนื่องจากหากอ็อบเจ็กต์เป็นอาร์กิวเมนต์ของ null หรือประเภทอื่น นั่นหมายความว่าอ็อบเจ็กต์นั้นไม่เท่ากัน- false

  • การส่งวัตถุอาร์กิวเมนต์เป็นประเภทเดียว (ในกรณีที่เป็นวัตถุประเภทพาเรนต์)

  • การเปรียบเทียบฟิลด์คลาสดั้งเดิม (หลังจากทั้งหมด การเปรียบเทียบผ่าน= ! ก็เพียงพอแล้ว ) หากฟิลด์ไม่เท่ากัน - false

  • การตรวจสอบฟิลด์ที่ไม่ใช่แบบดั้งเดิมสำหรับค่า null และเท่ากับ (ในStringวิธีการจะถูกแทนที่และจะเปรียบเทียบอย่างถูกต้อง) หากทั้งสองฟิลด์เป็น null หรือเท่ากับการตรวจสอบจะสิ้นสุดและเมธอดจะส่งคืนtrue

แฮชโค้ด:
  • การ ตั้งค่ารหัสแฮชเริ่มต้นเป็นอายุ ดั้งเดิมของวัตถุ

  • คูณรหัสแฮชปัจจุบันด้วย 31 (เพื่อการแพร่กระจายที่มากขึ้น) และเพิ่มรหัสแฮชของฟิลด์สตริงที่ไม่ใช่แบบดั้งเดิม (หากไม่เป็นค่าว่าง)

  • การส่งคืนผลลัพธ์

  • จากการแทนที่โค้ดแฮชนี้ วัตถุที่มีชื่อและ ค่า int เดียวกัน จะส่งกลับค่าเดียวกันเสมอ

103. การใช้ if (obj instanceof Student) และ if (getClass() == obj.getClass()) แตกต่างกันอย่างไร?

มาดูกันว่าแต่ละวิธีทำอะไรได้บ้าง:
  • instanceofตรวจสอบว่าการอ้างอิงวัตถุทางด้านซ้ายเป็นอินสแตนซ์ประเภททางด้านขวาหรือประเภทย่อยบางประเภท

  • getClass() == ... ตรวจสอบเอกลักษณ์ประเภท

นั่นคือ หากgetClass()ตรวจสอบตัวตนที่สมบูรณ์ของคลาส แล้วinstanceofจะคืนค่าเป็นจริงแม้ว่าอ็อบเจ็กต์นั้นจะเป็นเพียงชนิดย่อย ซึ่งสามารถทำให้เรามีความยืดหยุ่นมากขึ้นเมื่อใช้ polymorphism อย่างจริงจัง จริงๆ แล้วทั้งสองวิธีเป็นสิ่งที่ดีหากคุณเข้าใจคุณลักษณะของงานและนำไปใช้ในตำแหน่งที่ถูกต้อง

104. ให้คำอธิบายสั้น ๆ เกี่ยวกับเมธอด clone()

Clone()เป็นวิธีการของ คลาส Objectโดยมีวัตถุประสงค์เพื่อสร้างและส่งคืนโคลนของวัตถุปัจจุบัน (สำเนาของวัตถุปัจจุบัน) การวิเคราะห์คำถามและคำตอบจากการสัมภาษณ์นักพัฒนา Java  ตอนที่ 11 - 4หากต้องการใช้งาน คุณจะต้องใช้ อินเทอร์เฟซ Cloneable marker :
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ถูกใช้ในส่วนหัวของวิธีการเพื่อระบุข้อยกเว้นที่อาจเกิดขึ้นจากวิธีการนั้น นั่นคือนี่คือกลไกในการ "ทิ้ง" ข้อยกเว้นลงในวิธีการข้างต้น Uncheckedเป็นข้อยกเว้นประเภทหนึ่งที่ไม่จำเป็นต้องได้รับการจัดการ และโดยทั่วไปคาดเดาได้น้อยกว่าและมีโอกาสเกิดขึ้นน้อย อย่างไรก็ตาม สามารถดำเนินการได้หากต้องการ Throwใช้ในการส่งข้อยกเว้นด้วยตนเอง เช่น:
throw new Exception();

108. ลำดับชั้นของข้อยกเว้นคืออะไร?

ลำดับชั้นของข้อยกเว้นนั้นใหญ่มากและกว้างขวาง กว้างขวางเกินกว่าจะเล่าทุกอย่างเกี่ยวกับเรื่องนี้ที่นี่ ดังนั้นเราจะพิจารณาเฉพาะลิงก์ที่สำคัญเท่านั้น: การวิเคราะห์คำถามและคำตอบจากการสัมภาษณ์นักพัฒนา Java  ตอนที่ 11 - 6ที่ด้านบนสุดของลำดับชั้นเราจะเห็นคลาส - Throwable - คลาสทั่วไปซึ่งเป็นบรรพบุรุษของลำดับชั้นข้อยกเว้นซึ่งจะแบ่งออกเป็น:
  • ข้อผิดพลาด - ข้อผิดพลาดร้ายแรงและไม่สามารถตรวจสอบได้
  • ข้อยกเว้น - ตรวจสอบข้อยกเว้นแล้ว
ข้อยกเว้นแบ่งออกเป็นข้อยกเว้นรันไทม์ที่ไม่ได้ตรวจสอบต่างๆ และข้อยกเว้นที่ได้รับการตรวจสอบต่างๆ

109. อะไรคือข้อยกเว้นที่ถูกตรวจสอบและไม่ถูกตรวจสอบ?

อย่างที่ฉันพูดไปก่อนหน้านี้:
  • ตรวจสอบ - ข้อยกเว้นที่คุณต้องจัดการนั่นคือประมวลผลพวกมันในtry - catch block หรือ "ส่งต่อ" ไปยังวิธีการข้างต้น ในการดำเนินการนี้ ในลายเซ็นเมธอด หลังจากแสดงรายการอาร์กิวเมนต์ของเมธอดแล้ว คุณต้องใช้ คีย์เวิร์ดtrows <ประเภทข้อยกเว้น>ซึ่งระบุให้ผู้ใช้ทราบว่าเมธอดดังกล่าวสามารถส่งข้อยกเว้นนี้ (บางอย่างเช่นคำเตือน) และถ่ายโอน ความรับผิดชอบในการจัดการข้อยกเว้นสำหรับผู้ใช้วิธีนี้

  • ไม่ถูกตรวจสอบ - ข้อยกเว้นที่ไม่จำเป็นต้องได้รับการจัดการ เนื่องจากไม่ได้ตรวจสอบ ณ เวลาคอมไพล์ และตามกฎแล้วจะคาดเดาไม่ได้มากกว่า นั่นคือความแตกต่างที่สำคัญกับการตรวจสอบก็คือ กลไก การลองจับหรือการขว้างเหล่านี้ทำงานเหมือนกันสำหรับพวกเขา แต่ไม่ได้บังคับ

101. เขียนตัวอย่างการสกัดกั้นและการจัดการข้อยกเว้นในบล็อก try-catch ของวิธีการ

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

102. เขียนตัวอย่างการจับและจัดการข้อยกเว้นโดยใช้ข้อยกเว้นของคุณเอง

ขั้นแรก เรามาเขียนคลาสข้อยกเว้นของเราเอง ซึ่งสืบทอดมาจากExceptionและแทนที่ Constructor ด้วยข้อความแสดงข้อผิดพลาด:
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