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

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

เผยแพร่ในกลุ่ม
สวัสดีทุกคนอีกครั้ง! เรายังคงค้นหาคำตอบของคำถามมากกว่า 250 ข้อสำหรับนักพัฒนาระดับจูเนียร์ กลาง และอาวุโส คำถามค่อนข้างน่าสนใจและฉันเองก็ชอบที่จะวิเคราะห์: ในช่วงเวลาดังกล่าวคุณสามารถค้นพบช่องว่างในความรู้ทางทฤษฎีและในสถานที่ที่ไม่คาดคิดที่สุด การวิเคราะห์คำถามและคำตอบในการสัมภาษณ์  ส่วนที่ 2 - 1ส่วนก่อนหน้าสามารถพบได้ในบทความนี้ แต่ก่อนที่เราจะเริ่มต้น ฉันต้องการเตือนคุณว่า:
  1. ฉันจะข้าม คำถามที่ตัดกับบทความชุดนี้เพื่อไม่ให้ข้อมูลซ้ำกันอีกครั้ง ฉันขอแนะนำให้อ่านเอกสารเหล่านี้ เนื่องจากมีคำถามสัมภาษณ์ Java Core ที่พบบ่อยที่สุด (ยอดนิยม)
  2. คำถามเกี่ยวกับ DOU นำเสนอเป็นภาษายูเครน แต่ฉันจะมีทุกอย่างเป็นภาษารัสเซีย
  3. คำตอบสามารถอธิบายได้โดยละเอียดมากขึ้น แต่ฉันจะไม่อธิบาย เนื่องจากตั้งแต่นั้นมาคำตอบของแต่ละคำถามอาจใช้เวลาทั้งบทความ และพวกเขาจะไม่ถามคุณอย่างละเอียดในการสัมภาษณ์ใดๆ
หากจำเป็นฉันจะทิ้งลิงก์ไว้เพื่อศึกษาเชิงลึก บินกันเถอะ!

11. ตั้งชื่อวิธีการทั้งหมดของคลาส Object

คลาส Object มี 11 วิธี:
  • Class<?> getClass() — รับคลาสของอ็อบเจ็กต์ปัจจุบัน
  • int hashCode() — รับรหัสแฮชของวัตถุปัจจุบัน
  • บูลีนเท่ากับ(Object obj) - การเปรียบเทียบวัตถุปัจจุบันกับวัตถุอื่น
  • Object clone() - การสร้างและส่งคืนสำเนาของวัตถุปัจจุบัน
  • String toString() - รับการแสดงสตริงของวัตถุ
  • เป็นโมฆะแจ้งเตือน () - ปลุกหนึ่งเธรดที่รออยู่บนมอนิเตอร์ของวัตถุนี้ (การเลือกเธรดเป็นแบบสุ่ม)
  • เป็นโมฆะ notifyAll() - ปลุกเธรดทั้งหมดที่รออยู่บนจอภาพของวัตถุนี้
  • void wait() - เปลี่ยนเธรดปัจจุบันเป็นโหมดสแตนด์บาย (ค้าง) บนมอนิเตอร์ปัจจุบัน ใช้งานได้เฉพาะในบล็อกที่ซิงโครไนซ์จนกว่าบางคนจะแจ้งเตือนหรือ notifyAll ปลุกเธรด
  • รอเป็นโมฆะ(หมดเวลานาน) - ยังค้างเธรดปัจจุบันบนมอนิเตอร์ปัจจุบัน (บนอันที่ซิงโครไนซ์ปัจจุบัน) แต่ด้วยตัวจับเวลาเพื่อออกจากสถานะนี้ (หรืออีกครั้ง: จนกว่าจะแจ้งเตือนหรือแจ้งเตือนทั้งหมดจะตื่น)
  • การรอเป็นโมฆะ(การหมดเวลานาน, int nanos) - วิธีการที่คล้ายกับที่อธิบายไว้ข้างต้น แต่มีตัวจับเวลาที่แม่นยำยิ่งขึ้นสำหรับการออกจากการแช่แข็ง
  • ถือเป็นโมฆะสรุป() - ก่อนที่จะลบวัตถุนี้ ตัวรวบรวมขยะจะเรียกวิธีนี้ (ในที่สุด) มันถูกใช้เพื่อล้างทรัพยากรที่ถูกครอบครอง
หากต้องการใช้hashCode , เท่ากับ , clone , toStringและสรุปวิธีการอย่างถูกต้อง จะต้องกำหนดวิธีการใหม่ โดยคำนึงถึงงานและสถานการณ์ปัจจุบัน

12. อะไรคือความแตกต่างระหว่างการลองกับทรัพยากรและการลองจับในที่สุดเมื่อจัดการกับทรัพยากร?

โดยทั่วไป เมื่อใช้try-catch-finallyบล็อกสุดท้ายจะถูกใช้เพื่อปิดทรัพยากร Java 7 นำเสนอตัวดำเนินการรูปแบบใหม่try-with-resourcesซึ่งเป็นแบบอะนาล็อกของtry-catch-finallyสำหรับการเพิ่มทรัพยากร แต่มีขนาดกะทัดรัดและอ่านง่ายขึ้น โปรดจำไว้ว่าtry-catch-finally มีลักษณะอย่างไร :
String text = "some text......";
BufferedWriter bufferedWriter = null;
try {
   bufferedWriter = new BufferedWriter(new FileWriter("someFileName"));
   bufferedWriter.write(text);
} catch (IOException e) {
   e.printStackTrace();
} finally {
   try {
       bufferedWriter.close();
   } catch (IOException e) {
       e.printStackTrace();
   }
}
ตอนนี้เรามาเขียนโค้ดนี้ใหม่ แต่ใช้try-with-resources :
String text = "some text......";
try(BufferedWriter bufferedWriter =new BufferedWriter(new FileWriter("someFileName"))) {
   bufferedWriter.write(text);
} catch (IOException e) {
   e.printStackTrace();
}
มันจะง่ายขึ้นนะคุณว่ามั้ย? นอกจากการทำให้เข้าใจง่ายแล้ว ยังมีอีกสองสามประเด็น:
  1. ในtry-with-resourcesทรัพยากรที่ประกาศในวงเล็บ (ซึ่งจะถูกปิด) จะต้องใช้อินเทอร์เฟซ AutoCloseable และวิธีการเดียวคือclose( )

    วิธีการปิดจะดำเนินการโดยปริยายในที่สุด blockมิฉะนั้นโปรแกรมจะเข้าใจได้อย่างไรว่าจะปิดทรัพยากรที่กำหนดได้อย่างไร

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

  2. ลำดับการดำเนินการบล็อก:

    1. ลองบล็อก_
    2. โดยปริยายในที่สุด
    3. catch block ที่จับข้อยกเว้นในขั้นตอนก่อนหน้า
    4. ชัดเจนในที่สุด .

    ตามกฎแล้ว ข้อยกเว้นที่ปรากฏต่ำกว่าในรายการจะขัดจังหวะข้อยกเว้นที่ปรากฏสูงกว่า

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

13. การดำเนินการระดับบิตคืออะไร?

การดำเนินการระดับบิตคือการดำเนินการกับสตริงบิตที่รวมการดำเนินการเชิงตรรกะและการเลื่อนระดับบิต การดำเนินการเชิงตรรกะ:
  • ระดับบิตและ - เปรียบเทียบค่าบิตและในกระบวนการบิตใด ๆ ที่ตั้งค่าเป็น 0 (เท็จ) จะตั้งค่าบิตที่สอดคล้องกันในผลลัพธ์เป็น 0 นั่นคือถ้าทั้งสองค่าถูกเปรียบเทียบบิตคือ 1 (จริง) ผลลัพธ์จะเป็น 1 เช่นกัน

    แสดงว่า - และ , &

    ตัวอย่าง: 10111101 & 01100111 = 00100101

  • bitwise ORเป็นการดำเนินการผกผันของอันก่อนหน้า บิตใดๆ ที่ถูกตั้งค่าเป็น 1 จะทำให้บิตที่คล้ายกันในผลลัพธ์เป็น 1 และด้วยเหตุนี้ หากบิตเป็น 0 ในค่าที่เปรียบเทียบทั้งสองค่า บิตผลลัพธ์จะเป็น 0 เช่นกัน

    แสดงว่า - หรือ , |

    ตัวอย่าง: 10100101 | 01100011 = 11100111

  • bitwise NOT - ใช้กับค่าเดียว พลิก (กลับด้าน) บิต นั่นคือบิตเหล่านั้นที่เป็น 1 จะกลายเป็น 0 และอันที่เป็น 0 จะกลายเป็น 1

    แสดงว่า - ไม่ , ~

    ตัวอย่าง: ~10100101 = 01011010

  • เอกสิทธิ์ ระดับบิต หรือ - เปรียบเทียบค่าบิตและหากทั้งสองค่าบิตเท่ากับ 1 ผลลัพธ์จะเป็น 0 และหากในทั้งสองค่าบิตเป็น 0 ผลลัพธ์จะเป็น 0 นั่นคือ เพื่อให้ผลลัพธ์เท่ากับ 1 มีเพียงบิตเดียวเท่านั้นที่ต้องเท่ากับ 1 และบิตที่สองเท่ากับ 0

    แสดงว่า - XOR , ^

    ตัวอย่าง: 10100101 ^ 01100011 = 11000110

เลื่อนระดับบิต - >>หรือ<<เลื่อนบิตของค่าไปในทิศทางที่ระบุตามหมายเลขที่ระบุ ตำแหน่งว่างจะเต็มไปด้วยศูนย์ ตัวอย่างเช่น:
  1. 01100011 >> 4 = 00000110
  2. 01100011 << 3 = 00011000
นอกจากนี้ยังมีข้อยกเว้นเมื่อเลื่อนเลขลบไปทางขวา ดังที่คุณจำได้ บิตแรกมีหน้าที่รับผิดชอบต่อเครื่องหมาย และหากบิตนี้เท่ากับ 1 ตัวเลขนั้นจะเป็นลบ หากคุณย้ายจำนวนลบ ตำแหน่งที่ว่างจะไม่เต็มไปด้วยศูนย์อีกต่อไป แต่จะเต็มไปด้วยตำแหน่ง เนื่องจากจำเป็นต้องรักษาบิตเครื่องหมายไว้ ตัวอย่างเช่น: 10100010 >> 2 = 11101000 ในเวลาเดียวกันใน Java จะมีตัวดำเนินการเลื่อนขวาที่ไม่ได้ลงนามเพิ่มเติม >>> ตัวดำเนินการนี้เป็นอะนาล็อกของ >> เมื่อเปลี่ยนตำแหน่งที่ว่างจะเต็มไปด้วย 0 โดยไม่คำนึงว่า ตัวเลขเป็นลบหรือบวก ตัวอย่างเช่น: 10100010 >>> 2 = 00101000 อ่านเพิ่มเติมเกี่ยวกับการดำเนินการระดับบิตที่นี่ การวิเคราะห์คำถามและคำตอบในการสัมภาษณ์  ส่วนที่ 2 - 2เป็นตัวอย่างของการใช้การเลื่อนระดับบิตใน Java คุณสามารถอ้างอิงเมธอดhash()ของ HashMap ซึ่งใช้ในการกำหนดโค้ดแฮชภายในพิเศษสำหรับคีย์: การวิเคราะห์คำถามและคำตอบในการสัมภาษณ์  ส่วนที่ 2 - 3วิธีนี้ช่วยให้คุณกระจายข้อมูลใน HashMap เท่าๆ กันเพื่อลดขนาด จำนวนการชนกัน

14. คลาสที่ไม่เปลี่ยนรูปแบบมาตรฐานใดใน Java?

ไม่เปลี่ยนรูปเป็นวัตถุที่ไม่อนุญาตให้เปลี่ยนพารามิเตอร์ดั้งเดิม อาจมีเมธอดที่ส่งคืนออบเจ็กต์ใหม่ในประเภทที่กำหนด พร้อมด้วยพารามิเตอร์ที่คุณต้องการเปลี่ยนแปลง วัตถุที่ไม่เปลี่ยนรูปมาตรฐานบางตัว:
  • วัตถุที่ไม่เปลี่ยนรูปที่มีชื่อเสียงที่สุดใน Java คือ String;
  • อินสแตนซ์ของคลาส wrapper ที่รวมประเภทมาตรฐาน: บูลีน, อักขระ, ไบต์, สั้น, จำนวนเต็ม, ยาว, สองเท่า, ลอย;
  • วัตถุที่มักใช้สำหรับตัวเลขขนาดใหญ่โดยเฉพาะ - BigInteger และ BigDecimal
  • วัตถุที่เป็นหน่วยใน stacktrace (ตัวอย่างเช่น ใน stacktrace ข้อยกเว้น) StackTraceElement
  • วัตถุของคลาส File - สามารถเปลี่ยนไฟล์ได้ แต่ในขณะเดียวกันตัวมันเองก็ไม่เปลี่ยนรูป
  • UUID - ซึ่งมักใช้เป็นรหัสเฉพาะสำหรับองค์ประกอบ
  • อ็อบเจ็กต์คลาสทั้งหมดของแพ็คเกจ java.time
  • สถานที่ - ใช้เพื่อกำหนดภูมิภาคทางภูมิศาสตร์ การเมือง หรือวัฒนธรรม

15. ข้อดีของวัตถุที่ไม่เปลี่ยนรูปเหนือวัตถุทั่วไปคืออะไร?

  1. อ็อบเจ็กต์ดังกล่าวจะปลอดภัยเมื่อใช้ในสภาพแวดล้อมแบบมัลติเธรด เมื่อใช้สิ่งเหล่านี้ คุณจะไม่ต้องกังวลกับการสูญเสียข้อมูลเนื่องจากสภาพการแข่งขันของเธรด แตกต่างจากการทำงานกับวัตถุทั่วไป: ในกรณีนี้ คุณจะต้องคิดให้รอบคอบและหากลไกในการใช้วัตถุในสภาพแวดล้อมแบบขนาน
  2. วัตถุที่ไม่เปลี่ยนรูปเป็นคีย์ที่ดีในแผนที่ เพราะหากคุณใช้วัตถุที่ไม่แน่นอนแล้ววัตถุเปลี่ยนสถานะ อาจทำให้เกิดความสับสนเมื่อใช้ HashMap: วัตถุจะยังคงอยู่ และหากคุณใช้containsKey()ก็อาจไม่ สามารถพบได้
  3. วัตถุที่ไม่เปลี่ยนรูปเหมาะอย่างยิ่งสำหรับการจัดเก็บข้อมูลที่ไม่เปลี่ยนรูป (คงที่) ซึ่งไม่ควรเปลี่ยนแปลงในขณะที่โปรแกรมกำลังทำงาน
  4. “ความเป็นปรมาณูจนถึงความล้มเหลว” - หากวัตถุที่ไม่เปลี่ยนรูปทำให้เกิดข้อยกเว้น วัตถุนั้นจะยังคงอยู่ในสถานะที่ไม่ต้องการ (แตกหัก)
  5. ชั้นเรียนเหล่านี้ง่ายต่อการทดสอบ
  6. ไม่จำเป็นต้องมีกลไกเพิ่มเติม เช่น ตัวสร้างการคัดลอกและการใช้งานโคลน

คำถามเกี่ยวกับ OOP

การวิเคราะห์คำถามและคำตอบในการสัมภาษณ์  ส่วนที่ 2 - 4

16. อะไรคือข้อดีของ OOP โดยทั่วไปและเมื่อเปรียบเทียบกับการเขียนโปรแกรมตามขั้นตอน?

ดังนั้นข้อดีของ OOP:
  1. แอปพลิเคชันที่ซับซ้อนเขียนได้ง่ายกว่าการเขียนโปรแกรมตามขั้นตอน เนื่องจากทุกอย่างถูกแบ่งออกเป็นโมดูลขนาดเล็ก - อ็อบเจ็กต์ที่มีปฏิสัมพันธ์ระหว่างกัน - และด้วยเหตุนี้การเขียนโปรแกรมจึงลงมาที่ความสัมพันธ์ระหว่างอ็อบเจ็กต์
  2. แอปพลิเคชันที่เขียนโดยใช้ OOP นั้นแก้ไขได้ง่ายกว่ามาก (ตราบใดที่ปฏิบัติตามแนวคิดการออกแบบ)
  3. เนื่องจากข้อมูลและการดำเนินการบนข้อมูลเป็นเอนทิตีเดียว จึงไม่เลอะทั่วทั้งแอปพลิเคชัน (ซึ่งมักเกิดขึ้นกับการเขียนโปรแกรมตามขั้นตอน)
  4. การห่อหุ้มข้อมูลช่วยปกป้องข้อมูลที่สำคัญที่สุดจากผู้ใช้
  5. เป็นไปได้ที่จะนำโค้ดเดิมกลับมาใช้ซ้ำกับข้อมูลที่แตกต่างกัน เนื่องจากคลาสอนุญาตให้คุณสร้างออบเจ็กต์จำนวนมาก ซึ่งแต่ละออบเจ็กต์มีค่าแอตทริบิวต์ของตัวเอง
  6. การสืบทอดและความหลากหลายยังช่วยให้คุณสามารถใช้ซ้ำและขยายโค้ดที่มีอยู่ได้ (แทนที่จะทำซ้ำฟังก์ชันการทำงานที่คล้ายกัน)
  7. ความสามารถในการขยายการใช้งานได้ง่ายกว่าวิธีการแบบเป็นขั้นตอน
  8. วิธีการ OOP ทำให้สามารถสรุปจากรายละเอียดการใช้งานได้

17. บอกเราว่ามีข้อบกพร่องอะไรบ้างใน OOP

น่าเสียดายที่ยังมีอยู่ด้วย:
  1. OOP ต้องใช้ความรู้ทางทฤษฎีจำนวนมากซึ่งต้องได้รับการเรียนรู้ก่อนจึงจะสามารถเขียนอะไรก็ได้การวิเคราะห์คำถามและคำตอบในการสัมภาษณ์  ส่วนที่ 2 - 5
  2. แนวคิดของ OOP ไม่ใช่เรื่องง่ายที่จะเข้าใจและนำไปใช้ในทางปฏิบัติ (คุณต้องมีหัวใจของนักปรัชญาสักหน่อย)
  3. เมื่อใช้ OOP ประสิทธิภาพของซอฟต์แวร์จะลดลงเล็กน้อยเนื่องจากการจัดระเบียบของระบบที่ซับซ้อนมากขึ้น
  4. วิธี OOP ต้องใช้หน่วยความจำมากขึ้น เนื่องจากทุกอย่างประกอบด้วยคลาส อินเทอร์เฟซ วิธีการ ซึ่งใช้หน่วยความจำมากกว่าตัวแปรทั่วไปมาก
  5. เวลาที่จำเป็นสำหรับการวิเคราะห์เบื้องต้นนั้นมากกว่าเวลาที่ใช้ในขั้นตอน

18. ความหลากหลายแบบคงที่และไดนามิกคืออะไร

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

19. กำหนดหลักการของนามธรรมใน OOP

นามธรรมใน OOP เป็นวิธีการเน้นชุดคุณลักษณะที่สำคัญของวัตถุ ยกเว้นรายละเอียดที่ไม่สำคัญ นั่นคือ เมื่อออกแบบโปรแกรมด้วยแนวทาง OOP คุณจะมุ่งเน้นไปที่โมเดลโดยทั่วไป โดยไม่ต้องเจาะลึกรายละเอียดของการใช้งาน ใน Java อินเทอร์เฟซ มีหน้าที่รับผิดชอบต่อสิ่งที่เป็น นามธรรม ตัวอย่างเช่น คุณมีเครื่องจักร และนี่คืออินเทอร์เฟซ และการโต้ตอบต่างๆ กับมัน เช่น การสตาร์ทเครื่องยนต์ การใช้กระปุกเกียร์ สิ่งเหล่านี้คือฟังก์ชันที่เราใช้โดยไม่ต้องลงรายละเอียดการใช้งาน ท้ายที่สุดแล้วในขณะที่คุณกำลังขับรถคุณไม่ได้คิดว่ากระปุกเกียร์ตอบสนองวัตถุประสงค์ของมันได้อย่างไรหรือกุญแจสตาร์ทเครื่องยนต์อย่างไรหรือพวงมาลัยหมุนล้ออย่างไร และแม้ว่าการใช้งานฟังก์ชันอย่างใดอย่างหนึ่งนี้จะถูกแทนที่ (เช่น เครื่องยนต์) คุณอาจไม่สังเกตเห็น สิ่งนี้ไม่สำคัญสำหรับคุณ: คุณไม่ต้องลงรายละเอียดเกี่ยวกับการนำไปใช้งาน เป็นสิ่งสำคัญสำหรับคุณที่จะดำเนินการ จริงๆ แล้วนี่คือสิ่งที่เป็นนามธรรมจากรายละเอียดการใช้งาน นี่คือจุดที่เราจะหยุดในวันนี้: ดำเนินต่อไป!การวิเคราะห์คำถามและคำตอบในการสัมภาษณ์  ส่วนที่ 2 - 6
วัสดุอื่นๆ ในชุด:
ความคิดเห็น
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION