CodeGym /Blog Java /Ngẫu nhiên /Khám phá các câu hỏi và câu trả lời từ cuộc phỏng vấn xin...
John Squirrels
Mức độ
San Francisco

Khám phá các câu hỏi và câu trả lời từ cuộc phỏng vấn xin việc cho vị trí nhà phát triển Java. Phần 5

Xuất bản trong nhóm
Xin chào! Các nhà phát triển Java hiện đang có nhu cầu lớn. Tất nhiên, tôi không thể cung cấp cho bạn cơ hội việc làm, nhưng tôi sẽ cố gắng giúp bạn có được một số kiến ​​thức mới và lấp đầy một số lỗ hổng. Vì vậy, hãy tiếp tục xem xét các câu hỏi phỏng vấn nhà phát triển Java. Bạn có thể tìm thấy liên kết đến các phần trước của bài đánh giá ở cuối bài viết. Khám phá các câu hỏi và câu trả lời từ cuộc phỏng vấn xin việc cho vị trí nhà phát triển Java.  Phần 5 - 1

39. Công cụ sửa đổi truy cập trong Java là gì? Hãy gọi tên của chúng. Chúng nó được dùng cho cái gì?

Trước đây tôi đã đề cập đến các công cụ sửa đổi quyền truy cập trong một câu hỏi về các thành phần của Java được sử dụng để đạt được tính năng đóng gói. Nhưng tôi vẫn sẽ nhắc nhở bạn. Công cụ sửa đổi quyền truy cập trong Java là các từ khóa mô tả mức độ truy cập được cấp cho một thành phần Java cụ thể. Các công cụ sửa đổi truy cập sau đây tồn tại:
  • công khai - một phần tử được đánh dấu bằng công cụ sửa đổi này là công khai. Nói cách khác, các trường và phương thức cũng như các lớp được khai báo bằng công cụ sửa đổi công khai sẽ được hiển thị cho các lớp khác cả trong gói của chính chúng và trong các gói bên ngoài;
  • được bảo vệ - một phần tử được đánh dấu bằng công cụ sửa đổi này có thể truy cập được từ bất kỳ đâu trong lớp của chính nó trong gói hiện tại hoặc các lớp dẫn xuất, ngay cả khi chúng nằm trong các gói khác;
  • mặc định (hoặc hoàn toàn không có công cụ sửa đổi) áp dụng ngầm khi không có công cụ sửa đổi truy cập nào được chỉ định. Nó tương tự như cái trước, ngoại trừ việc nó hiển thị trong các lớp dẫn xuất được tìm thấy trong các gói khác;
  • riêng tư - đây là điều riêng tư nhất trong tất cả các sửa đổi. Nó chỉ cho phép truy cập vào một phần tử trong lớp hiện tại.

40. Kể tên các đặc điểm chính của phương thức tĩnh và không tĩnh

Sự khác biệt chính là các phương thức tĩnh thuộc về một lớp. Trên thực tế, bạn không cần tạo một thể hiện của lớp này — các phương thức tĩnh có thể được gọi chỉ từ kiểu lớp đó. Ví dụ: giả sử chúng ta có một phương thức tĩnh để vuốt ve một con mèo:
public class CatService {
   public static void petTheCat(Cat cat) {
       System.out.println("Pet the cat: " + cat.getName());
   }
Chúng ta không cần một phiên bản của lớp CatService để gọi nó:
Cat cat = new Cat(7, "Bobby");
CatService.petTheCat(cat);
Ngược lại, các phương thức thông thường bị ràng buộc (thuộc về) một đối tượng. Để gọi chúng, bạn phải có một thể hiện (đối tượng) mà phương thức sẽ được gọi trên đó. Ví dụ: giả sử con mèo của chúng ta có một phương thức không tĩnh meow() :
class Cat {
   public void meow() {
       System.out.println("Meow! Meow! Meow!");
   }
Để gọi phương thức này, chúng ta cần một instance cụ thể của một con mèo:
Cat cat = new Cat(7, "Bobby");
cat.meow();

41. Những hạn chế chính áp dụng cho các phương pháp tĩnh và không tĩnh là gì?

Như tôi đã nói trước đó, hạn chế chính của một phương thức thông thường (không tĩnh) là phải luôn có một phiên bản nào đó mà phương thức đó được gọi. Nhưng một phương thức tĩnh không yêu cầu điều này. Ngoài ra, một phương thức tĩnh không thể sử dụng tham chiếu this cho các phần tử của một đối tượng vì hiện tại một đối tượng hiện tại đã tồn tại cho phương thức đó.

42. Từ khóa static có nghĩa là gì? Phương thức tĩnh có thể bị ghi đè hoặc quá tải không?

Một phần tử được đánh dấu bằng từ khóa tĩnh không thuộc về một thể hiện của một lớp mà thuộc về chính lớp đó. Nó được tải khi lớp đó được tải. Các phần tử tĩnh giống nhau cho toàn bộ chương trình, trong khi các phần tử không tĩnh chỉ giống nhau cho một đối tượng cụ thể. Các phần tử sau có thể ở dạng tĩnh:
  • các trường của một lớp;
  • khối khởi tạo của một lớp;
  • một phương thức của một lớp;
  • các lớp lồng nhau của một lớp (tất nhiên, đây cũng là một tautology).
Một phương thức tĩnh không thể bị ghi đè: nó thuộc về lớp và không được kế thừa, nhưng đồng thời, nó có thể bị quá tải.

43. Một phương thức có thể tĩnh và trừu tượng cùng một lúc không?

Tôi đã trả lời điều này trong bài viết trước: một phương thức không thể trừu tượng và tĩnh cùng một lúc. Nếu một phương thức là trừu tượng, điều đó có nghĩa là nó phải được ghi đè trong lớp con. Nhưng một phương thức tĩnh thuộc về lớp và nó không thể bị ghi đè. Điều này tạo ra sự mâu thuẫn mà trình biên dịch sẽ nhận thấy và khó chịu. Nếu thấy mình trong tình huống này, bạn nên suy nghĩ nghiêm túc về tính đúng đắn của kiến ​​trúc ứng dụng của mình (gợi ý: rõ ràng có điều gì đó không ổn với nó). Khám phá các câu hỏi và câu trả lời từ cuộc phỏng vấn xin việc cho vị trí nhà phát triển Java.  Phần 5 - 2

44. Các phương thức tĩnh có thể được sử dụng ở giữa các phương thức không tĩnh không? Và ngược lại? Tại sao?

Chúng ta có thể sử dụng các phương thức tĩnh trong các phương thức không tĩnh. Không có gì ngăn cản điều đó. Điều đó nói lên rằng, điều ngược lại là không thể: một phương thức tĩnh không thể sử dụng một phương thức không tĩnh mà không tham chiếu đến một thể hiện cụ thể của lớp. Hãy nhớ rằng, các thành viên tĩnh của một lớp không có quyền truy cập vào tham chiếu this : bạn có thể có bao nhiêu đối tượng cụ thể của lớp tùy thích và mỗi đối tượng trong số chúng sẽ chứa một tham chiếu this , đây là một tham chiếu tự tham chiếu. Vậy làm thế nào để xác định tham chiếu này sẽ sử dụng? Ờ, bạn không. Đó là lý do tại sao các phần tử tĩnh không thể tham chiếu đến các phần tử không tĩnh mà không tham chiếu đến một đối tượng cụ thể. Về cơ bản, một phương thức tĩnh chỉ có thể sử dụng một phương thức không tĩnh nếu nó có tham chiếu đến một đối tượng cụ thể. Ví dụ: một đối số xuất hiện dưới dạng đối số phương thức:
public static void petTheCat(Cat cat) {
   System.out.println("Pet the cat: " + cat.getName());
}
Ở đây chúng ta thấy rằng trong phương thức tĩnh petTheCat() gọi getName , một phương thức không tĩnh thông thường của đối tượng Cat .

45. Giao diện là gì? Có thể có một giao diện cuối cùng?

Chúng ta hãy nhớ lại rằng Java không có tính đa kế thừa. Giao diện là một cái gì đó thay thế cho nó. Một giao diện giống như một lớp rất đơn giản. Chúng xác định chức năng nhưng không xác định cách triển khai cụ thể. Nhiệm vụ đó được giao cho các lớp thực hiện các giao diện này. Ví dụ về một giao diện:
public interface Animal {
    void speak();
}
Ví dụ về triển khai giao diện của một lớp
class Cat implements Animal {

   @Override
   public void speak() {
       System.out.println("Meow! Meow! Meow!");
   }
}
Đây là điều quan trọng cần biết về cách sử dụng giao diện:
  1. Các phương thức giao diện chỉ được chứa một tiêu đề. Chúng không được có phần thân phương thức cụ thể, tức là chúng phải trừu tượng (mặc dù chúng không sử dụng từ khóa abstract ). Có các trường hợp ngoại lệ: phương thức tĩnh và phương thức mặc định, yêu cầu phần thân phương thức.

  2. Một lớp có thể triển khai nhiều giao diện (như tôi đã nói, giao diện là một giải pháp thay thế cho đa kế thừa). Các tên giao diện được phân tách bằng dấu phẩy trong tiêu đề phương thức: class Lion triển khai Animal, Wild .

  3. Giao diện được tạo bằng từ khóa giao diện .

  4. Khi một lớp triển khai một giao diện, chúng ta sử dụng từ khóa cụ thể .

  5. Một lớp triển khai một giao diện nhất định phải triển khai tất cả các phương thức trừu tượng của nó hoặc phải khai báo chính nó là trừu tượng.

  6. Mục đích chính của việc sử dụng giao diện là thực hiện tính đa hình (để cung cấp cho một đối tượng khả năng có nhiều dạng).

  7. Theo quy định, các công cụ sửa đổi quyền truy cập cho các phương thức không được chỉ định trong giao diện: chúng được công khai theo mặc định và bạn không thể chỉ định các công cụ sửa đổi khác ngoài public . Bắt đầu với Java 9, bạn có thể sử dụng các công cụ sửa đổi riêng tư trên các phương thức.

  8. Theo mặc định, các biến giao diện là static cuối cùng . Nói cách khác, chúng là hằng số - chúng phải luôn được khởi tạo trực tiếp trong giao diện.

  9. Bạn không thể tạo một phiên bản của giao diện.

Tất nhiên, câu trả lời cho câu hỏi liệu giao diện có thể là cuối cùng hay không là không. Thật vậy, mục đích chung của việc có các giao diện là để chúng được triển khai. Và như tất cả chúng ta đều nhớ rất rõ, công cụ sửa đổi cuối cùng ở cấp độ lớp làm cho một lớp không thể kế thừa được và trong trường hợp là một giao diện - không thể triển khai được. Tại sao chúng ta cần một giao diện mà chúng ta không thể triển khai và sử dụng? Bạn nói đúng - chúng tôi sẽ không làm vậy! Và trình biên dịch đồng ý. :) Khám phá các câu hỏi và câu trả lời từ cuộc phỏng vấn xin việc cho vị trí nhà phát triển Java.  Phần 5 - 3Trên thực tế, với việc giới thiệu các phương thức giao diện tĩnh kể từ Java 8, có thể có lý, nhưng điều này không thay đổi thực tế rằng một giao diện không thể là cuối cùng. Tôi chỉ nói về giao diện một cách rất hời hợt vì đây là một chủ đề rộng. Để biết thêm về điều này, hãy xem các bài viết về giao diện trong Javasự khác biệt giữa các lớp trừu tượng và giao diện .

46. ​​Trường tĩnh có thể được khởi tạo ở đâu?

Các trường tĩnh có thể được khởi tạo:
  • ngay khi khai báo, sử dụng dấu bằng ( = );
  • trong khối khởi tạo tĩnh;
  • trong khối khởi tạo không tĩnh (nhưng bạn cần hiểu rằng mỗi khi một đối tượng được tạo, trường tĩnh sẽ bị ghi đè khi khối khởi tạo này được thực thi;
  • trong một hàm tạo của lớp. Mỗi lần hàm tạo được gọi (nghĩa là mỗi lần một đối tượng được tạo bằng hàm tạo này), trường sẽ bị ghi đè;
  • trong các phương pháp tĩnh;
  • trong các phương pháp không tĩnh;
  • trong các lớp tĩnh và không tĩnh, cục bộ và ẩn danh lồng nhau.

47. Lớp ẩn danh là gì?

Các lớp ẩn danh là các lớp không có kiểu riêng. Tôi đang nói về cái gì vậy? Khi chúng ta nói về giao diện, tôi đã đề cập rằng bạn không thể tạo một thể hiện của một đối tượng: bạn chỉ có thể tạo một thể hiện của một lớp thực hiện một giao diện. Điều gì sẽ xảy ra nếu bạn không muốn một số lớp triển khai giao diện nhưng lại cần một đối tượng triển khai giao diện đó? Và đây có thể là mục đích sử dụng duy nhất của đối tượng. Và bạn không cần phải tạo một lớp triển khai chính thức. Bạn sẽ làm điều này như thế nào? Đúng rồi! Bằng cách sử dụng một lớp ẩn danh! Khám phá các câu hỏi và câu trả lời từ cuộc phỏng vấn xin việc cho vị trí nhà phát triển Java.  Phần 5 - 4Giả sử chúng ta có một số giao diện Động vật :
public final interface Animal {
   public void speak();
}
Nếu chúng ta muốn sử dụng một lớp ẩn danh để khởi tạo một giao diện nhất định:
Animal cat = new Animal() {
   @Override
   public void speak() {
       System.out.println("Meow! Meow! Meow!");
   }
};
Sau đó, bạn có thể sử dụng đối tượng này và phương thức speak() được triển khai của nó một cách an toàn . Nói cách khác, lớp ẩn danh triển khai giao diện và tất cả các phương thức trừu tượng của nó, ngay tại đây và ngay bây giờ. Nếu không, chúng ta sẽ không thể tạo một đối tượng giao diện/lớp trừu tượng vì sẽ có các phương thức chưa được triển khai/trừu tượng. Như tôi đã đề cập, các lớp ẩn danh không chỉ được sử dụng để triển khai các phương thức trừu tượng của giao diện mà còn để triển khai các phương thức trừu tượng của một lớp trừu tượng. Cách tiếp cận này tốt cho các tình huống khi một đối tượng được sử dụng một lần hoặc khi chỉ cần triển khai một phương thức nhất định một lần. Không cần phải tạo một lớp riêng biệt sẽ triển khai lớp/giao diện trừu tượng cần thiết. Nhưng tôi cũng lưu ý rằng các lớp ẩn danh hiếm khi được sử dụng trong công việc. Theo quy định, các lớp bình thường vẫn được ưu tiên. Bạn có thể đọc thêm về các lớp ẩn danh ở đây trong bài viết này .

48. Lớp nguyên thủy là gì?

Tôi nghĩ đây là một câu hỏi gây hiểu lầm, có thể là một câu hỏi đánh lừa, vì Java không có cái gọi là các lớp nguyên thủy. Chỉ có khái niệm về các kiểu nguyên thủy mà chúng ta đã xem xét trước đây. Chúng tôi nhớ lại rằng Java có 8 loại nguyên thủy: byte , short , int , long , float , double , char , boolean .

49. Lớp bao bọc là gì?

Vấn đề chính khi sử dụng các kiểu nguyên thủy trong Java là chúng không phải là các lớp và Java là ngôn ngữ OOP. Nghĩa là, các chương trình được viết bằng ngôn ngữ này tương tác với nhau giữa các đối tượng. Nhưng nguyên thủy không phải là đối tượng. Họ không có các phương thức, thậm chí cả các phương thức tiêu chuẩn của lớp Object . Nhưng nếu chúng ta cần sử dụng một giá trị nguyên thủy làm khóa trong Map thì sao ? Sau đó chúng ta cần gọi phương thức hashCode() của nó . Bạn cũng có thể gọi phương thức Equals() của nó ở đó. Vậy thì sao? Có rất nhiều khoảnh khắc mà bạn cần một lớp học chứ không phải một lớp học nguyên thủy. Điều này làm cho các phần tử nguyên thủy không thể sử dụng được và không mong muốn trong một chương trình vì chúng vi phạm chính ý tưởng về OOP. Nhưng tình hình không tệ như người ta tưởng. Xét cho cùng, Java có khái niệm về các trình bao bọc nguyên thủy. Trong Java, mọi kiểu nguyên thủy đều có một lớp song sinh - một lớp bao bọc.
  • byte -> Byte.class
  • ngắn -> Short.class
  • int -> Integer.class
  • dài -> Long.class
  • float -> Float.class
  • gấp đôi -> Double.class
  • char -> Ký tự.class
  • boolean -> Boolean.class
Những kiểu này đại diện cho những kiểu đơn giản, nhưng trong các lớp chính thức với nhiều phương thức đa dạng và hữu ích. Các khái niệm về autoboxing và unboxing đã được giới thiệu để cho phép các lớp này được sử dụng một cách thuận tiện. Autoboxing là sự chuyển đổi tự động của một kiểu nguyên thủy sang lớp tương tự của nó, nếu cần thiết (ví dụ: chuyển đổi int thành Integer ). Mở hộp là quá trình ngược lại: tự động chuyển đổi lớp trình bao bọc nguyên thủy thành loại nguyên thủy (ví dụ: chuyển đổi Integer thành int ). Nhờ sự ra đời của các lớp trình bao bọc nguyên thủy cũng như các quy trình tự động đóng hộpmở hộp , các kiểu nguyên thủy giờ đây đã trở thành thành viên chính thức của Java dưới dạng ngôn ngữ OOP. Khám phá các câu hỏi và câu trả lời từ cuộc phỏng vấn xin việc cho vị trí nhà phát triển Java.  Phần 5 - 5Để thảo luận sâu hơn về chủ đề này, tôi thực sự khuyên bạn nên đọc bài viết này .

50. Lớp lồng nhau là gì? Nó được sử dụng ở đâu?

Lớp lồng nhau là lớp mà bản thân nó là thành viên của một lớp khác. Có 4 loại lớp lồng nhau này trong Java: 1. Lớp bên trong Loại lớp này được khai báo trực tiếp trong phần thân của một lớp khác. Lớp bên trong là lớp lồng nhau không tĩnh và có thể truy cập bất kỳ trường riêng tư hoặc phương thức cá thể nào của lớp bên ngoài. Ví dụ: hãy tạo một vườn thú có một con vật - ngựa vằn:
public class Zoo {
   class Zebra {
       public void eat(String food) {
           System.out.println("Zebra eats " + food);
       }
   }
}
Không phức tạp, phải không? Chúng ta hãy xem một ví dụ về việc tạo một thể hiện của lớp bên trong:
Zoo.Zebra zebra = new Zoo().new Zebra();
zebra.eat("apple");
Như bạn đã thấy, trước tiên cần phải tạo một đối tượng của lớp kèm theo. Sau đó, bạn sử dụng tham chiếu đối tượng để tạo một thể hiện của lớp bên trong. Tôi cũng muốn chỉ ra rằng một lớp bên trong (lớp lồng không tĩnh) không thể có các phương thức tĩnh hoặc trường tĩnh. Điều này chính xác là do lớp bên trong được liên kết ngầm với một thể hiện của lớp bên ngoài và do đó không thể khai báo bất kỳ phương thức tĩnh nào bên trong chính nó. 2. Các lớp lồng nhau tĩnh Các lớp này tương tự như loại trước, nhưng chúng có bộ sửa đổi truy cập tĩnh trong khai báo lớp. Vì loại lớp này không có quyền truy cập vào các trường không tĩnh của lớp bên ngoài nên nó trông giống một phần tĩnh của lớp bên ngoài hơn là lớp bên trong. Nhưng lớp này có quyền truy cập vào tất cả các thành viên tĩnh của lớp bên ngoài, ngay cả những thành viên riêng tư. Ví dụ về lớp lồng nhau tĩnh:
public class Zoo {
   static class Zebra {
       public void eat(String food) {
           System.out.println("Zebra eats " + food);
       }
   }
}
Nó được tạo ra hơi khác so với cái trước:
Zoo.Zebra zebra = new Zoo.Zebra();
zebra.eat("apple");
Ở đây chúng ta không cần một đối tượng của lớp bên ngoài để tạo một đối tượng của lớp lồng tĩnh. Chúng ta chỉ cần biết tên của lớp lồng nhau để tìm nó trong lớp bên ngoài. 3. Lớp cục bộ Lớp cục bộ là các lớp được khai báo bên trong phần thân của một phương thức. Các đối tượng của một lớp cục bộ chỉ có thể được tạo và sử dụng trong phương thức kèm theo. Ví dụ:
public class Zoo {
   public void feed(String animal, String food) {
       switch(animal) {
           case "zebra":
               class Zebra {
                   public void eat(String food) {
                       System.out.println("Zebra eats " + food);
                   }
               }
               Zebra zebra = new Zebra();
               zebra.eat(food);
               ...
Đây là một ví dụ:
Zoo zoo = new Zoo();
zoo.feed("zebra", "apple");
Nếu bạn không nhìn thấy mã của phương thức Feed() thì bạn thậm chí sẽ không nghi ngờ rằng có một lớp cục bộ tồn tại phải không? Một lớp cục bộ không thể là tĩnh hoặc thoáng qua , nhưng nó có thể được đánh dấu là trừu tượng hoặc cuối cùng (một HOẶC lớp kia, nhưng không phải cả hai, vì việc sử dụng đồng thời hai công cụ sửa đổi này sẽ tạo ra xung đột). 4. Lớp ẩn danh Chúng ta đã nói về lớp ẩn danh ở trên và như bạn sẽ nhớ, chúng có thể được tạo từ hai nguồn - giao diện và lớp. Lý do nên sử dụng chúng Các lớp tĩnh và không tĩnh lồng nhau được sử dụng vì đôi khi tốt hơn là nên nhúng các lớp nhỏ vào các lớp tổng quát hơn và giữ chúng lại với nhau để chúng có độ gắn kết cao hơn và có mục đích chung. Về cơ bản, các lớp lồng nhau cho phép bạn tăng khả năng đóng gói mã của mình. Bạn có thể chọn sử dụng một lớp cục bộ nếu lớp đó được sử dụng riêng trong một phương thức duy nhất. Trong trường hợp này, chúng ta có cần trải mã trên ứng dụng không? Không. Điều đó nói lên rằng, tôi sẽ nói thêm rằng theo kinh nghiệm của mình, tôi chưa bao giờ thấy ai sử dụng các lớp địa phương, bởi vì việc chúng có cần thiết hay không còn gây nhiều tranh cãi. Bạn có thể sử dụng các lớp ẩn danh khi chỉ cần triển khai cụ thể một giao diện hoặc một lớp trừu tượng một lần. Trong trường hợp đó, không cần phải tạo một lớp riêng biệt, đầy đủ để triển khai. Thay vào đó, chúng tôi giữ nó đơn giản và triển khai (các) phương thức chúng tôi cần bằng cách sử dụng một lớp ẩn danh, sử dụng đối tượng và sau đó quên nó đi (tất nhiên, trình thu gom rác không quên). Sự hiểu biết của bạn về các lớp lồng nhau sẽ được nâng cao nhờ bài viết tại đây.

51. Một lớp có thể có những công cụ sửa đổi truy cập nào?

Có nhiều loại lớp khác nhau và các công cụ sửa đổi truy cập khác nhau áp dụng cho chúng:
  • một lớp bên ngoài có thể có công cụ sửa đổi truy cập công khai hoặc hoàn toàn không có công cụ sửa đổi (công cụ sửa đổi mặc định);
  • một lớp bên trong (lớp lồng nhau không tĩnh) có thể có bất kỳ một trong 4 công cụ sửa đổi truy cập;
  • một lớp tĩnh lồng nhau có thể có bất kỳ một trong các công cụ sửa đổi truy cập ngoại trừ được bảo vệ vì công cụ sửa đổi này ngụ ý tính kế thừa, điều này mâu thuẫn với bất kỳ thành viên tĩnh nào của lớp (các thành viên tĩnh không được kế thừa);
  • một lớp cục bộ chỉ có thể có công cụ sửa đổi mặc định (tức là không có công cụ sửa đổi nào cả);
  • một lớp ẩn danh không có khai báo lớp, vì vậy nó không có công cụ sửa đổi truy cập nào cả.
Đây là nơi chúng ta sẽ kết thúc ngày hôm nay. Hẹn sớm gặp lại!Khám phá các câu hỏi và câu trả lời từ cuộc phỏng vấn xin việc cho vị trí nhà phát triển Java.  Phần 5 - 6
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION