
สัมภาษณ์ Java: คำถามเกี่ยวกับ OOP
1. Java มีลักษณะเด่นอย่างไร
คำตอบ:-
แนวคิด OOP:
- การวางแนววัตถุ
- มรดก
- การห่อหุ้ม
- ความหลากหลาย
- สิ่งที่เป็นนามธรรม
-
ข้ามแพลตฟอร์ม:โปรแกรม Java สามารถรันบนแพลตฟอร์มใดก็ได้โดยไม่มีการเปลี่ยนแปลงใดๆ แน่นอนว่าต้องติดตั้ง JVM (เครื่องเสมือน Java)
-
ประสิทธิภาพสูง:คอมไพเลอร์ Just-In-Time (JIT) ทำให้ประสิทธิภาพสูงเป็นไปได้ คอมไพเลอร์ JIT แปลง bytecode เป็นรหัสเครื่อง จากนั้น JVM จะเริ่มดำเนินการ
- มัลติเธรด: JVM สร้างเธรดการดำเนินการที่เรียกว่า
main thread
. โปรแกรมเมอร์สามารถสร้างหลายเธรดโดยได้รับจากคลาสเธรดหรือใช้Runnable
อินเทอร์เฟซ
2. มรดกคืออะไร?
การสืบทอดหมายความว่าคลาสหนึ่งสามารถสืบทอดคลาสอื่นได้ (โดยใช้ คำสำคัญ ขยาย ) ซึ่งหมายความว่าคุณสามารถใช้โค้ดจากคลาสที่คุณสืบทอดมาซ้ำได้ คลาสที่มีอยู่เรียกว่า thesuperclass
และคลาสที่สร้างขึ้นใหม่คือ the subclass
. ผู้คนยังพูดว่าใช้คำว่า parent child
และ
public class Animal {
private int age;
}
public class Dog extends Animal {
}
Animal
อยู่ ที่ไหนparent
และDog
คือchild
.
3. การห่อหุ้มคืออะไร?
คำถามนี้มักถูกถามในการสัมภาษณ์สำหรับตำแหน่งนักพัฒนา Java Encapsulationกำลังซ่อนการใช้งานโดยใช้ตัวดัดแปลงการเข้าถึง ตัวรับ และตัวตั้งค่า สิ่งนี้ทำเพื่อป้องกันการเข้าถึงจากภายนอกในทุกที่ที่นักพัฒนาคิดว่าจำเป็น ตัวอย่างง่ายๆ จากชีวิตจริงคือรถยนต์ เราไม่สามารถเข้าถึงการทำงานของเครื่องยนต์ได้โดยตรง สิ่งที่เราต้องทำคือใส่กุญแจเข้าไปในสวิตช์กุญแจแล้วเปิดเครื่องยนต์ กระบวนการที่เกิดขึ้นภายใต้ประทุนไม่ใช่ธุรกิจของเรา ยิ่งไปกว่านั้น หากเราไปแทรกแซงการทำงานของเครื่องยนต์ อาจนำไปสู่สถานการณ์ที่คาดเดาไม่ได้ อาจทำให้รถเสียหายและส่งผลเสียต่อร่างกายได้ สิ่งเดียวกันนี้เกิดขึ้นในการเขียนโปรแกรม สิ่งนี้อธิบายได้ดีในวิกิพีเดีย. นอกจากนี้ยังมีบทความเกี่ยวกับการห่อหุ้มบน CodeGym4. ความหลากหลายคืออะไร?
ความแตกต่างคือความสามารถของโปรแกรมในการจัดการกับวัตถุด้วยอินเทอร์เฟซเดียวกันในลักษณะเดียวกัน โดยไม่มีข้อมูลเกี่ยวกับประเภทเฉพาะของวัตถุ ดังคำกล่าวที่ว่า "อินเทอร์เฟซเดียว — ใช้งานได้หลายอย่าง" ด้วยความหลากหลาย คุณสามารถรวมและใช้วัตถุประเภทต่างๆ ตามพฤติกรรมที่ใช้ร่วมกันได้ ตัวอย่างเช่น เรามีคลาสสัตว์ที่มีลูกหลานสองคน: สุนัขและแมว คลาสสัตว์ทั่วไปมีพฤติกรรมร่วมกันคือความสามารถในการส่งเสียง เราใช้ความสามารถแบบ 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 คืออะไร?
ตัวสร้างมีคุณสมบัติดังต่อไปนี้:- เมื่อวัตถุใหม่ถูกสร้างขึ้น โปรแกรมจะใช้ตัวสร้างที่เหมาะสมในการสร้างวัตถุนั้น
- ตัวสร้างเป็นเหมือนวิธีการ คุณสมบัติที่โดดเด่นของมันอยู่ที่ความจริงที่ว่าไม่มีค่าส่งคืน (รวมถึงโมฆะ) และชื่อนั้นเหมือนกับชื่อของคลาส
- หากไม่มีการสร้างตัวสร้างอย่างชัดเจน ตัวสร้างว่างจะถูกสร้างขึ้นโดยอัตโนมัติ
- ตัวสร้างสามารถถูกแทนที่ได้
- หากคุณประกาศตัวสร้างพร้อมพารามิเตอร์แต่ต้องการตัวสร้างที่ไม่มีพารามิเตอร์ด้วย คุณต้องสร้างตัวสร้างแยกต่างหาก เนื่องจากตัวสร้างจะไม่ถูกสร้างขึ้นโดยอัตโนมัติ
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. ตัวดัดแปลงการเข้าถึงคืออะไร?
ตัวดัดแปลงการเข้าถึงเป็นกลไกสำหรับปรับแต่งการเข้าถึงคลาส เมธอด และตัวแปร มีตัวแก้ไขต่อไปนี้ ซึ่งแสดงรายการตามลำดับการเข้าถึงที่เพิ่มขึ้น:private
— ตัวดัดแปลงการเข้าถึงนี้ใช้กับเมธอด ฟิลด์ และคอนสตรัคเตอร์ การเข้าถึงถูกจำกัดไว้เฉพาะคลาสที่มีการประกาศpackage-private (default)
— นี่คือระดับการเข้าถึงเริ่มต้นสำหรับชั้นเรียน การเข้าถึงจะจำกัดเฉพาะแพ็คเกจที่มีการประกาศคลาส เมธอด ตัวแปร หรือคอนสตรัคเตอร์protected
— ตัวแก้ไขการเข้าถึงนี้นำเสนอระดับการเข้าถึงเดียวกันกับpackage-private
การเพิ่มการเข้าถึงสำหรับคลาสที่สืบทอดคลาสด้วยตัวprotected
แก้ไขpublic
— ระดับการเข้าถึงนี้ยังใช้สำหรับชั้นเรียน ระดับการเข้าถึงนี้หมายความว่ามีการเข้าถึงแบบเต็มตลอดทั้งแอปพลิเคชัน

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

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. วิธีการและคลาสนามธรรมคืออะไร?
ใน Javaabstract
เป็นคำสงวน ใช้เพื่อแสดงถึงคลาสนามธรรมและวิธีการ อันดับแรก เราต้องการคำจำกัดความ วิธีการแบบนามธรรมเป็นวิธีการที่ประกาศโดยใช้abstract
คำหลักโดยไม่มีการนำไปใช้ในคลาสนามธรรม นั่นคือ นี่คือวิธีการในอินเทอร์เฟซ แต่ด้วยการเพิ่มคำหลัก ตัวอย่างเช่น:
public abstract void foo();
คลาสนามธรรมคือคลาสที่มีabstract
คำหลัก:
public abstract class A {
}
คลาสนามธรรมมีคุณสมบัติหลายประการ:
- คุณไม่สามารถสร้างวัตถุของคลาสนามธรรมได้
- มันสามารถมีวิธีการนามธรรม
- มันอาจจะไม่มีวิธีการนามธรรม
17. ความแตกต่างระหว่าง String, StringBuilder และ StringBuffer คืออะไร?
String
ค่าจะถูกเก็บไว้ในพูลสตริงคงที่ ทันทีที่สร้างสตริง สตริงนั้นจะปรากฏในพูลนี้ และคุณไม่สามารถลบได้ ตัวอย่างเช่น:
String name = "book";
ตัวแปรจะชี้ไปที่กลุ่มสตริงค่าคง 
name = "pen";
พูลสตริงคงที่มีลักษณะดังนี้ 
String
ค่าจะถูกเก็บไว้ในสแต็ก หากมีการเปลี่ยนแปลงค่า ค่าใหม่จะแทนที่ค่าเก่าString Buffer
ถูกซิงโครไนซ์และดังนั้นจึงปลอดภัยสำหรับเธรด- เนื่องจากความปลอดภัยของเธรด ประสิทธิภาพจึงไม่ดี
StringBuffer name = “book”;


StringBuffer
เพียงแต่ไม่ปลอดภัยสำหรับเธรด เป็นผลให้มันเร็วกว่าอย่างเห็นได้StringBuffer
ชัด
18. คลาสนามธรรมและอินเทอร์เฟซต่างกันอย่างไร
คลาสนามธรรม:- คลาสนามธรรมมีตัวสร้างเริ่มต้น มันถูกเรียกทุกครั้งที่มีการสร้างลูกหลานของคลาสนามธรรม
- สามารถรวมทั้งวิธีการนามธรรมและวิธีที่ไม่เป็นนามธรรม โดยทั่วไปแล้วคลาสนามธรรมไม่จำเป็นต้องมีวิธีการนามธรรม
- คลาสที่สืบทอดนามธรรมต้องใช้เมธอดนามธรรมเท่านั้น
- คลาสนามธรรมสามารถมีตัวแปรเช่น (ดูคำถามที่ #5)
- อินเทอร์เฟซไม่มีตัวสร้างและไม่สามารถเริ่มต้นได้
- สามารถเพิ่มได้เฉพาะวิธีการแบบนามธรรมเท่านั้น (ยกเว้นวิธีการเริ่มต้น)
- คลาสที่ใช้อินเทอร์เฟซจะต้องใช้เมธอดทั้งหมด (ยกเว้นเมธอดดีฟอลต์)
- อินเทอร์เฟซสามารถมีค่าคงที่เท่านั้น
19. เหตุใดจึงต้องเข้าถึงองค์ประกอบในอาร์เรย์ O(1)
คำถามนี้ถูกถามอย่างแท้จริงในการสัมภาษณ์ครั้งล่าสุดของฉัน ดังที่ฉันได้เรียนรู้ในภายหลัง จุดประสงค์ของคำถามนี้คือเพื่อดูว่าคน ๆ หนึ่งคิดอย่างไร เห็นได้ชัดว่าความรู้นี้มีประโยชน์เพียงเล็กน้อย แค่รู้ไว้ก็พอ ก่อนอื่น เราต้องชี้แจงว่า O(1) เป็นสัญลักษณ์สำหรับความซับซ้อนของเวลาของอัลกอริทึม "เวลาคงที่" กล่าวอีกนัยหนึ่ง การกำหนดนี้ระบุเวลาดำเนินการที่เร็วที่สุด เพื่อตอบคำถามนี้ เราต้องพิจารณาสิ่งที่เรารู้เกี่ยวกับอาร์เรย์ ในการสร้างint
array เราต้องเขียนดังนี้
int[] intArray = new int[100];
สามารถสรุปได้หลายอย่างจากไวยากรณ์นี้:
- เมื่อมีการประกาศอาร์เรย์ ก็จะทราบชนิดของอาร์เรย์ หากทราบประเภท ก็จะทราบขนาดของแต่ละเซลล์ในอาร์เรย์
- ขนาดของอาร์เรย์ทั้งหมดเป็นที่รู้จัก
แล้วเราจะมาถึง O(1) เมื่อเข้าถึงวัตถุใน ArrayList ได้อย่างไร
คำถามนี้ต่อจากคำถามก่อนหน้าทันที ความจริงก็คือเมื่อทำงานกับอาร์เรย์ที่มีองค์ประกอบดั้งเดิม เราจะรู้ล่วงหน้า (ณ เวลาที่สร้างสรรค์) ขนาดของประเภทองค์ประกอบ แต่เราจะทำอย่างไรถ้าเรามีลำดับชั้นการสืบทอดแบบนี้ และ
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 คือจะมีการโยนnull
a ในระหว่างการแกะกล่อง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
สามารถใช้คีย์เวิร์ดกับตัวแปร เมธอด และคลาส ได้
- ไม่สามารถเปลี่ยนค่าของตัวแปรสุดท้ายได้หลังจากเริ่มต้นแล้ว
- ชั้นสุดท้ายเป็นหมัน :) ไม่สามารถมีลูกได้
- เมธอดสุดท้ายไม่สามารถแทนที่ได้โดยลูกหลาน
ตัวแปรสุดท้าย
Java ให้สองวิธีแก่เราในการประกาศตัวแปรและกำหนดค่าให้กับตัวแปร:- คุณสามารถประกาศตัวแปรและกำหนดค่าเริ่มต้นได้ในภายหลัง
- คุณสามารถประกาศตัวแปรและกำหนดค่าได้ทันที
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
GO TO FULL VERSION