สวัสดีทุกคน วันนี้ฉันจะมาวิเคราะห์ คำถามสัมภาษณ์ มากกว่า 250 ข้อสำหรับ Java Developer ต่อไป ส่วนก่อนหน้าของการวิเคราะห์: อันดับแรก , ที่สอง , ที่สาม งั้นมาทำต่อเลย
<ชื่อคลาส>{สืบทอดจากคลาสผู้ปกครอง} {การนำอินเทอร์เฟซไปใช้}
ดังนั้นสิ่งที่เรามี: {class access modifier} - เฉพาะตัวแก้ไข สาธารณะและตัวแก้ไขการเข้าถึงที่ขาดหายไป ซึ่งก็คือdefault เท่านั้นที่พร้อมใช้งาน สำหรับ คลาส {class static} - staticเป็นตัวดัดแปลงที่ระบุว่าคลาสนี้เป็นแบบคงที่ ใช้ได้กับคลาสภายในเท่านั้น (คลาสภายในคลาสอื่น) {class Finality} - ตามที่เราจำได้ นี่คือ ตัวแก้ไข ขั้นสุดท้ายโดยที่คลาสจะไม่สามารถสืบทอดได้ (ตัวอย่างจากกล่อง - String ) {class abstraction} - modifier - abstractซึ่งบ่งชี้ว่าคลาสนี้อาจมีวิธีการที่ไม่ได้ใช้งาน ตัวแก้ไขนี้ขัดแย้งกับ ตัวแก้ไข สุดท้ายนั่นคือมีเพียงตัวเดียวเท่านั้นที่สามารถอยู่ในส่วนหัวของคลาสได้ เนื่องจาก ตัวแก้ไข นามธรรมบอกเป็นนัยว่าคลาสที่กำหนดจะได้รับการสืบทอดและส่วนนามธรรมจะถูกนำไปใช้ และสุดท้ายบ่งชี้ว่านี่เป็นเวอร์ชันสุดท้าย (สุดท้าย) ของคลาส และไม่สามารถสืบทอดได้ จริงๆ แล้ว การใช้ตัวดัดแปลงทั้งสองพร้อมกันคงเป็นเรื่องไร้สาระ และคอมไพเลอร์จะไม่อนุญาตให้เราทำสิ่งนี้ <class>เป็นคีย์เวิร์ดที่จำเป็นซึ่งระบุการประกาศคลาส <ชื่อคลาส>เป็นชื่อคลาสแบบง่าย ซึ่งเป็นตัวระบุคลาส Java เฉพาะ ชื่อคลาสแบบเต็มประกอบด้วยชื่อแพ็กเกจแบบเต็ม + + ชื่อคลาสธรรมดา {การสืบทอดจากคลาสผู้ปกครอง} - การระบุคลาสพาเรนต์ (ถ้ามี) โดยใช้ คีย์เวิร์ด ขยาย ตัวอย่างเช่น .. ขยาย ParentClass {การใช้งานอินเทอร์เฟซ} - การระบุอินเทอร์เฟซที่คลาสนี้นำไปใช้ (ถ้ามี) โดยใช้ คำ หลักApplys ตัวอย่างเช่น: ... ใช้ FirstInterface, SecondInterface ... เอาล่ะ เป็นตัวอย่างของส่วนหัวของคลาส ให้พิจารณาส่วนหัวของ คลาส Lionซึ่งสืบทอดมาจากCatและใช้ อินเทอร์เฟซ WildAnimal :
29. เป็นไปได้ไหมที่จะใช้ return ในตัวสร้าง?
คุณสามารถ ทำได้แต่ไม่มีค่าส่งคืนทางด้านขวาของreturn นั่นคือคุณสามารถใช้return; เป็นการก่อสร้างเสริมระหว่างการคำนวณในตัวสร้างเพื่อที่จะเสร็จสิ้นการดำเนินการโค้ดเพิ่มเติมอย่างเร่งด่วน (ขัดจังหวะ) และดำเนินการเริ่มต้นของวัตถุให้เสร็จสิ้น ตัวอย่างเช่น เรามีคลาสCatและหากCatไม่มีที่อยู่อาศัย - isHomeless = trueเราจำเป็นต้องเริ่มต้นการกำหนดค่าให้เสร็จสิ้นและไม่กรอกข้อมูลในฟิลด์อื่น ๆ (เพราะเราไม่รู้จักพวกมันเนื่องจากแมวไม่มีที่อยู่อาศัย):public Cat(int age, String name, boolean isHomeless) {
if (isHomeless){
this.isHomeless = isHomeless;
return;
}
this.isHomeless = isHomeless;
this.age = age;
this.name = name;
}
แต่เมื่อพูดถึงค่าเฉพาะ Constructor ไม่สามารถใช้ return เพื่อคืนค่าได้เนื่องจาก:
- เมื่อประกาศ Constructor คุณจะไม่มีอะไรที่คล้ายกับประเภทการคืนสินค้า
- โดยทั่วไปแล้ว ตัวสร้างจะถูกเรียกโดยปริยายในระหว่างการสร้างอินสแตนซ์
- Constructor ไม่ใช่วิธีการ แต่เป็นกลไกที่แยกจากกันซึ่งมีวัตถุประสงค์เพียงอย่างเดียวในการเริ่มต้นตัวแปรอินสแตนซ์ และผู้ ปฏิบัติงาน ใหม่ มีหน้าที่รับผิดชอบในการสร้างวัตถุ
30. เป็นไปได้ไหมที่จะโยนข้อยกเว้นจากตัวสร้าง?
ตัวสร้างจัดการกับข้อยกเว้นในลักษณะเดียวกับวิธีการทุกประการ และหากเมธอดอนุญาตให้เราโยนข้อยกเว้นโดยการเขียน<ExceptionType> ในส่วนหัว ของเมธอด Constructor จะอนุญาตให้เราทำสิ่งนี้ได้ และเมื่อสืบทอดและกำหนด Constructor ที่สืบทอดมา เราก็สามารถขยายประเภทข้อยกเว้นได้ ตัวอย่างเช่น IOException -> ข้อยกเว้น (แต่ไม่ใช่ในทางกลับกัน) เพื่อเป็นตัวอย่างในการส่งข้อยกเว้นโดย Constructor ลองใช้ คลาส Catกัน สมมติว่าเมื่อสร้างมันขึ้นมาเราต้องการป้อนชื่อและอายุจากคอนโซล:public Cat() throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
this.name = reader.readLine();
this.age = Integer.parseInt(reader.readLine());
}
เนื่องจากreader.readLine()ส่ง IOException เราจึงระบุในส่วนหัวว่าเป็นข้อยกเว้นที่เป็นไปได้
31. ส่วนหัวของคลาสประกอบด้วยองค์ประกอบใดบ้าง? เขียนตัวอย่าง
เมื่อพูดถึงองค์ประกอบที่ประกอบเป็นส่วนหัวของคลาส ลองดูแผนภาพเล็กๆ กัน:- ส่วนประกอบบังคับจะอยู่ในวงเล็บ <>
- ทางเลือก - ใน {}
public final class Lion extends Cat implements WildAnimal
32. ส่วนหัวของ method ประกอบด้วยองค์ประกอบใดบ้าง? เขียนตัวอย่าง
อีกครั้ง เมื่อดูองค์ประกอบที่ประกอบเป็นส่วนหัวของวิธีการ ให้พิจารณาแผนภาพขนาดเล็กโดยที่:- ส่วนประกอบบังคับอยู่ในวงเล็บ <>
- ทางเลือก - ใน {}
public static void main(String[] args) throws IOException
33. สร้างคอนสตรัคเตอร์เริ่มต้นในวัตถุสืบทอดหากไม่ได้กำหนดไว้ในวัตถุฐาน (แต่มีการกำหนดคอนสตรัคเตอร์อื่นไว้)
ฉันไม่เข้าใจคำถามนั้นอย่างถ่องแท้ แต่บางทีมันอาจหมายความว่า ตัวอย่างเช่น ในพาเรนต์ เรามีตัวสร้างแบบกำหนดเอง:public Cat(int age, String name) {
this.age = age;
this.name = name;
}
ดังนั้นในคลาส ancestor เราจำเป็นต้องกำหนด Constructor ที่จะเติม (เรียก) Constructor หลัก:
public class Lion extends Cat {
public Lion(int age, String name) {
super(age, name);
}
}
34. คำสำคัญนี้ใช้เมื่อใด?
ในภาษา Java สิ่งนี้มีสองความหมายที่แตกต่างกัน 1. เพื่ออ้างอิงถึงวัตถุปัจจุบัน เช่นthis.age = 9 นั่นคือสิ่งนี้หมายถึงวัตถุที่ถูกเรียกและโค้ดที่ใช้สิ่งนี้ อ้างอิง ถึง หน้าที่หลักคือเพิ่มความสามารถในการอ่านโค้ดและหลีกเลี่ยงความคลุมเครือ ตัวอย่างเช่น ถ้าชื่อของฟิลด์คลาสภายในและอาร์กิวเมนต์ของเมธอดเหมือนกัน:public void setName(String name) {
this.name = name;
}
นั่นคือthis.nameเป็นเขตข้อมูลของ ชื่อ วัตถุ เป็นอาร์กิวเมนต์วิธีการ การอ้างอิงนี้ไม่สามารถใช้ในวิธีการแบบคงที่ 2. สิ่งนี้ สามารถใช้ในตัวสร้างในรูปแบบของการเรียก ใช้เมธอด เช่นthis(value) ในกรณีนี้ มันจะเป็นการเรียกไปยัง Constructor อื่นในคลาสเดียวกัน กล่าวโดยสรุป คุณสามารถเรียก Constructor สองตัวพร้อมกันเมื่อสร้าง Object:
public Cat(int age, String name) {
this(name);
this.age = age;
}
public Cat(String name) {
this.name = name;
}
เมื่อ วัตถุ Cat ถูกสร้างขึ้น และเรียกใช้ตัวสร้างตัวแรก ทั้งสองฟิลด์ของวัตถุจะถูกเรียกและเริ่มต้นได้สำเร็จ มีความแตกต่างสองสามประการ:
- this()ใช้งานได้ในตัวสร้างเท่านั้น
- การอ้างอิงถึงตัวสร้างอื่นจะต้องอยู่ในบรรทัดแรกของบล็อกตัวสร้าง (เนื้อหา) ดังนั้น ไม่สามารถเรียกคอนสตรัคเตอร์ (อื่นๆ) มากกว่าหนึ่งตัวของคลาสที่กำหนดในตัวสร้างเดียวได้
35. ตัวเริ่มต้นคืออะไร?
เท่าที่ฉันเข้าใจ ในคำถามนี้ เรากำลังพูดถึงบล็อกการเริ่มต้นแบบธรรมดาและแบบสถิติ ก่อนอื่น เรามาจำไว้ว่าการเริ่มต้นคืออะไร การเริ่มต้นคือการสร้าง การเปิดใช้งาน การเตรียมงาน การกำหนดพารามิเตอร์ การนำโปรแกรมหรือส่วนประกอบเข้าสู่สภาวะพร้อมใช้งาน อย่างที่คุณจำได้ ในระหว่างการสร้างอ็อบเจ็กต์ ตัวแปรคลาสสามารถเริ่มต้นได้โดยตรงจากการประกาศ:class Cat {
private int age = 9;
private String name = "Tom";
หรือตั้งค่าภายนอกผ่านตัวสร้าง:
class Cat {
private int age;
private String name;
public Cat(int age, String name) {
this.age = age;
this.name = name;
}
แต่มีวิธีอื่น: การตั้งค่าตัวแปรอ็อบเจ็กต์ภายในผ่านบล็อกการเริ่มต้น ซึ่งดูเหมือนวงเล็บปีกกา{ }ภายในคลาส โดยไม่มีชื่อ (เช่น วิธีการหรือตัวสร้าง):
class Cat {
private int age;
private String name;
{
age = 10;
name = "Tom";
}
นั่นคือ บล็อกการเริ่มต้นคือโค้ดชิ้นหนึ่งที่ถูกโหลดเมื่อสร้างออบเจ็กต์ โดยทั่วไป บล็อกดังกล่าวจะใช้ในการคำนวณที่ซับซ้อนซึ่งจำเป็นเมื่อโหลดคลาส ผลลัพธ์ของการคำนวณเหล่านี้สามารถระบุเป็นค่าสำหรับตัวแปรได้ นอกจากนี้ นอกเหนือจากบล็อกการเริ่มต้นปกติแล้ว ยังมีบล็อกแบบคงที่ซึ่งมีลักษณะเหมือนกัน แต่มีคำหลัก แบบคงที่อยู่ข้างหน้าวงเล็บปีกกา:
class Cat {
private static int age;
private static String name;
static{
age = 10;
name = "Tom";
}
บล็อกนี้เหมือนกับบล็อกก่อนหน้าทุกประการ แต่หากวัตถุปกติถูกทริกเกอร์เมื่อแต่ละวัตถุถูกเตรียมใช้งาน วัตถุแบบคงที่จะทริกเกอร์เพียงครั้งเดียวเมื่อคลาสถูกโหลด ตามกฎแล้วในบล็อกดังกล่าว การคำนวณที่ซับซ้อนบางอย่างจะดำเนินการด้วยสำหรับการเริ่มต้นตัวแปรคลาสคงที่ในภายหลัง ข้อจำกัดเดียวกันนี้ใช้กับบล็อกแบบคงที่เช่นเดียวกับวิธี การแบบคงที่: ไม่สามารถใช้ข้อมูลที่ไม่คงที่ได้ เช่นเดียวกับการอ้างอิงถึงวัตถุปัจจุบัน - นี่ ต่อไป เราจะเห็นลำดับการเริ่มต้นของคลาส (ร่วมกับบรรพบุรุษ) เพื่อความเข้าใจที่ดีขึ้นเกี่ยวกับช่วงเวลาที่บล็อกการเริ่มต้นถูกทริกเกอร์
36. ในการสืบทอดคลาส public class Child ขยาย Parent ให้เขียนลำดับการเริ่มต้นของอ็อบเจ็กต์
เมื่อโหลดคลาส Child ลำดับการเริ่มต้นจะเป็นดังนี้:- ฟิลด์คงที่ของคลาสParent
- บล็อกการเริ่มต้นแบบคง ที่สำหรับ คลาส Parent
- ฟิลด์คงที่ของคลาสChild
- บล็อกการเริ่มต้นแบบคง ที่สำหรับ คลาส Child
- ฟิลด์ที่ไม่คงที่ของคลาสParent
- ไม่ใช่บล็อกการเริ่มต้นแบบคงที่สำหรับคลาสParent
- ตัวสร้างสำหรับคลาสParent
- ฟิลด์ที่ไม่คงที่ของ คลาส Child
- ไม่ใช่บล็อกการเริ่มต้นแบบคงที่สำหรับคลาสChild
- ตัวสร้างคลาสChild
37. คุณรู้ความสัมพันธ์อะไรระหว่างคลาส (วัตถุ)?
ความสัมพันธ์ระหว่างคลาสใน Java มีสองประเภท:- IS-ความสัมพันธ์
Lion IS-A Cat
(แต่ไม่ใช่ทุกCat is a Lion ) สถานการณ์จะเหมือนกันทุกประการกับอินเทอร์เฟซ หาก คลาส Lionใช้ อินเทอร์เฟซ WildAnimalแสดงว่าพวกมันยังมีความสัมพันธ์กัน:
Lion IS-A WildAnimal
- ความสัมพันธ์แบบมี-เอ
Car HAS-A Passenger
และในทางกลับกัน: หากPassengerมีการอ้างอิงถึงCarนี่จะเป็นความสัมพันธ์:
Passenger HAS-A Car
38. คุณรู้ความเชื่อมโยงระหว่างวัตถุอะไรบ้าง?
การรวมกลุ่มและการจัดองค์ประกอบไม่ใช่อะไรมากไปกว่าการรวมกลุ่มกรณีพิเศษ การรวมกลุ่มคือความสัมพันธ์ที่วัตถุหนึ่งเป็นส่วนหนึ่งของอีกวัตถุหนึ่ง ตัวอย่างเช่น ผู้โดยสารอาจอยู่ในรถยนต์ นอกจากนี้อาจมีผู้โดยสารหลายคนหรือไม่มีเลย (หากเรากำลังพูดถึง Tesla ก็ไม่จำเป็นต้องใช้คนขับ) ตัวอย่างเช่น:public class Car {
private List passengers = new ArrayList<>();
void setPassenger(Passenger passenger) {
passengers.add(passenger);
}
void move() {
for (Passenger passenger : passengers) {
System.out.println("Перевозка пассажира - " + passenger.toString());
}
passengers.clear();
}
}
นั่นคือเราไม่สนใจจำนวนผู้โดยสาร (หรือว่ามีเลย): ฟังก์ชั่นของ คลาส Carไม่ได้ขึ้นอยู่กับสิ่งนี้ การรวมกลุ่มยังบอกเป็นนัยว่าเมื่อวัตถุถูกใช้โดยวัตถุอื่น วัตถุแรกสามารถนำไปใช้กับวัตถุอื่นได้ ตัวอย่างเช่น นักเรียนคนเดียวกันสามารถเป็นสมาชิกของทั้งชมรมถักนิตติ้งและกลุ่มดนตรีร็อค และในขณะเดียวกันก็ไปที่กลุ่มผู้เรียนภาษาอังกฤษ ดังที่คุณเข้าใจ การรวมกลุ่มคือความสัมพันธ์ที่หลวมกว่าระหว่างชั้นเรียน องค์ประกอบคือความสัมพันธ์ที่เข้มงวดยิ่งขึ้น เมื่อวัตถุไม่ได้เป็นเพียงส่วนหนึ่งของวัตถุอื่นเท่านั้น แต่งานของวัตถุอีกชิ้นนั้นขึ้นอยู่กับวัตถุชิ้นแรกเป็นอย่างมาก ยกตัวอย่างเครื่องยนต์ของรถยนต์ แม้ว่าเครื่องยนต์จะอยู่ได้โดยไม่มีรถยนต์ แต่ภายนอกเครื่องยนต์ก็ไม่มีประโยชน์ รถยนต์ไม่สามารถทำงานได้หากไม่มีเครื่องยนต์:
public class Car {
private Engine engine;
public Car(Engine engine) {
this.engine = engine;
}
void startMoving() {
engine.start();
...
}
องค์ประกอบยังบอกเป็นนัยว่าเมื่อวัตถุถูกใช้โดยวัตถุอื่น วัตถุแรกไม่สามารถเป็นของบุคคลอื่นได้ หากเรากลับมาที่ตัวอย่างของเรา เครื่องยนต์สามารถเป็นของรถคันเดียวเท่านั้น แต่ไม่สามารถเป็นของสองคันขึ้นไปในเวลาเดียวกันได้ วันนี้เราคงจะหยุดที่นี่
GO TO FULL VERSION