JavaRush /Blog Java /Random-VI /Phân tích các câu hỏi và câu trả lời từ các cuộc phỏng vấ...

Phân tích các câu hỏi và câu trả lời từ các cuộc phỏng vấn dành cho nhà phát triển Java. Phần 4

Xuất bản trong nhóm
Xin chào mọi người, hôm nay mình tiếp tục phân tích hơn 250 câu hỏi phỏng vấn Java dev. Phân tích các câu hỏi và câu trả lời từ các cuộc phỏng vấn dành cho nhà phát triển Java.  Phần 4 - 1Các phần phân tích trước đó: thứ nhất , thứ hai , thứ ba . Vì vậy hãy tiếp tục.

29. Có thể sử dụng return trong hàm tạo không?

Bạn có thể, nhưng không có giá trị trả về ở bên phải return . Nghĩa là, bạn có thể sử dụng return; như một công trình phụ trợ trong quá trình tính toán trong hàm tạo nhằm khẩn trương hoàn thành (ngắt) việc thực thi mã tiếp theo và hoàn thành việc khởi tạo đối tượng. Ví dụ: chúng ta có một lớp Cat và nếu Cat là người vô gia cư - isHomeless = true , chúng ta cần hoàn thành quá trình khởi tạo và không điền vào các trường khác (xét cho cùng, chúng ta không biết chúng vì con mèo là người vô gia cư):
public Cat(int age, String name, boolean isHomeless) {
   if (isHomeless){
       this.isHomeless = isHomeless;
       return;
   }
   this.isHomeless = isHomeless;
   this.age = age;
   this.name = name;
}
Nhưng khi nói đến các giá trị cụ thể, hàm tạo không thể sử dụng return để trả về một giá trị vì:
  • khi khai báo một hàm tạo, bạn sẽ không có bất kỳ thứ gì giống với kiểu trả về;
  • Thông thường, hàm tạo được gọi ngầm trong quá trình khởi tạo;
  • Hàm tạo không phải là một phương thức: nó là một cơ chế riêng biệt với mục đích duy nhất là khởi tạo các biến thể hiện và toán tử new chịu trách nhiệm tạo một đối tượng .
Phân tích các câu hỏi và câu trả lời từ các cuộc phỏng vấn dành cho nhà phát triển Java.  Phần 4 - 2

30. Có thể ném ngoại lệ từ một hàm tạo không?

Các nhà xây dựng xử lý các ngoại lệ theo cách giống hệt như các phương thức. Và nếu các phương thức cho phép chúng ta ném ngoại lệ bằng cách viết Throws <ExceptionType> vào tiêu đề phương thức , thì hàm tạo cho phép chúng ta thực hiện điều này và khi kế thừa và xác định hàm tạo kế thừa, chúng ta có thể mở rộng loại ngoại lệ. Ví dụ: IOException -> Exception (nhưng không phải ngược lại). Để làm ví dụ về việc đưa ra một ngoại lệ bởi hàm tạo, hãy lấy lớp Cat . Giả sử khi tạo nó, chúng ta muốn nhập tên và tuổi từ bảng điều khiển:
public Cat() throws IOException {
   BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
   this.name = reader.readLine();
   this.age = Integer.parseInt(reader.readLine());
}
reader.readLine() ném ra IOException nên chúng tôi chỉ định nó trong tiêu đề dưới dạng một ngoại lệ có thể được ném ra.

31. Tiêu đề lớp bao gồm những thành phần nào? Viết một ví dụ

Nói về các thành phần tạo nên tiêu đề lớp, chúng ta hãy xem một sơ đồ nhỏ:
  • thành phần bắt buộc sẽ nằm trong ngoặc <>
  • tùy chọn - trong {}
{công cụ sửa đổi truy cập lớp}{class staticity}{class Finality}{class abstraction} <tên lớp>{kế thừa từ lớp cha} {thực hiện giao diện} Vì vậy, những gì chúng ta có: {class access modifier} - chỉ các công cụ sửa đổi công khai và công cụ sửa đổi truy cập bị thiếu, tức là default , mới có sẵn cho lớp . {class static} - static là công cụ sửa đổi cho biết lớp này là tĩnh, chỉ áp dụng cho các lớp bên trong (các lớp bên trong các lớp khác). {class Finality} - như chúng ta nhớ, đây là công cụ sửa đổi cuối cùng , khi có lớp đó trở thành không thể kế thừa (ví dụ từ hộp - String ). {class abstraction} - modifier - abstract , cho biết lớp này có thể có các phương thức chưa được triển khai. Công cụ sửa đổi này xung đột với công cụ sửa đổi cuối cùng , nghĩa là chỉ một trong số chúng có thể nằm trong tiêu đề lớp, vì công cụ sửa đổi trừu tượng ngụ ý rằng lớp đã cho sẽ được kế thừa và các phần trừu tượng của nó sẽ được triển khai. Và cuối cùng chỉ ra rằng đây là phiên bản cuối cùng (cuối cùng) của lớp và nó không thể được kế thừa. Trên thực tế, việc sử dụng cả hai từ bổ nghĩa cùng lúc sẽ là điều vô lý và trình biên dịch sẽ không cho phép chúng ta làm điều này. <class> là từ khóa bắt buộc dùng để khai báo lớp. <tên lớp> là tên lớp đơn giản, là mã định danh của một lớp Java cụ thể. Tên lớp đủ điều kiện bao gồm tên gói đủ điều kiện + . + Tên lớp đơn giản. {inheritance from Parent class} - chỉ định lớp cha (nếu có) bằng từ khóa mở rộng . Ví dụ: .. mở rộng ParentClass . {triển khai giao diện} - chỉ định các giao diện mà lớp này triển khai (nếu có) bằng cách sử dụng từ khóa triển khai . Ví dụ: ... triển khai FirstInterface, SecondInterface ... Vâng, như một ví dụ về tiêu đề lớp, hãy xem xét tiêu đề của lớp Lion , kế thừa từ Cat và triển khai giao diện WildAnimal :
public final class Lion extends Cat implements WildAnimal
Phân tích các câu hỏi và câu trả lời từ các cuộc phỏng vấn dành cho nhà phát triển Java.  Phần 4 - 3

32. Tiêu đề của phương thức bao gồm những thành phần nào? Viết một ví dụ

Một lần nữa, khi xem xét các phần tử tạo nên tiêu đề phương thức, hãy xem xét một sơ đồ nhỏ trong đó:
  • thành phần bắt buộc nằm trong ngoặc <>
  • tùy chọn - trong {}
{công cụ sửa đổi truy cập}{phương thức tĩnh}{trừu tượng phương thức}{phương thức cuối cùng}{công cụ sửa đổi đồng bộ hóa} {công cụ sửa đổi gốc<giá trị trả về><tên phương thức> <(> {đối số phương thức} <)>{ngoại lệ được ném ra} {công cụ sửa đổi truy cập } — tất cả các công cụ sửa đổi quyền truy cập đều có sẵn cho phương thức: public , protected , default , private . {method static} - static là một công cụ sửa đổi cho biết rằng phương thức này là tĩnh, nghĩa là nó không được gắn với một đối tượng mà với một lớp. {trừu tượng hóa phương thức} là công cụ sửa đổi trừu tượng , cho biết rằng không có phần triển khai (nội dung) của phương thức. Để hoạt động chính xác, bạn cũng cần một công cụ sửa đổi trừu tượng cho lớp mà phương thức được cung cấp. Như trong tiêu đề lớp, công cụ sửa đổi này xung đột với công cụ sửa đổi cuối cùng , nhưng ngoài nó ra, nó còn xung đột với công cụ sửa đổi tĩnh , bởi vì một phương thức trừu tượng ngụ ý ghi đè phương thức đó ở phần tử con và các phương thức tĩnh không bị ghi đè. {sự cuối cùng của phương thức} - cuối cùng - một công cụ sửa đổi cho biết rằng phương thức này không thể bị ghi đè. {công cụ sửa đổi đồng bộ hóa} - được đồng bộ hóa - một công cụ sửa đổi có nghĩa là phương thức này được bảo vệ khỏi sự truy cập đồng thời vào nó từ các luồng khác nhau. Nếu phương thức không tĩnh, nó sẽ đóng trên mutex này của đối tượng. Nếu phương thức là tĩnh, nó sẽ đóng trên mutex của lớp hiện tại. {công cụ sửa đổi gốc} - công cụ sửa đổi gốc - công cụ sửa đổi này cho biết rằng phương thức này được viết bằng ngôn ngữ lập trình khác. <giá trị trả về> là loại giá trị mà phương thức sẽ trả về. Nếu nó không trả lại bất cứ thứ gì, void . <tên phương thức> là tên phương thức, định danh của nó trong hệ thống. {đối số phương thức} là các đối số (tham số) mà phương thức lấy: chúng cần thiết để triển khai chức năng của nó. {các ngoại lệ có thể ném được} - ThrowsExceptionType - danh sách các ngoại lệ được kiểm tra mà phương thức này có thể ném ra. Và để làm ví dụ về tiêu đề phương thức, tôi sẽ đưa ra điều này:
public static void main(String[] args) throws IOException

33. Tạo một hàm tạo mặc định trong đối tượng con cháu nếu nó không được xác định trong đối tượng cơ sở (nhưng một hàm tạo khác được xác định)

Tôi không hiểu hết câu hỏi, nhưng có lẽ nó có nghĩa là, ví dụ, trong phần gốc, chúng ta có một số hàm tạo tùy chỉnh:
public Cat(int age, String name) {
   this.age = age;
   this.name = name;
}
Do đó, trong lớp tổ tiên, chúng ta chắc chắn cần định nghĩa một hàm tạo sẽ điền (gọi) hàm tạo gốc:
public  class Lion extends Cat {

   public Lion(int age, String name) {
       super(age, name);
   }
}
Phân tích các câu hỏi và câu trả lời từ các cuộc phỏng vấn dành cho nhà phát triển Java.  Phần 4 - 4

34. Từ khóa this được sử dụng khi nào?

Trong Java, điều này có hai ý nghĩa khác nhau. 1. Để tham chiếu đến đối tượng hiện tại, như this.age = 9 . Nghĩa là, this đề cập đến đối tượng mà nó được gọi và mã sử dụng this đề cập đến . Chức năng chính là tăng khả năng đọc mã và tránh sự mơ hồ. Ví dụ: nếu tên của trường lớp bên trong và đối số phương thức giống nhau:
public void setName(String name) {
   this.name = name;
}
Nghĩa là, this.name là một trường có tên đối tượng là một đối số của phương thức, tham chiếu this không thể được sử dụng trong các phương thức tĩnh. 2. cái này có thể được sử dụng trong một hàm tạo dưới dạng lệnh gọi phương thức, như this(value) . Trong trường hợp này, nó sẽ là một cuộc gọi đến một hàm tạo khác của cùng một lớp. Nói tóm lại, bạn có thể gọi hai hàm tạo cùng một lúc khi tạo một đối tượng:
public Cat(int age, String name) {
   this(name);
   this.age = age;
}

public Cat(String name) {
   this.name = name;
}
Khi một đối tượng Cat được tạo và hàm tạo đầu tiên được gọi, cả hai trường của đối tượng sẽ được gọi và khởi tạo thành công. Có một vài sắc thái:
  1. this() chỉ hoạt động trong hàm tạo.
  2. Tham chiếu đến hàm tạo khác phải nằm ở dòng đầu tiên của khối hàm tạo (nội dung). Do đó, không thể gọi nhiều hơn một hàm tạo (khác) của một lớp nhất định trong một hàm tạo.
Phân tích các câu hỏi và câu trả lời từ các cuộc phỏng vấn dành cho nhà phát triển Java.  Phần 4 - 5Nhiều ví dụ hơn có trong bài viết này .

35. Công cụ khởi tạo là gì?

Theo như tôi hiểu, trong câu hỏi này, chúng ta đang nói về các khối khởi tạo thống kê và thông thường. Đầu tiên, hãy nhớ khởi tạo là gì. Khởi tạo là tạo, kích hoạt, chuẩn bị làm việc, xác định các tham số. Đưa một chương trình hoặc thành phần vào trạng thái sẵn sàng để sử dụng. Như bạn nhớ, trong quá trình tạo đối tượng, một biến lớp có thể được khởi tạo trực tiếp khi khai báo:
class Cat {
   private int age = 9;
   private  String name = "Tom";
Hoặc đặt nó bên ngoài thông qua một hàm tạo:
class Cat {
   private int age;
   private  String name;

   public Cat(int age, String name) {
       this.age = age;
       this.name = name;
   }
Nhưng có một cách khác: đặt một biến đối tượng bên trong thông qua một khối khởi tạo, trông giống như dấu ngoặc nhọn { } bên trong lớp, không có tên (như phương thức hoặc hàm tạo):
class Cat {
   private int age;
   private  String name;

   {
       age = 10;
       name = "Tom";
   }
Nghĩa là, khối khởi tạo là một đoạn mã được tải khi một đối tượng được tạo. Thông thường, các khối như vậy được sử dụng để thực hiện một số phép tính phức tạp cần thiết khi tải một lớp. Kết quả của những phép tính này có thể được chỉ định làm giá trị cho các biến. Ngoài ra, ngoài các khối khởi tạo thông thường, còn có các khối tĩnh trông giống nhau nhưng có từ khóa static trước dấu ngoặc nhọn :
class Cat {
   private static int age;
   private static String name;

   static{
       age = 10;
       name = "Tom";
   }
Khối này hoàn toàn giống với khối trước. Nhưng nếu cái thông thường được kích hoạt khi mỗi đối tượng được khởi tạo thì cái tĩnh sẽ chỉ kích hoạt một lần khi lớp được tải. Trong một khối như vậy, theo quy luật, một số phép tính phức tạp cũng được thực hiện cho lần khởi tạo tiếp theo của các biến lớp tĩnh. Các hạn chế tương tự áp dụng cho khối tĩnh cũng như đối với các phương thức tĩnh: nó không thể sử dụng dữ liệu không tĩnh, cũng như tham chiếu đến đối tượng hiện tại - this . Phân tích các câu hỏi và câu trả lời từ các cuộc phỏng vấn dành cho nhà phát triển Java.  Phần 4 - 6Tiếp theo, chúng ta có thể xem thứ tự khởi tạo của lớp (cùng với lớp trước của nó) để hiểu rõ hơn về thời điểm các khối khởi tạo được kích hoạt.

36. Để kế thừa một lớp public lớp Child kế thừa lớp Parent, viết thứ tự khởi tạo của đối tượng

Khi lớp Child được nạp thì thứ tự khởi tạo sẽ như sau:
  1. Các trường tĩnh của lớp Parent .
  2. Khối khởi tạo tĩnh cho lớp Parent .
  3. Các trường tĩnh của lớp Child .
  4. Khối khởi tạo tĩnh cho lớp Con .
  5. Các trường không tĩnh của lớp Parent .
  6. Không phải là khối khởi tạo tĩnh cho lớp Parent .
  7. Trình xây dựng cho lớp cha .
  8. Các trường không tĩnh của lớp Trẻ em .
  9. Không phải là khối khởi tạo tĩnh cho lớp Trẻ em .
  10. Trình xây dựng của lớp Con .
Phân tích các câu hỏi và câu trả lời từ các cuộc phỏng vấn dành cho nhà phát triển Java.  Phần 4 - 7Đây là một bài viết ngắn giải thích thứ tự khởi tạo trong thực tế.

37. Bạn biết mối quan hệ nào giữa các lớp (đối tượng)?

Có hai loại mối quan hệ giữa các lớp trong Java:
  • Mối quan hệ IS-A
Nguyên tắc IS-A trong OOP dựa trên sự kế thừa lớp hoặc triển khai giao diện. Ví dụ: nếu lớp Lion kế thừa từ Cat , chúng ta nói rằng LionCat :
Lion IS-A Cat
(nhưng không phải con mèo nào cũng là sư tử ) Tình hình hoàn toàn giống với các giao diện. Nếu lớp Lion triển khai giao diện WildAnimal thì chúng cũng có mối quan hệ:
Lion IS-A WildAnimal
  • Mối quan hệ HAS-A
Kiểu quan hệ này dựa trên việc sử dụng các lớp của các lớp khác, còn được gọi là “liên kết”. Một liên kết là một lớp tham chiếu đến một lớp khác (hoặc thậm chí là tham chiếu lẫn nhau). Ví dụ: lớp Xe có thể tham chiếu đến lớp Hành khách và đây sẽ là mối quan hệ:
Car HAS-A Passenger
Và ngược lại: nếu Passenger có tham chiếu đến Car thì đây sẽ là mối quan hệ:
Passenger HAS-A Car

38. Bạn biết những mối liên kết nào giữa các đồ vật?

Tập hợp và thành phần không gì khác hơn là những trường hợp đặc biệt của sự liên kết. Tập hợp là một mối quan hệ trong đó một đối tượng là một phần của đối tượng khác. Ví dụ, một hành khách có thể ở trong ô tô. Ngoài ra, có thể có một số hành khách hoặc không có (nếu chúng ta đang nói về một chiếc Tesla, thì không cần phải có người lái xe). Ví dụ:
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();
   }
}
Nghĩa là, chúng tôi không quan tâm đến số lượng hành khách (hoặc có hay không): chức năng của lớp Ô tô không phụ thuộc vào điều này. Tập hợp cũng ngụ ý rằng khi một đối tượng được sử dụng bởi một đối tượng khác thì đối tượng đầu tiên có thể được sử dụng trong các đối tượng khác. Ví dụ, cùng một học sinh có thể là thành viên của cả câu lạc bộ đan lát và nhóm nhạc rock, đồng thời tham gia vào một nhóm người học tiếng Anh. Như bạn hiểu, tập hợp là mối quan hệ liên kết lỏng lẻo hơn giữa các lớp. Phân tích các câu hỏi và câu trả lời từ các cuộc phỏng vấn dành cho nhà phát triển Java.  Phần 4 - 8Thành phần là một mối quan hệ thậm chí còn cứng nhắc hơn khi một đối tượng không chỉ là một phần của đối tượng khác mà công việc của đối tượng kia phụ thuộc rất nhiều vào đối tượng đầu tiên. Ví dụ như động cơ ô tô. Mặc dù động cơ có thể tồn tại mà không có ô tô, nhưng ở bên ngoài ô tô thì nó cũng vô dụng. Chà, ô tô không thể hoạt động nếu không có động cơ:
public class Car {
   private Engine engine;

   public Car(Engine engine) {
       this.engine = engine;
   }

   void startMoving() {
       engine.start();
           ...
   }
Thành phần cũng ngụ ý rằng khi một đối tượng được một đối tượng khác sử dụng thì đối tượng đầu tiên không thể thuộc về ai khác. Nếu chúng ta quay lại ví dụ của mình, một động cơ chỉ có thể thuộc về một ô tô chứ không thể thuộc về hai hoặc nhiều ô tô cùng một lúc. Có lẽ hôm nay chúng ta sẽ dừng ở đây.Phân tích các câu hỏi và câu trả lời từ các cuộc phỏng vấn dành cho nhà phát triển Java.  Phần 4 - 9
Các tài liệu khác trong loạt bài:
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION