JavaRush /จาวาบล็อก /Random-TH /จาวาคอร์ คำถามสัมภาษณ์งาน ตอนที่ 3
Vadim625
ระดับ

จาวาคอร์ คำถามสัมภาษณ์งาน ตอนที่ 3

เผยแพร่ในกลุ่ม
ในสองบทความก่อนหน้านี้ เราได้พูดคุยถึงคำถามสำคัญบางข้อที่คุณมักถูกถามบ่อยที่สุดในการสัมภาษณ์ ถึงเวลาที่จะดำเนินการต่อและดูคำถามที่เหลือ
จาวาคอร์  คำถามสัมภาษณ์ ตอนที่ 3 - 1

การคัดลอกแบบลึกและการคัดลอกแบบตื้น

สำเนาต้นฉบับที่ถูกต้องคือโคลนของมัน ใน Java นี่หมายถึงความสามารถในการสร้างวัตถุที่มีโครงสร้างคล้ายกับวัตถุดั้งเดิม วิธีการนี้clone()มีฟังก์ชันการทำงานนี้ การคัดลอกแบบตื้นคัดลอกข้อมูลให้น้อยที่สุด ตามค่าเริ่มต้น การโคลนนิ่งใน Java เป็นแบบตื้น เช่น Object classไม่รู้เกี่ยวกับโครงสร้างของคลาสที่กำลังคัดลอก เมื่อทำการโคลน JVM จะดำเนินการดังต่อไปนี้:
  1. หากคลาสมีเพียงสมาชิกของประเภทดั้งเดิม สำเนาใหม่ของออบเจ็กต์จะถูกสร้างขึ้นและการอ้างอิงถึงออบเจ็กต์นั้นจะถูกส่งกลับ
  2. หากคลาสไม่เพียงมีสมาชิกของประเภทดั้งเดิมเท่านั้น แต่ยังรวมถึงสมาชิกของประเภทคลาสอื่นด้วย การอ้างอิงไปยังออบเจ็กต์ของคลาสเหล่านี้จะถูกคัดลอก ดังนั้นวัตถุทั้งสองจะมีการอ้างอิงที่เหมือนกัน
การคัดลอกแบบลึกจะทำซ้ำทุกสิ่ง การทำสำเนาแบบลึกคือสองคอลเลกชั่น โดยหนึ่งในนั้นจะทำซ้ำองค์ประกอบทั้งหมดของคอลเลกชั่นดั้งเดิม เราต้องการทำสำเนาโดยที่การเปลี่ยนแปลงองค์ประกอบใดๆ ของสำเนาจะไม่ส่งผลกระทบต่อคอลเลกชันต้นฉบับ การโคลนนิ่งแบบลึกต้องใช้กฎต่อไปนี้:
  1. ไม่จำเป็นต้องคัดลอกข้อมูลดั้งเดิมแยกกัน
  2. คลาสสมาชิกทั้งหมดในคลาสดั้งเดิมต้องรองรับการโคลนนิ่ง สำหรับสมาชิกคลาสแต่ละคน จะต้องถูกเรียกsuper.clone()เมื่อเมธอดถูกแทนที่clone();
  3. หากสมาชิกของคลาสไม่รองรับการโคลน ดังนั้นในวิธีการโคลน คุณจะต้องสร้างอินสแตนซ์ใหม่ของคลาสนั้นและคัดลอกสมาชิกแต่ละคนพร้อมคุณสมบัติทั้งหมดไปยังอ็อบเจ็กต์คลาสใหม่ ทีละตัว
ค้นหาข้อมูลเพิ่มเติมเกี่ยวกับการโคลนนิ่งได้ที่นี่

การซิงโครไนซ์คืออะไร? การล็อคระดับวัตถุและการล็อคระดับคลาส?

การซิงโครไนซ์หมายถึงมัลติเธรด บล็อกโค้ดที่ซิงโครไนซ์สามารถดำเนินการได้ครั้งละหนึ่งเธรดเท่านั้น Java ช่วยให้คุณสามารถประมวลผลหลายเธรดพร้อมกันได้ ซึ่งอาจส่งผลให้มีเธรดตั้งแต่สองเธรดขึ้นไปต้องการเข้าถึงฟิลด์เดียวกัน การซิงโครไนซ์ช่วยหลีกเลี่ยงข้อผิดพลาดของหน่วยความจำที่เกิดขึ้นเมื่อใช้ทรัพยากรหน่วยความจำอย่างไม่ถูกต้อง เมื่อมีการประกาศวิธีการซิงโครไนซ์ เธรดจะเก็บมอนิเตอร์ไว้ หากเธรดอื่นพยายามเข้าถึงวิธีการซิงโครไนซ์ในขณะนี้ เธรดนั้นจะถูกบล็อกและรอให้จอภาพว่าง การซิงโครไนซ์ใน Java ทำได้สำเร็จด้วยคีย์เวิร์ด ซิงโครไนซ์ พิเศษ คุณสามารถทำเครื่องหมายแต่ละบล็อกหรือวิธีการในชั้นเรียนของคุณได้ด้วยวิธีนี้ คำสำคัญที่ซิงโครไนซ์ไม่สามารถใช้ร่วมกับตัวแปรคลาสหรือคุณลักษณะได้ การล็อกระดับออบเจ็กต์เป็นกลไกเมื่อคุณต้องการซิงโครไนซ์วิธีการที่ไม่คงที่หรือบล็อกโค้ดที่ไม่คงที่เพื่อให้เธรดเดียวเท่านั้นที่สามารถดำเนินการบล็อกของโค้ดบนอินสแตนซ์ที่กำหนดของคลาสได้ สิ่งนี้ควรทำเสมอเพื่อทำให้เธรดอินสแตนซ์ของคลาสปลอดภัย การล็อกระดับคลาสจะป้องกันไม่ให้เธรดจำนวนมากเข้าสู่บล็อกที่ซิงโครไนซ์สำหรับอินสแตนซ์ที่มีอยู่ทั้งหมดของคลาส ตัวอย่างเช่น หากมี 100 อินสแตนซ์ของคลาส DemoClass จะมีเพียง 1 เธรดเท่านั้นที่จะสามารถดำเนินการ demoMethod() โดยใช้ตัวแปรตัวใดตัวหนึ่งในเวลาที่กำหนด สิ่งนี้ควรทำเสมอเพื่อความปลอดภัยของเธรดแบบคงที่ เรียนรู้เพิ่มเติมเกี่ยวกับการซิงโครไนซ์ที่นี่

ความแตกต่างระหว่าง sleep() และ wait() คืออะไร?

Sleep()เป็นวิธีการที่ใช้ในการชะลอกระบวนการไม่กี่วินาที ในกรณีของwait()เธรดจะอยู่ในสถานะรอจนกว่าเราจะเรียกเมธอดnotify()or notifyAll()ข้อแตกต่างที่สำคัญคือwait()จะปลดล็อคจอภาพในขณะที่sleep()ไม่ได้ปลดล็อค Wait()ใช้สำหรับแอปพลิเคชันแบบมัลติเธรดsleep()ใช้เพื่อหยุดการทำงานของเธรดชั่วคราว Thread.sleep()ทำให้เธรดปัจจุบันอยู่ในสถานะ "ไม่สามารถรันได้" เป็นระยะเวลาหนึ่ง เธรดจะบันทึกสถานะของจอภาพที่เคยเป็นก่อนที่จะเรียกเมธอดนี้ หากมีการเรียกเธรดอื่นt.interrupt()เธรดที่ "หลับ" จะถูกปลุกขึ้นมา โปรดทราบว่านี่sleep()เป็นวิธีคงที่ ซึ่งหมายความว่าจะส่งผลต่อเธรดปัจจุบันเสมอ (วิธีดำเนินการ method sleep()) ข้อผิดพลาดทั่วไปคือการเรียกt.sleep()Where tis another thread; แม้ว่าเธรดปัจจุบันที่เรียกว่าเมธอดsleep()จะไม่ใช่tเธรดก็ตาม Object.wait()ส่งเธรดปัจจุบันเข้าสู่สถานะ "Not Runnable" ชั่วขณะหนึ่ง เช่นเดียวกับsleep()แต่มีความแตกต่างกันเล็กน้อย Wait()เรียกบนวัตถุ ไม่ใช่เธรด เราเรียกวัตถุนี้ว่า "วัตถุล็อค" ก่อนที่จะโทรlock.wait()เธรดปัจจุบันจะต้องซิงโครไนซ์กับ "วัตถุล็อค"; wait()หลังจากนั้นจะปลดล็อกนี้ และเพิ่มเธรดลงใน "รายการรอ" ที่เกี่ยวข้องกับการล็อกนี้ ต่อมา เธรดอื่นสามารถซิงโครไนซ์กับอ็อบเจ็กต์ล็อคเดียวกันและเรียกใช้ไฟล์lock.notify(). วิธีนี้จะ "ปลุก" เธรดเดิมที่ยังรออยู่ ตามหลักการแล้วwait()/ notify()สามารถเปรียบเทียบได้กับsleep()/ interrupt()เฉพาะเธรดที่ใช้งานอยู่เท่านั้นที่ไม่ต้องการตัวชี้โดยตรงไปยังเธรดที่กำลังหลับ เพียงแต่จำเป็นต้องรู้อ็อบเจ็กต์การล็อกที่แชร์เท่านั้น อ่านรายละเอียดความแตกต่างได้ที่นี่

เป็นไปได้ไหมที่จะกำหนดค่าว่างให้กับตัวแปรอ้างอิง?

ไม่คุณไม่สามารถ. ใน Java ทางด้านซ้ายของตัวดำเนินการกำหนดจะต้องเป็นตัวแปร "This" เป็นคีย์เวิร์ดพิเศษที่ให้อินสแตนซ์ปัจจุบันของคลาสเสมอ มันไม่ใช่แค่ตัวแปรใดๆ ในทำนองเดียวกัน ไม่สามารถกำหนด null ให้กับตัวแปรโดยใช้คีย์เวิร์ด "super" หรือคีย์เวิร์ดอื่นๆ ที่คล้ายกัน

&& และ & && ต่างกันอย่างไร?

&- ระดับบิตและ&&- เชิงตรรกะ
  1. &ประเมินการดำเนินงานทั้งสองด้าน
  2. &&ประเมินด้านซ้ายของการดำเนินการ หากเป็นจริงก็ประเมินฝั่งขวาต่อไป
ดูที่นี่เพื่อความเข้าใจที่ลึกซึ้งยิ่งขึ้น

จะแทนที่วิธีเท่ากับ () และ hachCode () ได้อย่างไร

hashCode()และequals()วิธีการถูกกำหนดไว้ในคลาสObjectซึ่งเป็นคลาสพาเรนต์สำหรับอ็อบเจ็กต์ Java ด้วยเหตุนี้ ออบเจ็กต์ Java ทั้งหมดจึงสืบทอดการใช้งานเริ่มต้นสำหรับเมธอด วิธีการนี้hashCode()ใช้เพื่อให้ได้จำนวนเต็มเฉพาะสำหรับวัตถุที่กำหนด จำนวนเต็มนี้ใช้เพื่อกำหนดตำแหน่งของวัตถุเมื่อจำเป็นต้องจัดเก็บวัตถุนั้นHashTableเช่น ตามค่าเริ่มต้นhashCode()ส่งคืนintegerการแสดงที่อยู่ของตำแหน่งหน่วยความจำที่จัดเก็บออบเจ็กต์ วิธีการequls()ตามชื่อของมัน ใช้เพื่อทดสอบว่าวัตถุสองชิ้นเท่ากันหรือไม่ การใช้งานเริ่มต้นจะตรวจสอบการอ้างอิงออบเจ็กต์เพื่อดูว่าเท่ากันหรือไม่ ด้านล่างนี้เป็นแนวทางที่สำคัญสำหรับการโหลดวิธีการเหล่านี้ซ้ำ:
  1. ใช้แอตทริบิวต์ของวัตถุเดียวกันเสมอเมื่อสร้างhashCode()และequals();
  2. สมมาตร. เหล่านั้น. xถ้า มัน คืนค่าจริง สำหรับบางอ็อบเจ็กต์y x.equals(y)ก็y.equals(x)ควรคืนค่าจริง
  3. สะท้อนแสง สำหรับวัตถุใด ๆx x.equals(x)จะต้องคืนค่าจริง
  4. ความสม่ำเสมอ สำหรับวัตถุใด ๆxและy x.equals(y)ส่งกลับสิ่งเดียวกันหากข้อมูลที่ใช้ในการเปรียบเทียบไม่เปลี่ยนแปลง
  5. การขนส่ง สำหรับอ็อบเจ็กต์ใดๆxและถ้ามันคืนค่าจริงและส่งกลับค่าจริง ก็ ควรจะ yคืนค่าจริงzx.equals(y)y.equals(z)x.equals(z)
  6. เมื่อใดก็ตามที่มีการเรียกใช้เมธอดบนออบเจ็กต์เดียวกันระหว่างการทำงานของแอปพลิเคชัน ก็ควรส่งคืนหมายเลขเดียวกัน เว้นแต่ว่าข้อมูลที่ใช้จะเปลี่ยนแปลง hashCodeสามารถคืนค่าที่แตกต่างกันสำหรับวัตถุที่เหมือนกันในอินสแตนซ์ของแอปพลิเคชันที่แตกต่างกัน
  7. หากวัตถุสองชิ้นมีค่าเท่ากัน ตามนั้นequalsวัตถุทั้งสองhashCodeจะต้องส่งคืนค่าเดียวกัน
  8. ข้อกำหนดตรงกันข้ามเป็นทางเลือก วัตถุสองวัตถุที่ไม่เท่ากันสามารถส่งคืน hashCode เดียวกันได้ อย่างไรก็ตาม เพื่อปรับปรุงประสิทธิภาพ ควรให้อ็อบเจ็กต์ที่แตกต่างกันส่งคืนโค้ดที่แตกต่างกันจะดีกว่า
อ่านข้อเท็จจริงที่น่าสนใจเกี่ยวกับวิธีการเหล่านี้ได้ที่นี่

บอกเราเกี่ยวกับตัวแก้ไขการเข้าถึง

คลาส Java, ฟิลด์, ตัวสร้าง และเมธอดสามารถมีหนึ่งในสี่ตัวดัดแปลงการเข้าถึงที่แตกต่างกัน: ไพรเวท หากเมธอดหรือตัวแปรถูกทำเครื่องหมายเป็นไพรเวท เฉพาะโค้ดภายในคลาสเดียวกันเท่านั้นที่สามารถเข้าถึงตัวแปร หรือเรียกเมธอดนั้นได้ โค้ดภายในคลาสย่อยไม่สามารถเข้าถึงตัวแปรหรือเมธอด และไม่สามารถเข้าถึงได้จากคลาสอื่น ตัวแก้ไขการเข้าถึงส่วนตัวมักใช้สำหรับตัวสร้าง วิธีการ และตัวแปร ค่าเริ่มต้น ตัวแก้ไขการเข้าถึงเริ่มต้นจะถูกประกาศหากไม่ได้ระบุตัวแก้ไขเลย ตัวแก้ไขนี้หมายความว่าการเข้าถึงฟิลด์ ตัวสร้าง และวิธีการของคลาสที่กำหนดสามารถรับได้โดยโค้ดภายในคลาสนั้นเอง โค้ดภายในคลาสในแพ็คเกจเดียวกัน คลาสย่อยไม่สามารถเข้าถึงเมธอดและตัวแปรสมาชิกของซูเปอร์คลาสได้ หากถูกประกาศเป็นค่าเริ่มต้นเว้นแต่คลาสย่อยจะอยู่ในแพ็คเกจเดียวกันกับซูเปอร์คลาส protected ตัวดัดแปลงที่ได้รับการป้องกันทำงานเหมือนกับdefaultยกเว้นว่าคลาสย่อยยังสามารถเข้าถึงเมธอดและตัวแปรที่ได้รับการป้องกันของซูเปอร์คลาสได้ คำสั่งนี้เป็นจริงแม้ว่าคลาสย่อยจะไม่ได้อยู่ในแพ็คเกจเดียวกันกับซูเปอร์คลาสก็ตาม public ตัวแก้ไขการเข้าถึงสาธารณะหมายความว่าโค้ดทั้งหมดสามารถเข้าถึงคลาส ตัวแปร ตัวสร้าง หรือเมธอดได้ โดยไม่คำนึงว่าโค้ดนั้นจะอยู่ที่ใด จาวาคอร์  คำถามสัมภาษณ์ ตอนที่ 3 - 2

คนเก็บขยะคืออะไร? เราโทรหาเขาได้ไหม?

Garbage Collection เป็นฟีเจอร์หนึ่งของการจัดการหน่วยความจำอัตโนมัติในภาษาโปรแกรมสมัยใหม่หลายๆ ภาษา เช่น Java และภาษาต่างๆ ใน ​​NET.Framework ภาษาที่ใช้การรวบรวมขยะมักจะตีความการรวบรวมขยะในเครื่องเสมือนเช่น JVM การรวบรวมขยะมีวัตถุประสงค์สองประการ: หน่วยความจำที่ไม่ได้ใช้ควรถูกทำให้ว่าง และหน่วยความจำไม่ควรถูกทำให้ว่างหากโปรแกรมยังคงใช้งานอยู่ คุณสามารถเรียกใช้การรวบรวมขยะด้วยตนเองได้หรือไม่? ไม่System.gc()มันช่วยให้คุณเข้าถึงได้มากที่สุดเท่าที่จะเป็นไปได้ ตัวเลือกที่ดีที่สุดคือการเรียกเมธอดSystem.gc()ซึ่งจะบอกใบ้ให้ตัวรวบรวมขยะจำเป็นต้องเรียกใช้ ไม่มีวิธีรันทันทีเนื่องจากตัวรวบรวมขยะไม่สามารถกำหนดได้ นอกจากนี้ ตามเอกสารประกอบOutOfMemoryErrorจะไม่มีการส่งต่อหากเครื่องเสมือนล้มเหลวในการเพิ่มหน่วยความจำหลังจากการรวบรวมขยะทั้งหมด เรียนรู้เพิ่มเติมเกี่ยวกับตัวเก็บขยะที่นี่

คำหลักพื้นเมืองหมายถึงอะไร? อธิบายอย่างละเอียด

คำหลักเนทิ ฟ ใช้เพื่อระบุว่ามีการใช้วิธีนี้ในภาษาการเขียนโปรแกรมอื่นที่ไม่ใช่ไฟล์ Java วิธีการ ดั้งเดิมถูกนำมาใช้ในอดีต ใน Java เวอร์ชันปัจจุบัน สิ่งนี้จำเป็นน้อยลง ปัจจุบันจำเป็นต้องใช้วิธีการดั้งเดิมเมื่อ:
  1. คุณต้องเรียกไลบรารีจาก Java ที่เขียนในภาษาอื่น
  2. คุณต้องเข้าถึงทรัพยากรระบบหรือฮาร์ดแวร์ที่สามารถเข้าถึงได้โดยใช้ภาษาอื่นเท่านั้น (โดยปกติคือ C) ในความเป็นจริง ฟังก์ชันระบบหลายอย่างที่โต้ตอบกับคอมพิวเตอร์จริง (เช่น ดิสก์หรือข้อมูลเครือข่าย) สามารถเรียกได้โดยวิธีการดั้งเดิมเท่านั้น
ข้อเสียของการใช้ ไลบรารีเมธอดเน ทีฟ ก็มีความสำคัญเช่นกัน:
  1. JNI/JNA อาจทำให้ JVM ไม่เสถียร โดยเฉพาะอย่างยิ่งหากคุณพยายามทำสิ่งที่ซับซ้อน หากวิธีดั้งเดิมของคุณทำสิ่งผิดปกติ มีความเป็นไปได้ที่ JVM จะขัดข้อง นอกจากนี้ สิ่งเลวร้ายอาจเกิดขึ้นได้หากวิธีดั้งเดิมของคุณถูกเรียกจากหลายเธรด และอื่นๆ
  2. การดีบัก โปรแกรมด้วยโค้ดเนทีฟ นั้นยากกว่า
  3. โค้ดแบบเนทีฟต้องมีการสร้างเฟรมเวิร์กแยกต่างหาก ซึ่งอาจทำให้เกิดปัญหาในการพอร์ตไปยังแพลตฟอร์มอื่นได้

การทำให้เป็นอนุกรมคืออะไร?

ในวิทยาการคอมพิวเตอร์ ในบริบทของการจัดเก็บและการส่งข้อมูล การทำให้เป็นอนุกรมเป็นกระบวนการแปลโครงสร้างข้อมูลหรือสถานะของออบเจ็กต์ให้อยู่ในรูปแบบที่สามารถจัดเก็บและเรียกค้นได้ในภายหลังในสภาพแวดล้อมการประมวลผลอื่น หลังจากได้รับชุดของบิตแล้ว บิตเหล่านั้นจะถูกคำนวณใหม่ตามรูปแบบการทำให้เป็นอนุกรม และสามารถใช้เพื่อสร้างโคลนที่เหมือนกันทางความหมายของออบเจ็กต์ต้นฉบับได้ Java จัดให้มีการทำให้เป็นอนุกรมอัตโนมัติ ซึ่งต้องใช้อ็อบเจ็กต์เพื่อใช้อินเทอร์เฟjava.io.Serializableซ การใช้งานอินเทอร์เฟซทำเครื่องหมายคลาสว่า "ต่อเนื่องได้" อินเทอร์เฟซ java.io.Serializable ไม่มีวิธีการทำให้เป็นอนุกรม แต่คลาสที่ทำให้เป็นอนุกรมสามารถเลือกกำหนดวิธีการที่จะเรียกว่าเป็นส่วนหนึ่งของกระบวนการทำให้เป็นอนุกรม/กระจายการซีเรียลไลซ์ได้ เมื่อทำการเปลี่ยนแปลงคลาส คุณต้องพิจารณาว่าคลาสใดจะเข้ากันได้กับซีเรียลไลซ์ คุณสามารถอ่านคำแนะนำแบบเต็มได้ที่นี่ ฉันจะให้คะแนนที่สำคัญที่สุด: การเปลี่ยนแปลงที่เข้ากันไม่ได้:
  1. ลบฟิลด์;
  2. ย้ายชั้นเรียนขึ้นหรือลงในลำดับชั้น
  3. การเปลี่ยนฟิลด์ที่ไม่คงที่เป็นแบบคงที่หรือแบบไม่ชั่วคราวเป็นชั่วคราว
  4. การเปลี่ยนชนิดข้อมูลดั้งเดิมที่ประกาศ
  5. การเปลี่ยนวิธีการเพื่อไม่ให้เขียนหรืออ่านฟิลด์ตามค่าเริ่มต้นอีกต่อWriteObjectไปReadObject
  6. การเปลี่ยนชั้นเรียนSerializableเป็นExternalizableหรือในทางกลับกัน
  7. การเปลี่ยน คลาส enumเป็นnon-enumหรือในทางกลับกัน
  8. การถอดSerializableหรือExternalizable;
  9. การเพิ่มwriteReplaceวิธี การให้ readResolveกับชั้นเรียน
การเปลี่ยนแปลงที่เข้ากันได้:
  1. การเพิ่มฟิลด์;
  2. การเพิ่ม/ลบคลาส;
  3. การเพิ่มเมธอดWriteObject/ReadObject[วิธีการdefaultReadObjectหรือdefaultWriteObjectต้องเรียกตอนต้น];
  4. วิธีการลบWriteObject/ReadObject;
  5. ส่วนที่เพิ่มเข้าไปjava.io.Serializable;
  6. การเปลี่ยนแปลงการเข้าถึงสนาม
  7. การเปลี่ยน ฟิลด์ สแตติกเป็นแบบไม่คงที่หรือชั่วคราวเป็นไม่ชั่วคราว
ลิงก์ไปยังส่วนก่อนหน้า: Java Core คำถามสัมภาษณ์ ตอนที่ 1 Java Core คำถามสัมภาษณ์ ตอนที่ 2 บทความต้นฉบับ เรียนอย่างมีความสุข!
ความคิดเห็น
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION