CodeGym /จาวาบล็อก /สุ่ม /คำถามและคำตอบสัมภาษณ์งาน 50 อันดับแรกสำหรับ Java Core ส่ว...
John Squirrels
ระดับ
San Francisco

คำถามและคำตอบสัมภาษณ์งาน 50 อันดับแรกสำหรับ Java Core ส่วนที่ 1

เผยแพร่ในกลุ่ม
สวัสดีทุกท่าน ท่านสุภาพบุรุษและสุภาพสตรี วิศวกรซอฟต์แวร์! พูดคุยเกี่ยวกับคำถามสัมภาษณ์ เกี่ยวกับสิ่งที่คุณต้องเตรียมและสิ่งที่คุณต้องรู้ นี่เป็นเวลาที่ดีในการทบทวนหรือศึกษาประเด็นเหล่านี้เป็นครั้งแรก คำถามและคำตอบสัมภาษณ์งาน 50 อันดับแรกสำหรับ Java Core  ตอนที่ 1 - 1 ฉันลงเอยด้วยการรวบรวมคำถามที่พบบ่อยเกี่ยวกับ OOP, ไวยากรณ์ของ Java, ข้อยกเว้นของ Java, คอลเลกชัน และมัลติเธรด ซึ่งฉันจะแบ่งออกเป็นหลายส่วนเพื่อความสะดวก เป็นเรื่องยากที่จะครอบคลุมทุกอย่างในคราวเดียว แต่ฉันหวังว่าเนื้อหานี้จะเป็นพื้นฐานที่ดีสำหรับผู้ที่เตรียมตัวหางานแรกในฐานะโปรแกรมเมอร์ เพื่อความเข้าใจและการเก็บรักษาที่ดีที่สุด ฉันแนะนำให้ค้นหาแหล่งข้อมูลอื่นๆ เช่นกัน คุณสามารถเข้าใจแนวคิดได้ลึกซึ้งยิ่งขึ้นโดยเข้าใกล้แนวคิดนั้นจากหลายๆ มุม สำคัญ:เราจะพูดถึง Java ก่อนเวอร์ชัน 8 เท่านั้น นวัตกรรมทั้งหมดที่มาในเวอร์ชัน 9, 10, 11, 12 และ 13 จะไม่นำมาพิจารณาที่นี่ ยินดีต้อนรับความคิด / ความคิดเห็นใด ๆ เกี่ยวกับวิธีการปรับปรุงคำตอบ สนุกกับการอ่านของคุณ ไปกันเถอะ!

สัมภาษณ์ Java: คำถามเกี่ยวกับ OOP

1. Java มีลักษณะเด่นอย่างไร

คำตอบ:
  1. แนวคิด OOP:

    1. การวางแนววัตถุ
    2. มรดก
    3. การห่อหุ้ม
    4. ความหลากหลาย
    5. สิ่งที่เป็นนามธรรม
  2. ข้ามแพลตฟอร์ม:โปรแกรม Java สามารถรันบนแพลตฟอร์มใดก็ได้โดยไม่มีการเปลี่ยนแปลงใดๆ แน่นอนว่าต้องติดตั้ง JVM (เครื่องเสมือน Java)

  3. ประสิทธิภาพสูง:คอมไพเลอร์ Just-In-Time (JIT) ทำให้ประสิทธิภาพสูงเป็นไปได้ คอมไพเลอร์ JIT แปลง bytecode เป็นรหัสเครื่อง จากนั้น JVM จะเริ่มดำเนินการ

  4. มัลติเธรด: JVM สร้างเธรดการดำเนินการที่เรียกว่าmain thread. โปรแกรมเมอร์สามารถสร้างหลายเธรดโดยได้รับจากคลาสเธรดหรือใช้Runnableอินเทอร์เฟซ

2. มรดกคืออะไร?

การสืบทอดหมายความว่าคลาสหนึ่งสามารถสืบทอดคลาสอื่นได้ (โดยใช้ คำสำคัญ ขยาย ) ซึ่งหมายความว่าคุณสามารถใช้โค้ดจากคลาสที่คุณสืบทอดมาซ้ำได้ คลาสที่มีอยู่เรียกว่า the superclassและคลาสที่สร้างขึ้นใหม่คือ the subclass. ผู้คนยังพูดว่าใช้คำว่า parent childและ

public class Animal {
   private int age;
}

public class Dog extends Animal {

}
Animalอยู่ ที่ไหนparentและDogคือchild.

3. การห่อหุ้มคืออะไร?

คำถามนี้มักถูกถามในการสัมภาษณ์สำหรับตำแหน่งนักพัฒนา Java Encapsulationกำลังซ่อนการใช้งานโดยใช้ตัวดัดแปลงการเข้าถึง ตัวรับ และตัวตั้งค่า สิ่งนี้ทำเพื่อป้องกันการเข้าถึงจากภายนอกในทุกที่ที่นักพัฒนาคิดว่าจำเป็น ตัวอย่างง่ายๆ จากชีวิตจริงคือรถยนต์ เราไม่สามารถเข้าถึงการทำงานของเครื่องยนต์ได้โดยตรง สิ่งที่เราต้องทำคือใส่กุญแจเข้าไปในสวิตช์กุญแจแล้วเปิดเครื่องยนต์ กระบวนการที่เกิดขึ้นภายใต้ประทุนไม่ใช่ธุรกิจของเรา ยิ่งไปกว่านั้น หากเราไปแทรกแซงการทำงานของเครื่องยนต์ อาจนำไปสู่สถานการณ์ที่คาดเดาไม่ได้ อาจทำให้รถเสียหายและส่งผลเสียต่อร่างกายได้ สิ่งเดียวกันนี้เกิดขึ้นในการเขียนโปรแกรม สิ่งนี้อธิบายได้ดีในวิกิพีเดีย. นอกจากนี้ยังมีบทความเกี่ยวกับการห่อหุ้มบน CodeGym

4. ความหลากหลายคืออะไร?

ความแตกต่างคือความสามารถของโปรแกรมในการจัดการกับวัตถุด้วยอินเทอร์เฟซเดียวกันในลักษณะเดียวกัน โดยไม่มีข้อมูลเกี่ยวกับประเภทเฉพาะของวัตถุ ดังคำกล่าวที่ว่า "อินเทอร์เฟซเดียว — ใช้งานได้หลายอย่าง" ด้วยความหลากหลาย คุณสามารถรวมและใช้วัตถุประเภทต่างๆ ตามพฤติกรรมที่ใช้ร่วมกันได้ ตัวอย่างเช่น เรามีคลาสสัตว์ที่มีลูกหลานสองคน: สุนัขและแมว คลาสสัตว์ทั่วไปมีพฤติกรรมร่วมกันคือความสามารถในการส่งเสียง เราใช้ความสามารถแบบ polymorphic เมื่อเราต้องการรวบรวมทุกอย่างที่สืบทอดคลาส Animal และเรียกใช้เมธอด "make sound" นี่คือลักษณะ:

List<Animal> animals = Arrays.asList(new Cat(), new Dog(), new Cat());
animals.forEach(animal -> animal.makeSound());
กล่าวอีกนัยหนึ่งความหลากหลายนั้นมีประโยชน์ และยังใช้กับวิธี polymorphic (โอเวอร์โหลด) วิธีการใช้ความหลากหลาย

คำถามสัมภาษณ์เกี่ยวกับไวยากรณ์ Java

5. Constructor ใน Java คืออะไร?

ตัวสร้างมีคุณสมบัติดังต่อไปนี้:
  1. เมื่อวัตถุใหม่ถูกสร้างขึ้น โปรแกรมจะใช้ตัวสร้างที่เหมาะสมในการสร้างวัตถุนั้น
  2. ตัวสร้างเป็นเหมือนวิธีการ คุณสมบัติที่โดดเด่นของมันอยู่ที่ความจริงที่ว่าไม่มีค่าส่งคืน (รวมถึงโมฆะ) และชื่อนั้นเหมือนกับชื่อของคลาส
  3. หากไม่มีการสร้างตัวสร้างอย่างชัดเจน ตัวสร้างว่างจะถูกสร้างขึ้นโดยอัตโนมัติ
  4. ตัวสร้างสามารถถูกแทนที่ได้
  5. หากคุณประกาศตัวสร้างพร้อมพารามิเตอร์แต่ต้องการตัวสร้างที่ไม่มีพารามิเตอร์ด้วย คุณต้องสร้างตัวสร้างแยกต่างหาก เนื่องจากตัวสร้างจะไม่ถูกสร้างขึ้นโดยอัตโนมัติ

6. คลาส 2 คลาสใดที่ไม่สืบทอด Object

อย่าถูกหลอกด้วยคำถามหลอกลวง — ไม่มีชั้นเรียนแบบนี้ คลาสทั้งหมดสืบทอดคลาส Object ไม่ว่าจะโดยตรงหรือผ่านบรรพบุรุษ!

7. ตัวแปรท้องถิ่นคืออะไร?

นี่เป็นอีกหนึ่งคำถามสัมภาษณ์ยอดนิยมสำหรับนักพัฒนา Java ตัวแปรโลคัลคือตัวแปรที่กำหนดภายในเมธอดและมีอยู่ตราบเท่าที่เมธอดนั้นถูกเรียกใช้งาน ทันทีที่การดำเนินการสิ้นสุดลง ตัวแปรโลคัลจะหยุดอยู่ นี่คือโปรแกรมที่ใช้ตัวแปรโลคัลชื่อ helloMessage ในเมธอด main():

public static void main(String[] args) {
   String helloMessage;
   helloMessage = "Hello, World!";
   System.out.println(helloMessage);
}

8. ตัวแปรอินสแตนซ์คืออะไร?

ตัวแปรอินสแตนซ์คือตัวแปรที่ประกาศภายในคลาส มันมีอยู่ตราบเท่าที่มีวัตถุอยู่ ตัวอย่างเช่น เรามีคลาส Bee ซึ่งมีตัวแปรอินสแตนซ์สองตัว — เนคทาร์โหลด และ maxNectarLoad:

public class Bee {

   /**
    * Current nectar load
    */
   private double nectarLoad;

   /**
    * Maximum nectar that can the bee can collect.
    */
   private double maxNectarLoad = 20.0;
 
  ...
}

9. ตัวดัดแปลงการเข้าถึงคืออะไร?

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

10. วิธีการเอาชนะคืออะไร?

เราลบล้างเมธอดเมื่อคลาสลูกต้องการเปลี่ยนพฤติกรรมของคลาสพาเรนต์ หากเราต้องทำสิ่งที่อยู่ในเมธอดพาเรนต์ เราสามารถใช้ super.methodName() ในลูก ซึ่งจะดำเนินการเมธอดพาเรนต์ เราสามารถเพิ่มตรรกะเพิ่มเติมของเราได้หลังจากนั้น ข้อกำหนดที่ต้องปฏิบัติตาม:
  • ลายเซ็นวิธีการต้องเหมือนกัน
  • ค่าที่ส่งคืนจะต้องเหมือนกัน

11. ลายเซ็นวิธีการคืออะไร?

คำถามและคำตอบสัมภาษณ์งาน 50 อันดับแรกสำหรับ Java Core  ตอนที่ 1 - 3ลายเซ็นเมธอดคือการรวมกันของชื่อเมธอดและอาร์กิวเมนต์ที่เมธอดใช้ ลายเซ็นเมธอดเป็นตัวระบุเฉพาะของเมธอดเมื่อเมธอดโอเวอร์โหลด

12. วิธีการโอเวอร์โหลดคืออะไร?

การโอเวอร์โหลดเมธอดเป็นคุณลักษณะของความหลากหลายที่เราเปลี่ยนลายเซ็นเมธอดเพื่อสร้างเมธอดหลายวิธีที่ดำเนินการแบบเดียวกัน:
  • ชื่อเดียวกัน
  • ข้อโต้แย้งที่แตกต่างกัน
  • อาจมีประเภทผลตอบแทนที่แตกต่างกัน
ตัวอย่างเช่น เมธอด ArrayListของคลาสadd()สามารถโอเวอร์โหลดได้ ทำให้เราสามารถเพิ่มได้หลายวิธีขึ้นอยู่กับอาร์กิวเมนต์อินพุต:
  • add(Object o)— วิธีนี้เพียงแค่เพิ่มวัตถุ
  • add(int index, Object o)— วิธีนี้จะเพิ่มวัตถุที่ดัชนีเฉพาะ
  • add(Collection<Object> c)— วิธีนี้จะเพิ่มรายการของวัตถุ
  • add(int index, Collection<Object> c)— วิธีนี้จะเพิ่มรายการของวัตถุที่เริ่มต้นจากดัชนีเฉพาะ

13. อินเทอร์เฟซคืออะไร

Java ไม่รองรับการสืบทอดหลายรายการ เพื่อเอาชนะข้อจำกัดนี้ อินเทอร์เฟซถูกเพิ่มเข้ามาในรูปแบบที่เรารู้จักและชื่นชอบ ;) เป็นเวลานานแล้วที่อินเทอร์เฟซมีเฉพาะวิธีการโดยไม่ต้องดำเนินการใดๆ ในบริบทของคำตอบนี้ เรามาพูดถึงพวกเขากัน ตัวอย่างเช่น:


public interface Animal {
   void makeSound();
   void eat();
   void sleep();
}
รายละเอียดบางส่วนตามนี้:
  • วิธีการทั้งหมดในอินเทอร์เฟซเป็นแบบสาธารณะและเป็นนามธรรม
  • ตัวแปรทั้งหมดเป็นแบบสาธารณะคงที่ขั้นสุดท้าย
  • คลาสไม่สืบทอดอินเทอร์เฟซ (เช่น เราไม่ได้ใช้คำหลักขยาย) คลาสดำเนินการแทน (เช่น เราใช้คีย์เวิร์ด Implement) นอกจากนี้ คุณสามารถใช้อินเทอร์เฟซได้มากเท่าที่คุณต้องการ
  • คลาสที่ใช้อินเตอร์เฟสต้องจัดเตรียมเมธอดทั้งหมดที่อยู่ในอินเตอร์เฟส
แบบนี้:

public class Cat implements Animal {
   public void makeSound() {
       // Method implementation
   }

   public void eat() {
       // Implementation
   }

   public void sleep() {
       // Implementation
   }
}

14. วิธีการเริ่มต้นในอินเทอร์เฟซคืออะไร?

ตอนนี้เรามาพูดถึงวิธีการเริ่มต้น สิ่งที่พวกเขาสำหรับ? พวกเขาเป็นใคร? เพิ่มวิธีการเหล่านี้เพื่อให้บริการ "ทั้งสองมือ" ฉันกำลังพูดถึงอะไร ในแง่หนึ่ง จำเป็นต้องเพิ่มฟังก์ชันใหม่: lambdas และ Stream API ในทางกลับกัน จำเป็นต้องคงไว้ซึ่งสิ่งที่ Java มีชื่อเสียงในด้านความเข้ากันได้แบบย้อนกลับ ในการทำเช่นนี้ อินเทอร์เฟซจำเป็นต้องมีโซลูชันสำเร็จรูปใหม่ นี่คือวิธีที่วิธีการเริ่มต้นมาถึงเรา เมธอดดีฟอลต์คือเมธอดที่ถูกนำไปใช้ในอินเทอร์เฟซ ทำเครื่องหมายด้วยdefaultคีย์เวิร์ด ตัวอย่างเช่นstream()วิธีการที่รู้จักกันดีในCollectionอินเทอร์เฟซ เชื่อฉันเถอะว่าอินเทอร์เฟซนี้ไม่ง่ายอย่างที่คิด หรือforEach()วิธีที่โด่งดังไม่แพ้กันในการIterableอินเตอร์เฟซ. ไม่มีอยู่จนกว่าจะมีการเพิ่มวิธีการเริ่มต้น นอกจากนี้ คุณสามารถอ่านเกี่ยวกับ CodeGym ได้ที่ นี่

15. แล้วเราจะสืบทอดวิธีเริ่มต้นที่เหมือนกันสองวิธีได้อย่างไร

คำตอบก่อนหน้านี้เกี่ยวกับวิธีการเริ่มต้นทำให้เกิดคำถามอื่น หากคุณสามารถนำเมธอดไปใช้ในอินเทอร์เฟซได้ ในทางทฤษฎีแล้ว คุณสามารถใช้สองอินเทอร์เฟซด้วยวิธีการเดียวกันได้ เราจะทำอย่างนั้นได้อย่างไร? นี่คือสองอินเทอร์เฟซที่แตกต่างกันด้วยวิธีการเดียวกัน:

interface A {
   default void foo() {
       System.out.println("Foo A");
   }
}

interface B {
   default void foo() {
       System.out.println("Foo B");
   }
}
และเรามีคลาสที่ใช้อินเทอร์เฟซทั้งสองนี้ แต่เราจะเลือกวิธีการเฉพาะในอินเทอร์เฟซ A หรือ B ได้อย่างไร โครงสร้างพิเศษต่อไปนี้ช่วยให้สิ่งนี้: A.super.foo():

public class C implements A, B {
   public void fooA() {
       A.super.foo();
   }

   public void fooB() {
       B.super.foo();
   }
}
ดังนั้น เมธอดfooA()จะใช้foo()วิธีเริ่มต้นของAอินเทอร์เฟซ ในขณะที่fooB()เมธอดจะใช้foo()วิธีการของBอินเทอร์เฟซ

16. วิธีการและคลาสนามธรรมคืออะไร?

ใน Java abstractเป็นคำสงวน ใช้เพื่อแสดงถึงคลาสนามธรรมและวิธีการ อันดับแรก เราต้องการคำจำกัดความ วิธีการแบบนามธรรมเป็นวิธีการที่ประกาศโดยใช้abstractคำหลักโดยไม่มีการนำไปใช้ในคลาสนามธรรม นั่นคือ นี่คือวิธีการในอินเทอร์เฟซ แต่ด้วยการเพิ่มคำหลัก ตัวอย่างเช่น:

public abstract void foo();
คลาสนามธรรมคือคลาสที่มีabstractคำหลัก:

public abstract class A {

}
คลาสนามธรรมมีคุณสมบัติหลายประการ:
  • คุณไม่สามารถสร้างวัตถุของคลาสนามธรรมได้
  • มันสามารถมีวิธีการนามธรรม
  • มันอาจจะไม่มีวิธีการนามธรรม
คลาสนามธรรมจำเป็นสำหรับสิ่งที่เป็นนามธรรม (ขออภัยสำหรับคำซ้ำซาก) ที่มีชุดของพฤติกรรมและสถานะทั่วไป (นั่นคือเมธอดและตัวแปร) ชีวิตจริงเต็มไปด้วยตัวอย่าง ทุกสิ่งรอบตัวเรา "สัตว์", "รถยนต์", "รูปทรงเรขาคณิต" และอื่นๆ

17. ความแตกต่างระหว่าง String, StringBuilder และ StringBuffer คืออะไร?

Stringค่าจะถูกเก็บไว้ในพูลสตริงคงที่ ทันทีที่สร้างสตริง สตริงนั้นจะปรากฏในพูลนี้ และคุณไม่สามารถลบได้ ตัวอย่างเช่น:

String name = "book";
ตัวแปรจะชี้ไปที่กลุ่มสตริงค่าคง คำถามและคำตอบสัมภาษณ์งาน 50 อันดับแรกสำหรับ Java Core  ตอนที่ 1 - 4ที่ การตั้งชื่อตัวแปรเป็นค่าอื่น เรามี:

name = "pen";
พูลสตริงคงที่มีลักษณะดังนี้ คำถามและคำตอบสัมภาษณ์งาน 50 อันดับแรกสำหรับ Java Core  ตอนที่ 1 - 5กล่าวคือ ค่าทั้งสองจะยังคงอยู่ บัฟเฟอร์สตริง:
  • Stringค่าจะถูกเก็บไว้ในสแต็ก หากมีการเปลี่ยนแปลงค่า ค่าใหม่จะแทนที่ค่าเก่า
  • String Bufferถูกซิงโครไนซ์และดังนั้นจึงปลอดภัยสำหรับเธรด
  • เนื่องจากความปลอดภัยของเธรด ประสิทธิภาพจึงไม่ดี
ตัวอย่าง:

StringBuffer name = “book”;
คำถามและคำตอบสัมภาษณ์งาน 50 อันดับแรกสำหรับ Java Core  ตอนที่ 1 - 6ทันทีที่ค่าของตัวแปรชื่อเปลี่ยนแปลง ค่าในสแต็กจะเปลี่ยนไป: คำถามและคำตอบสัมภาษณ์งาน 50 อันดับแรกสำหรับ Java Core  ตอนที่ 1 - 7StringBuilderจะเหมือนกับ ทุกประการStringBufferเพียงแต่ไม่ปลอดภัยสำหรับเธรด เป็นผลให้มันเร็วกว่าอย่างเห็นได้StringBufferชัด

18. คลาสนามธรรมและอินเทอร์เฟซต่างกันอย่างไร

คลาสนามธรรม:
  • คลาสนามธรรมมีตัวสร้างเริ่มต้น มันถูกเรียกทุกครั้งที่มีการสร้างลูกหลานของคลาสนามธรรม
  • สามารถรวมทั้งวิธีการนามธรรมและวิธีที่ไม่เป็นนามธรรม โดยทั่วไปแล้วคลาสนามธรรมไม่จำเป็นต้องมีวิธีการนามธรรม
  • คลาสที่สืบทอดนามธรรมต้องใช้เมธอดนามธรรมเท่านั้น
  • คลาสนามธรรมสามารถมีตัวแปรเช่น (ดูคำถามที่ #5)
อินเตอร์เฟซ:
  • อินเทอร์เฟซไม่มีตัวสร้างและไม่สามารถเริ่มต้นได้
  • สามารถเพิ่มได้เฉพาะวิธีการแบบนามธรรมเท่านั้น (ยกเว้นวิธีการเริ่มต้น)
  • คลาสที่ใช้อินเทอร์เฟซจะต้องใช้เมธอดทั้งหมด (ยกเว้นเมธอดดีฟอลต์)
  • อินเทอร์เฟซสามารถมีค่าคงที่เท่านั้น

19. เหตุใดจึงต้องเข้าถึงองค์ประกอบในอาร์เรย์ O(1)

คำถามนี้ถูกถามอย่างแท้จริงในการสัมภาษณ์ครั้งล่าสุดของฉัน ดังที่ฉันได้เรียนรู้ในภายหลัง จุดประสงค์ของคำถามนี้คือเพื่อดูว่าคน ๆ หนึ่งคิดอย่างไร เห็นได้ชัดว่าความรู้นี้มีประโยชน์เพียงเล็กน้อย แค่รู้ไว้ก็พอ ก่อนอื่น เราต้องชี้แจงว่า O(1) เป็นสัญลักษณ์สำหรับความซับซ้อนของเวลาของอัลกอริทึม "เวลาคงที่" กล่าวอีกนัยหนึ่ง การกำหนดนี้ระบุเวลาดำเนินการที่เร็วที่สุด เพื่อตอบคำถามนี้ เราต้องพิจารณาสิ่งที่เรารู้เกี่ยวกับอาร์เรย์ ในการสร้างintarray เราต้องเขียนดังนี้

int[] intArray = new int[100];
สามารถสรุปได้หลายอย่างจากไวยากรณ์นี้:
  1. เมื่อมีการประกาศอาร์เรย์ ก็จะทราบชนิดของอาร์เรย์ หากทราบประเภท ก็จะทราบขนาดของแต่ละเซลล์ในอาร์เรย์
  2. ขนาดของอาร์เรย์ทั้งหมดเป็นที่รู้จัก
ดังนั้นเพื่อให้เข้าใจว่าจะเขียนเซลล์ใด เราเพียงแค่ต้องคำนวณพื้นที่ของหน่วยความจำที่จะเขียน สำหรับคอมพิวเตอร์ นี่เป็นเรื่องง่าย คอมพิวเตอร์รู้ว่าหน่วยความจำที่จัดสรรเริ่มต้นที่ใด จำนวนองค์ประกอบ และขนาดของแต่ละเซลล์ ทั้งหมดนี้หมายความว่าตำแหน่งที่จะเขียนจะเท่ากับตำแหน่งเริ่มต้นของอาร์เรย์ + ขนาดของแต่ละเซลล์คูณด้วยดัชนี

แล้วเราจะมาถึง O(1) เมื่อเข้าถึงวัตถุใน ArrayList ได้อย่างไร

คำถามนี้ต่อจากคำถามก่อนหน้าทันที ความจริงก็คือเมื่อทำงานกับอาร์เรย์ที่มีองค์ประกอบดั้งเดิม เราจะรู้ล่วงหน้า (ณ เวลาที่สร้างสรรค์) ขนาดของประเภทองค์ประกอบ แต่เราจะทำอย่างไรถ้าเรามีลำดับชั้นการสืบทอดแบบนี้ และ คำถามและคำตอบสัมภาษณ์งาน 50 อันดับแรกสำหรับ Java Core  ตอนที่ 1 - 8เราต้องการสร้างคอลเลกชันสำหรับองค์ประกอบประเภท A และเพิ่มการใช้งานที่แตกต่างกัน (B, C และ D):

List<A> list = new ArrayList();
list.add(new B());
list.add(new C());
list.add(new D());
list.add(new B());
ในสถานการณ์นี้ เราจะคำนวณขนาดของแต่ละเซลล์ได้อย่างไร ท้ายที่สุดแล้ว แต่ละวัตถุจะแตกต่างกัน อาจมีฟิลด์เพิ่มเติมที่แตกต่างกัน จะทำอย่างไร? นี่เป็นคำถามในลักษณะที่ทำให้คุณสับสน เราทราบดีว่าคอลเลกชันไม่ได้จัดเก็บวัตถุโดยตรง มันเก็บการอ้างอิงถึงวัตถุเท่านั้น และการอ้างอิงทั้งหมดมีขนาดเท่ากันและเป็นที่รู้จักกัน เป็นผลให้เราคำนวณที่อยู่ที่นี่ด้วยวิธีเดียวกับในคำถามก่อนหน้า

21. การทำกล่องอัตโนมัติและการแกะกล่อง

ประวัติความเป็นมา:การใส่กล่องอัตโนมัติและการแกะกล่องเป็นนวัตกรรมหลักบางอย่างใน JDK 5 การทำกล่องอัตโนมัติเป็นกระบวนการของการแปลงอัตโนมัติจากประเภทดั้งเดิมเป็นคลาสของ wrapper ที่สอดคล้องกัน การแกะกล่องเป็นสิ่งที่ตรงกันข้ามกับการทำกล่องอัตโนมัติ เป็นกระบวนการแปลงคลาส wrapper เป็นคลาสดั้งเดิม แต่ถ้าค่าของ wrapper คือจะมีการโยน nulla ในระหว่างการแกะกล่องNullPointerException

Primitives และ wrappers ที่เกี่ยวข้อง

ดึกดำบรรพ์ ชั้นห่อ
บูลีน บูลีน
นานาชาติ จำนวนเต็ม
ไบต์ ไบต์
ถ่าน อักขระ
ลอย ลอย
ยาว ยาว
สั้น สั้น
สองเท่า สองเท่า

// การทำกล่องอัตโนมัติเกิดขึ้น:

  • เมื่อกำหนดพื้นฐานให้กับการอ้างอิงถึงคลาสของ wrapper:

    ก่อน Java 5:

    
    // Manual boxing (the way it was BEFORE Java 5).
    public void boxingBeforeJava5() {
       Boolean booleanBox = new Boolean(true);
       Integer intBox = new Integer(3);
       // And so on for other types
    }
    
    After Java 5:
    // Automatic boxing (the way it became in Java 5).
    public void boxingJava5() {
       Boolean booleanBox = true;
       Integer intBox = 3;
       // And so on for other types
    }
    
  • เมื่อการดั้งเดิมถูกส่งผ่านเป็นอาร์กิวเมนต์ไปยังเมธอดที่คาดว่าจะมี wrapper:

    
    public void exampleOfAutoboxing() {
       long age = 3;
       setAge(age);
    }
    
    public void setAge(Long age) {
       this.age = age;
    }
    

// Unboxing เกิดขึ้น:

  • เมื่อเรากำหนดอินสแตนซ์ของคลาส wrapper ให้กับตัวแปรดั้งเดิม:

    
    // BEFORE Java 5:
    int intValue = new Integer(4).intValue();
    double doubleValue = new Double(2.3).doubleValue();
    char c = new Character((char) 3).charValue();
    boolean b = Boolean.TRUE.booleanValue();
    
    // And after JDK 5:
    int intValue = new Integer(4);
    double doubleValue = new Double(2.3);
    char c = new Character((char) 3);
    boolean b = Boolean.TRUE;
    
  • ระหว่างการดำเนินการทางคณิตศาสตร์ การดำเนินการใช้กับประเภทดั้งเดิมเท่านั้น ดังนั้นการแกะกล่องไปยังประเภทดั้งเดิมจึงเป็นสิ่งจำเป็น

    
    // BEFORE Java 5:
    Integer integerBox1 = new Integer(1);
    Integer integerBox2 = new Integer(2);
    
    // A comparison used to require this:
    integerBox1.intValue() > integerBox2.intValue()
          
    // In Java 5
    integerBox1 > integerBox2
    
  • เมื่อส่งอินสแตนซ์ของคลาส wrapper ไปยังเมธอดที่ใช้ค่าดั้งเดิมที่สอดคล้องกัน:

    
    public void exampleOfAutoboxing() {
       Long age = new Long(3);
       setAge(age);
    }
    
    public void setAge(long age) {
       this.age = age;
    }
    

22. คำหลักสุดท้ายคืออะไรและใช้ที่ไหน?

finalสามารถใช้คีย์เวิร์ดกับตัวแปร เมธอด และคลาส ได้
  1. ไม่สามารถเปลี่ยนค่าของตัวแปรสุดท้ายได้หลังจากเริ่มต้นแล้ว
  2. ชั้นสุดท้ายเป็นหมัน :) ไม่สามารถมีลูกได้
  3. เมธอดสุดท้ายไม่สามารถแทนที่ได้โดยลูกหลาน
เราได้ครอบคลุมเนื้อหาระดับสูงแล้ว ทีนี้มาเจาะลึกกัน

ตัวแปรสุดท้าย

Java ให้สองวิธีแก่เราในการประกาศตัวแปรและกำหนดค่าให้กับตัวแปร:
  1. คุณสามารถประกาศตัวแปรและกำหนดค่าเริ่มต้นได้ในภายหลัง
  2. คุณสามารถประกาศตัวแปรและกำหนดค่าได้ทันที
นี่คือตัวอย่างที่แสดงให้เห็นถึงการใช้ตัวแปรสุดท้ายเหล่านี้:

public class FinalExample {

   // A static final variable that is immediately initialized:
   final static String FINAL_EXAMPLE_NAME = "I'm likely the final one";

   // A final variable that is not initialized, but will only work if you
   // initialize it in the constructor:
   final long creationTime;

   public FinalExample() {
       this.creationTime = System.currentTimeMillis();
   }

   public static void main(String[] args) {
       FinalExample finalExample = new FinalExample();
       System.out.println(finalExample.creationTime);

       // The final FinalExample.FINAL_EXAMPLE_NAME field cannot be accessed
//    FinalExample.FINAL_EXAMPLE_NAME = "Not you're not!";

       // The final Config.creationTime field cannot be accessed
//    finalExample.creationTime = 1L;
   }
}

ตัวแปรสุดท้ายถือเป็นค่าคงที่ได้หรือไม่?

เนื่องจากเราไม่สามารถกำหนดค่าใหม่ให้กับตัวแปรสุดท้ายได้ จึงดูเหมือนว่าค่าเหล่านี้เป็นตัวแปรคงที่ แต่เมื่อมองแวบแรก: หากชนิดข้อมูลของตัวแปรคือimmutableใช่ ตัวแปรนั้นจะเป็นค่าคงที่ แต่ถ้าชนิดข้อมูลคือmutableเปลี่ยนแปลงได้ ก็จะสามารถใช้เมธอดและตัวแปรเพื่อเปลี่ยนค่าของวัตถุที่อ้างอิงโดยตัวแปรfinalได้ ด้วยเหตุนี้จึงไม่สามารถเรียกว่าค่าคงที่ได้ ตัวอย่างต่อไปนี้แสดงให้เห็นว่าตัวแปรสุดท้ายบางตัวเป็นค่าคงที่จริง ๆ ในขณะที่ตัวแปรอื่น ๆ ไม่ใช่ เนื่องจากสามารถเปลี่ยนแปลงได้

public class FinalExample {

   // Immutable final variables
   final static String FINAL_EXAMPLE_NAME = "I'm likely the final one";
   final static Integer FINAL_EXAMPLE_COUNT  = 10;

   // Mutable final variables
   final List<String> addresses = new ArrayList();
   final StringBuilder finalStringBuilder = new StringBuilder("Constant?");
}

ตัวแปรสุดท้ายในท้องถิ่น

เมื่อfinalตัวแปรถูกสร้างขึ้นภายในเมธอด จะเรียกว่าlocal finalตัวแปร:

public class FinalExample {

   public static void main(String[] args) {
       // You can do this
       final int minAgeForDriveCar = 18;

       // Or you can do this, in a for-each loop:
       for (final String arg : args) {
           System.out.println(arg);
       }
   }

}
เราสามารถใช้คำหลักสุดท้ายในการวนซ้ำแบบปรับปรุงได้ เนื่องจากตัวแปรใหม่จะถูกสร้างขึ้นหลังจากการวนซ้ำแต่ละครั้ง โปรดทราบว่าสิ่งนี้ใช้ไม่ได้กับลูปปกติ ดังนั้นเราจะได้รับข้อผิดพลาดในการคอมไพล์

// The final local j variable cannot be assigned
for (final int i = 0; i < args.length; i ++) {
   System.out.println(args[i]);
}

ชั้นเรียนสุดท้าย

คลาสที่ประกาศว่าfinalไม่สามารถขยายได้ พูดง่ายๆ ก็คือไม่มีคลาสอื่นใดที่สามารถสืบทอดได้ ตัวอย่างที่ยอดเยี่ยมของfinalคลาสใน JDK คือ String ขั้นตอนแรกในการสร้างคลาสที่ไม่เปลี่ยนรูปแบบคือการทำเครื่องหมายเป็นfinalเพื่อป้องกันการขยายคลาส:

public final class FinalExample {
}

// Compilation error!
class WantsToInheritFinalClass extends FinalExample {
}

วิธีการสุดท้าย

เมื่อเมธอดใดถูกทำเครื่องหมายเป็นขั้นสุดท้าย จะเรียกว่าเมธอดขั้นสุดท้าย (สมเหตุสมผลไหม?) ไม่สามารถแทนที่เมธอดสุดท้ายในคลาสย่อยได้ อนึ่ง เมธอด wait() และ alert() ของคลาสออบเจกต์ถือเป็นที่สิ้นสุด ดังนั้นเราจึงไม่สามารถแทนที่เมธอดเหล่านั้นได้

public class FinalExample {
   public final String generateAddress() {
       return "Some address";
   }
}

class ChildOfFinalExample extends FinalExample {

   // Compilation error!
   @Override
   public String generateAddress() {
       return "My OWN Address";
   }
}

จะใช้ Final อย่างไรและที่ไหนใน Java

  • ใช้คีย์เวิร์ดสุดท้ายเพื่อกำหนดค่าคงที่ระดับคลาส
  • สร้างตัวแปรสุดท้ายสำหรับวัตถุที่คุณไม่ต้องการเปลี่ยนแปลง ตัวอย่างเช่น คุณสมบัติเฉพาะของออบเจกต์ที่เราสามารถใช้เพื่อวัตถุประสงค์ในการบันทึก
  • หากคุณไม่ต้องการให้ขยายชั้นเรียน ให้ทำเครื่องหมายว่าชั้นเรียนสิ้นสุด
  • หากคุณต้องการสร้างคลาสที่ไม่เปลี่ยนรูป คุณต้องทำให้เป็นคลาสสุดท้าย
  • หากคุณต้องการให้การใช้งานเมธอดไม่เปลี่ยนแปลงในลำดับล่าง ให้ทำเครื่องหมายเมธอดfinalเป็น นี่เป็นสิ่งสำคัญมากที่จะต้องแน่ใจว่าการใช้งานจะไม่เปลี่ยนแปลง

23. ประเภทที่ไม่เปลี่ยนรูปและไม่เปลี่ยนรูปคืออะไร?

ไม่แน่นอน

วัตถุที่ไม่แน่นอนคือวัตถุที่สามารถเปลี่ยนแปลงสถานะและตัวแปรได้หลังจากสร้าง ตัวอย่างของคลาสที่ไม่แน่นอน ได้แก่ StringBuilder และ StringBuffer ตัวอย่าง:

public class MutableExample {

   private String address;

   public MutableExample(String address) {
       this.address = address;
   }

   public String getAddress() {
       return address;
   }

   // This setter can change the name field
   public void setAddress(String address) {
       this.address = address;
   }

   public static void main(String[] args) {

       MutableExample obj = new MutableExample("First address");
       System.out.println(obj.getAddress());

       // We are updating the name field, so this is a mutable object
       obj.setAddress("Updated address");
       System.out.println(obj.getAddress());
   }
}

ไม่เปลี่ยนรูป

อ็อบเจกต์ที่ไม่เปลี่ยนรูปคืออ็อบเจกต์ที่ไม่สามารถเปลี่ยนสถานะและตัวแปรได้หลังจากสร้างอ็อบเจกต์แล้ว กุญแจสำคัญสำหรับ HashMap คุณว่าไหม? :) ตัวอย่างเช่น สตริง จำนวนเต็ม สองเท่า และอื่น ๆ ตัวอย่าง:

// We'll make this class final so no one can change it
public final class ImmutableExample {

   private String address;

   ImmutableExample(String address) {
       this.address = address;
   }

   public String getAddress() {
       return address;
   }

   // We remove the setter

   public static void main(String[] args) {

       ImmutableExample obj = new ImmutableExample("Old address");
       System.out.println(obj.getAddress());

       // There is no way to change this field, so it is an immutable object
       // obj.setName("new address");
       // System.out.println(obj.getName());

   }
}
ในส่วนถัดไป เราจะพิจารณาคำถามและคำตอบเกี่ยวกับคอลเลกชัน โปรไฟล์ของฉันใน GitHub คำถามสัมภาษณ์งาน 50 อันดับแรกและคำตอบสำหรับ Java Core ส่วนที่ 2
ความคิดเห็น
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION