Phỏng vấn Java: OOP, Collections, JVM và những khái niệm Spring cơ bản

  • author-image

    Nguyễn Đình Cường

  • blog-tag
  • blog-comment 0 comment
  • created-date 09 Nov, 2026
blog-thumbnail

Java vẫn là ngôn ngữ nền tảng của nhiều hệ thống doanh nghiệp, ngân hàng và ứng dụng Android. Phỏng vấn Java thường chia thành ba mảng: lập trình hướng đối tượng, Collections và JVM, rồi đến framework như Spring. Bài này tóm lược những câu hỏi được hỏi nhiều nhất.

Bốn tính chất của OOP trong Java

  • Đóng gói: giấu dữ liệu bằng private, truy cập qua getter, setter có kiểm tra.
  • Kế thừa: lớp con dùng lại lớp cha qua extends; Java chỉ cho kế thừa đơn lớp.
  • Đa hình: cùng một lời gọi, đối tượng khác nhau xử lý khác nhau (ghi đè phương thức).
  • Trừu tượng: thể hiện qua lớp trừu tượng và interface.

Interface và abstract class khác nhau thế nào?

Một lớp có thể triển khai nhiều interface nhưng chỉ kế thừa một lớp. Abstract class có thể chứa trạng thái (trường dữ liệu) và constructor, còn interface chủ yếu định nghĩa hợp đồng, từ Java 8 có thể có phương thức mặc định. Dùng interface khi muốn mô tả khả năng, dùng abstract class khi các lớp con thật sự chia sẻ code và trạng thái.

Overload và override

Overload là nhiều phương thức cùng tên khác tham số trong một lớp (quyết định lúc biên dịch). Override là lớp con định nghĩa lại phương thức của lớp cha với cùng chữ ký (quyết định lúc chạy, nên là cơ sở của đa hình).

equals, hashCode và HashMap

HashMap lưu cặp khóa và giá trị dựa trên mã băm. Khi tra cứu, nó tính hashCode() của khóa để tìm ô chứa, sau đó dùng equals() để xác định đúng khóa trong ô đó. Quy tắc: hai đối tượng bằng nhau theo equals phải có cùng hashCode. Nếu bạn chỉ ghi đè một trong hai, HashMap và HashSet sẽ cho kết quả sai.

public class Point {    private final int x, y;    public Point(int x, int y) { this.x = x; this.y = y; }    @Override    public boolean equals(Object o) {        if (this == o) return true;        if (!(o instanceof Point)) return false;        Point p = (Point) o;        return x == p.x && y == p.y;    }    @Override    public int hashCode() {        return java.util.Objects.hash(x, y);    }}

Các collection thường gặp

KiểuĐặc điểm
ArrayListMảng động, truy cập theo chỉ số nhanh
LinkedListChèn xóa đầu cuối nhanh, truy cập ngẫu nhiên chậm
HashSetTập không trùng, không đảm bảo thứ tự
HashMapCặp khóa giá trị, cho phép khóa null
TreeMapSắp xếp theo khóa

JVM, bộ nhớ và thu gom rác

Mã Java được biên dịch thành bytecode và chạy trên JVM, nhờ vậy "viết một lần, chạy mọi nơi". Bộ nhớ gồm heap (chứa đối tượng, được garbage collector quản lý) và stack (chứa biến cục bộ, mỗi luồng một stack). Bộ thu gom rác tự giải phóng những đối tượng không còn được tham chiếu, nhưng rò rỉ bộ nhớ vẫn có thể xảy ra nếu bạn giữ tham chiếu vô ích, chẳng hạn trong cache tĩnh không giới hạn.

String, StringBuilder, StringBuffer

String bất biến, nên nối chuỗi nhiều lần trong vòng lặp tạo nhiều đối tượng. StringBuilder có thể thay đổi, nhanh hơn, không an toàn luồng. StringBuffer an toàn luồng nhưng chậm hơn.

Xử lý ngoại lệ

Checked exception phải được bắt hoặc khai báo (ví dụ IOException), unchecked exception (kế thừa RuntimeException) thì không bắt buộc. Dùng try-with-resources để tự đóng tài nguyên. Tránh bắt Exception chung chung rồi bỏ qua im lặng.

Spring Boot cơ bản

  • Dependency Injection: thay vì tự tạo phụ thuộc bằng new, container Spring tạo và tiêm chúng vào, giúp giảm ràng buộc và dễ kiểm thử.
  • Bean: đối tượng do Spring quản lý vòng đời.
  • Annotation hay gặp: @RestController, @Service, @Repository, @Autowired, @GetMapping.
  • Spring Data JPA: giảm code truy cập cơ sở dữ liệu nhờ repository interface.

Câu hỏi về lập trình đa luồng

Ứng viên có kinh nghiệm thường được hỏi về luồng. Bạn nên nắm hai cách tạo luồng (kế thừa Thread hoặc triển khai Runnable), hiểu vì sao nên dùng ExecutorService thay vì tự tạo luồng thủ công, và biết từ khóa synchronized dùng để bảo vệ vùng code truy cập dữ liệu chung. Hãy giải thích được race condition bằng ví dụ hai luồng cùng tăng một biến đếm và kết quả bị sai, cũng như cách khắc phục bằng khóa hoặc lớp nguyên tử như AtomicInteger.

Một vài tính năng Java hiện đại nên biết

  • Lambda và Stream: xử lý tập hợp theo phong cách khai báo với filter, map, collect.
  • Optional: biểu diễn giá trị có thể vắng mặt, hạn chế NullPointerException.
  • Record: khai báo lớp dữ liệu bất biến gọn gàng trong các phiên bản Java mới.

Kết luận

Hãy luyện cách giải thích bằng ví dụ nhỏ và liên hệ với dự án bạn từng làm. Với Java, hiểu sâu vài khái niệm cốt lõi như equals và hashCode, collection, JVM và dependency injection thường quan trọng hơn việc thuộc cả thư viện.

Nếu cần một lộ trình học Java có thực hành, bạn có thể xem các khóa học tại codebem.com.

author_photo
Nguyễn Đình Cường

0 comment