
คำถาม & คำตอบสำหรับตำแหน่งนักพัฒนารุ่นเยาว์
คำถามทั่วไป
1. คุณรู้รูปแบบการออกแบบอะไรบ้าง? บอกเราเกี่ยวกับรูปแบบการออกแบบ 2 รูปแบบที่คุณเคยใช้ในการทำงาน
มีหลากหลายรูปแบบมาก สำหรับผู้ที่ต้องการทำความคุ้นเคยกับรูปแบบการออกแบบอย่างละเอียด ผมขอแนะนำให้อ่านหนังสือ "Head First. Design Patterns" จะช่วยให้คุณเรียนรู้รายละเอียดของรูปแบบการออกแบบขั้นพื้นฐานได้อย่างง่ายดาย ในแง่ของรูปแบบการออกแบบที่คุณสามารถพูดถึงในการสัมภาษณ์งาน สิ่งที่ควรคำนึงถึงมีดังนี้:- Builder — เทมเพลตที่ใช้บ่อย ซึ่งเป็นทางเลือกแทนแนวทางดั้งเดิมในการสร้างวัตถุ
- กลยุทธ์ — รูปแบบที่แสดงถึงความหลากหลายเป็นหลัก นั่นคือเรามีอินเทอร์เฟซเดียว แต่พฤติกรรมของโปรแกรมจะเปลี่ยนไปขึ้นอยู่กับการใช้งานอินเทอร์เฟซเฉพาะที่ส่งผ่านไปยังฟังก์ชัน (รูปแบบกลยุทธ์นี้ใช้เกือบทุกที่ในแอปพลิเคชัน Java)
- โรงงาน — รูปแบบนี้สามารถพบได้ใน ApplicationContext (หรือใน BeanFactory);
- ซิงเกิลตัน — ถั่วทั้งหมดเป็นซิงเกิลตันตามค่าเริ่มต้น
- Proxy — โดยพื้นฐานแล้ว ทุกอย่างใน Spring ใช้รูปแบบนี้ไม่ทางใดก็ทางหนึ่ง เช่น AOP;
- ห่วงโซ่ความรับผิดชอบ — รูปแบบที่เป็นรากฐานของ Spring Security;
- เทมเพลต — ใช้ใน Spring JDBC
จาวาคอร์

2. Java มีประเภทข้อมูลอะไรบ้าง?
Java มีประเภทข้อมูลดั้งเดิมดังต่อไปนี้:- ไบต์ — จำนวนเต็มตั้งแต่ -128 ถึง 127 ใช้เวลาสูงสุด 1 ไบต์
- สั้น — จำนวนเต็มตั้งแต่ -32768 ถึง 32767 ใช้เวลาสูงสุด 2 ไบต์
- int — จำนวนเต็มตั้งแต่ -2147483648 ถึง 2147483647 ใช้เวลาสูงสุด 4 ไบต์
- ยาว — จำนวนเต็มตั้งแต่ 9223372036854775808 ถึง 9223372036854775807 ใช้เวลาสูงสุด 8 ไบต์
- float — จำนวนทศนิยมตั้งแต่ -3.4E+38 ถึง 3.4E+38 ใช้เวลาสูงสุด 4 ไบต์
- สองเท่า — เลขทศนิยมตั้งแต่ -1.7E+308 ถึง 1.7E+308 ใช้เวลาสูงสุด 8 ไบต์
- ถ่าน — อักขระเดี่ยวใน UTF-16 ใช้เวลาสูงสุด 2 ไบต์
- ค่า บูลีนจริง/เท็จ ใช้พื้นที่ 1 ไบต์
3. วัตถุแตกต่างจากประเภทข้อมูลดั้งเดิมอย่างไร?
ความแตกต่างประการแรกคือจำนวนหน่วยความจำที่ใช้อยู่: วัตถุดั้งเดิมใช้พื้นที่น้อยมากเนื่องจากมีเพียงค่าของตัวเอง แต่วัตถุสามารถมีค่าที่แตกต่างกันได้มากมาย — ทั้งวัตถุดั้งเดิมและการอ้างอิงถึงวัตถุอื่นๆ ข้อแตกต่างประการที่สองคือ: Java เป็นภาษาเชิงวัตถุ ดังนั้นทุกอย่างในการทำงานของ Java จึงเป็นการโต้ตอบระหว่างวัตถุ ยุคดั้งเดิมไม่เหมาะกับที่นี่มากนัก อันที่จริง นั่นเป็นเหตุผลที่ Java ไม่ใช่ภาษาเชิงวัตถุ 100% ความแตกต่างประการที่สามซึ่งตามมาจากข้อที่สองคือเนื่องจาก Java มุ่งเน้นไปที่การโต้ตอบกับวัตถุ จึงมีกลไกที่แตกต่างกันมากมายสำหรับการจัดการวัตถุ ตัวอย่างเช่น คอนสตรัคเตอร์ เมธอด ข้อยกเว้น (ซึ่งทำงานกับอ็อบเจกต์เป็นหลัก) ฯลฯ และเพื่อให้สิ่งดั้งเดิมทำงานในสภาพแวดล้อมเชิงวัตถุ ผู้สร้างของ Java จึงคิดค้นwrappersสำหรับประเภทดั้งเดิม ( จำนวนเต็ม , อักขระ , สองเท่า , บูลีน ... )4. ความแตกต่างระหว่างการส่งผ่านอาร์กิวเมนต์โดยการอ้างอิงและตามค่าคืออะไร?
ฟิลด์พื้นฐานจะเก็บค่าของมัน ตัวอย่างเช่น ถ้าเราตั้งค่าint i = 9; จากนั้น ช่อง iจะเก็บค่า 9 เมื่อเรามีการอ้างอิงถึงวัตถุ นั่นหมายความว่าเรามีฟิลด์ที่มีการอ้างอิงถึงวัตถุ กล่าวอีกนัยหนึ่ง เรามีฟิลด์ที่เก็บที่อยู่ของวัตถุในหน่วยความจำ
Cat cat = new Cat();
ซึ่งหมายความว่าฟิลด์ที่มีการอ้างอิงถึงวัตถุจะเก็บค่าด้วย ค่าของพวกเขาคือที่อยู่หน่วยความจำ นั่นคือcatเก็บที่อยู่หน่วยความจำของวัตถุCat() ใหม่ เมื่อเราส่งอาร์กิวเมนต์ไปยังเมธอด ค่าของมันก็จะถูกคัดลอก ในกรณีของค่าดั้งเดิม ค่าของค่าดั้งเดิมจะถูกคัดลอก ดังนั้นวิธีการนี้ใช้ได้กับสำเนา เมื่อสำเนามีการเปลี่ยนแปลง ต้นฉบับจะไม่ได้รับผลกระทบ ในกรณีของประเภทการอ้างอิง ค่าของที่อยู่หน่วยความจำจะถูกคัดลอก ดังนั้น ตัวแปรอ้างอิงทั้งสองจะจัดเก็บที่อยู่ที่ชี้ไปยังวัตถุเดียวกัน และถ้าเราใช้การอ้างอิงใหม่นี้เพื่อเปลี่ยนวัตถุ เราจะพบว่าการอ้างอิงเก่ามีการเปลี่ยนแปลงด้วย ท้ายที่สุดแล้ว ทั้งคู่ชี้ไปที่วัตถุเดียวกัน
5. JVM, JDK และ JRE คืออะไร
JVMย่อมาจากJava Virtual Machineซึ่งรัน Java bytecode ที่คอมไพเลอร์สร้างไว้ล่วงหน้า JREย่อมาจากJava Runtime Environment โดยพื้นฐานแล้วมันเป็นสภาพแวดล้อมสำหรับการรันแอปพลิเคชัน Java ประกอบด้วย JVM, ไลบรารีมาตรฐาน และส่วนประกอบอื่นๆ สำหรับการเรียกใช้แอปเพล็ตและแอปพลิเคชันที่เขียนด้วยภาษาโปรแกรมจาวา กล่าวอีกนัยหนึ่ง JRE เป็นแพ็คเกจของทุกสิ่งที่จำเป็นในการรันโปรแกรม Java ที่คอมไพล์แล้ว แต่ไม่มีเครื่องมือและยูทิลิตี้ เช่น คอมไพเลอร์หรือดีบักเกอร์สำหรับการพัฒนาแอปพลิเคชัน JDKย่อมาจากJava Development Kitซึ่งเป็นส่วนขยายของJRE. นั่นคือ มันเป็นสภาพแวดล้อมที่ไม่เพียงแต่สำหรับการเรียกใช้แอปพลิเคชัน Java เท่านั้น แต่ยังสำหรับการพัฒนาแอปพลิเคชันเหล่านั้นด้วย JDK มีทุกอย่างใน JRE รวมถึงเครื่องมือเพิ่มเติมต่างๆ เช่น คอมไพเลอร์และดีบักเกอร์ ซึ่งจำเป็นในการสร้างแอปพลิเคชัน Java (รวมถึงเอกสาร Java)
6. ทำไมต้องใช้ JVM?
ตามที่ระบุไว้ข้างต้น Java Virtual Machine เป็นเครื่องเสมือนที่เรียกใช้ Java bytecode ที่คอมไพเลอร์สร้างไว้ล่วงหน้า ซึ่งหมายความว่า JVM ไม่เข้าใจซอร์สโค้ด Java ก่อนอื่น เรารวบรวมไฟล์.java ไฟล์ที่คอมไพล์มี.classส่วนขยายและตอนนี้อยู่ในรูปของ bytecode ซึ่ง JVM เข้าใจ JVM นั้นแตกต่างกันไปในแต่ละระบบปฏิบัติการ เมื่อ JVM รันไฟล์ bytecode จะปรับไฟล์เหล่านั้นให้เหมาะกับระบบปฏิบัติการที่รันอยู่ อันที่จริง เนื่องจากมี JVM ที่แตกต่างกัน JDK (หรือ JRE) จึงแตกต่างกันไปตามระบบปฏิบัติการที่แตกต่างกัน (แต่ละเวอร์ชันต้องการ JVM ของตัวเอง) อย่าลืมว่าการพัฒนาทำงานอย่างไรในภาษาการเขียนโปรแกรมอื่นๆ คุณเขียนโปรแกรม จากนั้นโค้ดของโปรแกรมจะถูกคอมไพล์เป็นรหัสเครื่องสำหรับ OS เฉพาะ และจากนั้นคุณสามารถเรียกใช้งานได้ คุณต้องเขียนเวอร์ชันต่างๆ ของโปรแกรมสำหรับแต่ละแพลตฟอร์ม แต่การประมวลผลโค้ดสองครั้งของ Java (การคอมไพล์ซอร์สโค้ดเป็นไบต์โค้ด จากนั้นจึงประมวลผลไบต์โค้ดโดย JVM) ช่วยให้คุณได้รับประโยชน์จากโซลูชันข้ามแพลตฟอร์ม เราสร้างรหัสเพียงครั้งเดียวและคอมไพล์เป็น bytecode จากนั้นเราสามารถนำไปใช้กับระบบปฏิบัติการใดก็ได้ และ JVM ดั้งเดิมก็สามารถเรียกใช้ได้ และนี่คือตำนานของ Java แน่นอนเขียนครั้งเดียวเรียกใช้ได้ทุกที่
7. ไบต์โค้ดคืออะไร?
ดังที่ฉันได้กล่าวไว้ข้างต้น คอมไพเลอร์แปลงโค้ด Java เป็นbytecode ระดับกลาง (เราเปลี่ยนจากไฟล์ที่มีนามสกุล .java เป็นไฟล์ที่มีนามสกุล .class) ในหลาย ๆ ทาง bytecode คล้ายกับรหัสเครื่อง ยกเว้นว่าชุดคำสั่งนั้นไม่ใช่สำหรับโปรเซสเซอร์จริง แต่เป็นเสมือน ที่กล่าวว่าสามารถรวมส่วนที่ออกแบบมาสำหรับคอมไพเลอร์ JIT ซึ่งปรับการดำเนินการคำสั่งให้เหมาะสมสำหรับตัวประมวลผลจริงที่โปรแกรมกำลังทำงานอยู่ การคอมไพล์ JIT หรือที่เรียกว่าการคอมไพล์แบบ on-the-fly เป็นเทคโนโลยีที่เพิ่มประสิทธิภาพของโปรแกรม bytecode โดยการคอมไพล์ bytecode เป็นรหัสเครื่องหรือรูปแบบอื่นในขณะที่โปรแกรมกำลังทำงาน ตามที่คุณอาจคาดเดา JVM ใช้คอมไพเลอร์ JIT เมื่อเรียกใช้ bytecode มาดูตัวอย่าง bytecode:
8. คุณลักษณะของ JavaBean คืออะไร?
JavaBean เป็นคลาส Java ที่เป็นไปตามกฎบางอย่าง นี่คือกฎบางประการสำหรับการเขียนJavaBean :-
คลาสต้องมีคอนสตรัคเตอร์ว่าง (ไม่มีอาร์กิวเมนต์) พร้อมตัวดัดแปลงการเข้าถึงสาธารณะ ตัวสร้างนี้ทำให้สามารถสร้างวัตถุของคลาสได้โดยไม่มีปัญหาที่ไม่จำเป็น (เพื่อไม่ให้มีข้อโต้แย้งที่ไม่จำเป็น)
-
ฟิลด์ภายในสามารถเข้าถึงได้โดยใช้ วิธี รับและตั้งค่าอินสแตนซ์ ซึ่งควรมีการใช้งานมาตรฐาน ตัวอย่างเช่น หากเรามี ฟิลด์ ชื่อเราก็ควรมีgetNameและsetNameเป็นต้น ซึ่งจะช่วยให้เครื่องมือต่างๆ (เฟรมเวิร์ก) รับและตั้งค่าเนื้อหาของ bean โดยอัตโนมัติโดยไม่มีปัญหาใดๆ
-
คลาสจะต้องแทนที่วิธีการเท่ากับ () , hashCode ()และtoString ()
-
คลาสจะต้องทำให้เป็นอนุกรมได้ นั่นคือต้องมีอินเทอร์เฟซเครื่องหมาย Serializable หรือใช้อินเทอร์เฟซExternalizable ทั้งนี้เพื่อให้สถานะของ bean สามารถบันทึก จัดเก็บ และกู้คืนได้อย่างน่าเชื่อถือ

9. OutOfMemoryError คืออะไร
OutOfMemoryErrorเป็นข้อผิดพลาดรันไทม์ที่สำคัญที่เกี่ยวข้องกับ Java Virtual Machine (JVM) ข้อผิดพลาดนี้เกิดขึ้นเมื่อ JVM ไม่สามารถจัดสรรวัตถุได้เนื่องจากมีหน่วยความจำไม่เพียงพอ และตัวรวบรวมขยะไม่สามารถจัดสรรหน่วยความจำเพิ่มเติมได้ OutOfMemoryErrorบางประเภท:-
OutOfMemoryError: Java heap space — ไม่สามารถจัดสรรวัตถุบน Java heap ได้เนื่องจากหน่วยความจำไม่เพียงพอ ข้อผิดพลาดนี้อาจเกิดจากหน่วยความจำรั่วหรือขนาดฮีปเริ่มต้นที่เล็กเกินไปสำหรับแอปพลิเคชันปัจจุบัน
-
OutOfMemoryError: เกินขีดจำกัด GC Overhead — เนื่องจากข้อมูลของแอปพลิเคชันแทบจะไม่พอดีกับฮีป ตัวรวบรวมขยะจึงทำงานตลอดเวลา ทำให้โปรแกรม Java ทำงานช้ามาก เป็นผลให้เกินขีดจำกัดค่าโสหุ้ยตัวรวบรวมขยะและแอปพลิเคชันหยุดทำงานด้วยข้อผิดพลาดนี้
-
OutOfMemoryError: ขนาดอาร์เรย์ที่ร้องขอเกินขีดจำกัด VM — สิ่งนี้บ่งชี้ว่าแอปพลิเคชันพยายามจัดสรรหน่วยความจำสำหรับอาร์เรย์ที่เกินขนาดฮีป นี่อาจหมายความว่ามีการจัดสรรหน่วยความจำไม่เพียงพอตามค่าเริ่มต้น
-
OutOfMemoryError: Metaspace — ฮีปเต็มพื้นที่ที่จัดสรรไว้สำหรับข้อมูลเมตา (ข้อมูลเมตาเป็นคำแนะนำสำหรับคลาสและเมธอด)
-
OutOfMemoryError: ขอขนาดไบต์ด้วยเหตุผล ไม่มีพื้นที่สว็อป — ข้อผิดพลาดบางอย่างเกิดขึ้นเมื่อพยายามจัดสรรหน่วยความจำจากฮีป และส่งผลให้ฮีปมีพื้นที่ไม่เพียงพอ
10. สแต็กเทรซคืออะไร? ฉันจะรับได้อย่างไร
การติดตามสแต็กคือรายการของคลาสและเมธอดที่ถูกเรียกจนถึงจุดนี้ในการดำเนินการของแอปพลิเคชัน คุณสามารถรับการติดตามสแต็ก ณ จุดใดจุดหนึ่งในแอปพลิเคชันโดยทำดังนี้:
StackTraceElement[] stackTraceElements =Thread.currentThread().getStackTrace();
สิ่งนี้ทำให้เรามีอาร์เรย์ของ StackTraceElements ที่จัดเรียงตามลำดับ Last In First Out (LIFO) 
StackTraceElement[] stackTraceElements;
try{
...
} catch (Exception e) {
stackTraceElements = e.getStackTrace();
}
และถ้าเราต้องการแสดงสแต็กเทรซของข้อยกเว้นบนคอนโซล:
try{
...
} catch (Exception e) {
e.printStackTrace();
}
นอกจากนี้ หากเกิดข้อผิดพลาด ข้อยกเว้น ที่ไม่ได้ตรวจสอบหรือ ข้อยกเว้นที่ ตรวจสอบแล้วที่ไม่ได้จัดการ เราจะได้รับสแต็กเทรซของข้อยกเว้นบนคอนโซลโดยอัตโนมัติเมื่อแอปพลิเคชันหยุดทำงาน ต่อไปนี้คือตัวอย่างเล็กๆ ของสแต็กเทรซบนคอนโซล: 

GO TO FULL VERSION