Câu hỏi phỏng vấn Java kèm cách trả lời, theo từng cấp độ
Trả lời nhanh: câu hỏi phỏng vấn Java hay gặp nhất xoay quanh equals/hashCode, Collections, exception, generics, Optional/Stream, đa luồng (synchronized, volatile, ExecutorService) và cách tìm nguyên nhân khi service chậm. Cách trả lời mạnh: nêu hợp đồng (contract) của API trước, rồi lựa chọn triển khai, rồi cái giá phải trả. Bài này chia theo fresher, junior/middle và senior; tài liệu gốc nằm ở Dev.java và Java API docs của Oracle.
Phỏng vấn Java thường diễn ra thế nào
Nhà tuyển dụng hiếm khi chỉ hỏi định nghĩa. Một câu cơ bản thường được kéo thành câu thiết kế: chọn collection cho một bài toán, làm sao để class dùng được làm key của map, hay service tắt các executor thế nào khi dừng. Cấp độ gọi tên thường gặp trong tin tuyển dụng tiếng Việt là fresher, junior, middle, senior, nhưng ranh giới khác nhau theo từng công ty, vì vậy hãy đọc kỹ JD và hỏi nhà tuyển dụng về vòng thi (live coding, bài test online, phỏng vấn kỹ thuật). Bài này không đưa số liệu lương hay tỷ lệ đậu vì chưa có nguồn chính thống để kiểm chứng.
Câu hỏi Java cho fresher/junior
1. == khác equals thế nào?
Với tham chiếu đối tượng, == kiểm tra hai biến có trỏ cùng một đối tượng không. equals cho phép định nghĩa bằng nhau về mặt giá trị. Class giá trị bất biến thường override equals để hai instance có cùng các trường được coi là bằng nhau. Người phỏng vấn hay hỏi tiếp: “so sánh hai String bằng gì?” (dùng equals).
2. Vì sao phải override hashCode cùng equals?
Tài liệu Object.hashCode() của Java SE 21 nêu: nếu hai đối tượng bằng nhau theo equals thì hashCode của chúng phải cho cùng một số nguyên. Ngược lại, hai đối tượng khác nhau không bắt buộc có hash khác nhau, nhưng hash phân tán tốt giúp bảng băm nhanh hơn. Nếu vi phạm, HashMap/HashSet có thể không tìm thấy giá trị vừa thêm vào. Thêm điều kiện: equals phải phản xạ, đối xứng, bắc cầu và nhất quán.
3. ArrayList và LinkedList khác nhau thế nào?
ArrayList lưu phần tử trong mảng co giãn nên truy cập theo chỉ số nhanh. LinkedList nối các nút, chèn/xóa quanh một nút đã có thì rẻ, nhưng duyệt và cấp phát thường tốn hơn nên ArrayList thường là mặc định hợp lý. Hãy nói “tôi chọn theo mẫu truy cập thực tế” thay vì học thuộc Big-O.
4. Interface dùng để làm gì?
Interface định nghĩa hợp đồng mà nhiều cài đặt có thể thỏa mãn, để nơi gọi phụ thuộc vào hành vi thay vì class cụ thể, dễ thay thế và dễ test. Không nên tạo interface cho mọi class nếu không có ranh giới thật hoặc cài đặt thay thế.
5. Checked và unchecked exception khác nhau thế nào?
Checked exception phải khai báo hoặc xử lý ở nơi gọi; unchecked kế thừa RuntimeException thì không bắt buộc. Câu hỏi thiết kế quan trọng là nơi gọi có thể khắc phục được không. Đừng dùng exception cho luồng điều khiển thông thường.
Câu hỏi Java cho middle
6. Generics mang lại gì?
Generics cho API khai báo kiểu giá trị nhận vào/trả ra, bắt nhiều lỗi ngay lúc biên dịch. Do type erasure, đừng giả định mọi kiểu generic còn tồn tại lúc chạy. Biết phân biệt ? extends T (nguồn cung cấp) và ? super T (nơi tiêu thụ).
7. Khi nào dùng Optional?
Javadoc của Optional (Java SE 21) nói nó chủ yếu dành cho kiểu trả về của phương thức khi cần biểu diễn “không có kết quả” và dùng null dễ gây lỗi; biến kiểu Optional không bao giờ được là null. Tài liệu cũng khuyên không so sánh với Optional.empty() bằng ==, hãy dùng isEmpty()/isPresent(). Quy ước phổ biến là tránh dùng nó cho trường hoặc tham số theo mặc định; đây là khuyến nghị thiết kế, không phải quy tắc ngôn ngữ.
8. Stream khác collection thế nào?
Collection lưu dữ liệu, Stream mô tả một pipeline xử lý dữ liệu; thường chỉ dùng được một lần và có thể lazy. Dùng khi pipeline rõ hơn vòng lặp, đừng nhồi một chuỗi dày che mất nhánh rẽ hay xử lý lỗi.
9. Vì sao String bất biến?
Bất biến giúp chia sẻ an toàn, phù hợp làm khóa băm và dễ suy luận trong đa luồng. Điểm thực tế: mỗi thao tác tạo giá trị mới, nên nối chuỗi lặp trong vòng lặp nên cân nhắc StringBuilder.
10. Dependency injection là gì?
Cung cấp các thành phần phụ thuộc từ bên ngoài thay vì tự tạo bên trong. Constructor injection làm lộ rõ phụ thuộc bắt buộc và dễ dựng test. Framework (như Spring) có thể tự động nối, nhưng nguyên lý tồn tại độc lập với framework.
11. HashMap khác ConcurrentHashMap thế nào?
Theo Javadoc, ConcurrentHashMap thread-safe, thao tác đọc như get nói chung không chặn nên có thể chồng lên put/remove, và khác HashMap, nó không cho phép key hoặc value là null. Nhưng thao tác ghép kiểu “kiểm tra rồi ghi” vẫn cần hàm nguyên tử như computeIfAbsent hay merge.
Câu hỏi Java cho senior
12. synchronized bảo vệ cái gì?
Nó điều phối truy cập qua monitor và đảm bảo tính hiển thị (visibility) quanh vùng đồng bộ; không phải thuốc tăng tốc. Hãy xác định bất biến dùng chung trước, rồi chọn khóa, thiết kế bất biến, kiểu atomic hay collection đồng thời.
13. volatile dùng để làm gì?
Đảm bảo visibility và thứ tự cho việc đọc/ghi một biến, nhưng không làm các thao tác ghép như count++ trở thành nguyên tử. Hợp với cờ dừng hoặc tham chiếu được công bố khi hợp đồng giới hạn này là đủ.
14. Dùng ExecutorService an toàn thế nào?
Chọn pool có giới hạn và quan sát được, xử lý lỗi task, đặt timeout khi cần, và tắt khi ứng dụng dừng. Javadoc có mẫu hai pha: shutdown() để từ chối task mới, awaitTermination để chờ, rồi shutdownNow() nếu hết thời gian. Lưu ý shutdownNow() chỉ cố gắng hết sức (thường dùng interrupt), nên task không phản hồi interrupt có thể không bao giờ kết thúc.
pool.shutdown();
try {
if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
pool.shutdownNow();
}
} catch (InterruptedException e) {
pool.shutdownNow();
Thread.currentThread().interrupt();
}15. Thế nào là một đối tượng bất biến?
Trạng thái quan sát được không đổi sau khi khởi tạo: trường private (và final nếu được), sao chép phòng vệ các đầu vào có thể thay đổi, không để lộ nội bộ có thể sửa. Giảm lỗi chia sẻ trạng thái.
16. Cách điều tra một Java service chạy chậm?
Bắt đầu từ triệu chứng và đo: độ trễ request, tốc độ cấp phát, thời gian chờ database, hàng đợi thread pool, hành vi GC. Lấy profile hoặc thread dump một cách an toàn, đặt giả thuyết, đổi một thứ mỗi lần. Đừng đổ lỗi cho JVM hay GC khi chưa có bằng chứng.
Cách trả lời Java thuyết phục hơn
Theo thứ tự: hợp đồng → lựa chọn → chi phí. Ví dụ: “HashMap cần equals/hashCode ổn định, nên tôi dùng key bất biến và viết test kiểm tra lookup.” Câu này thuyết phục hơn việc kể tên class theo trí nhớ. Khi được hỏi về live coding, hãy nói to ý đồ: chọn collection theo ràng buộc, độ phức tạp, ai sở hữu trạng thái dùng chung. Hỏi nhà tuyển dụng phiên bản Java và thư viện được phép dùng; các hợp đồng cốt lõi bền hơn cú pháp theo phiên bản. Với bài live coding, xem thêm trợ lý AI cho phỏng vấn coding.
Nếu bạn bị đứng hình khi phỏng vấn
Bạn có thể luyện trước bằng cách tự giải thích từng câu trên thành tiếng, mỗi câu hai phút. Interview Copilot là ứng dụng overlay trên máy tính, nghe âm thanh cuộc gọi và hiện gợi ý trả lời theo thời gian thực, có thể giải bài code từ ảnh chụp màn hình. Có gói miễn phí không cần thẻ (5 phút nhận dạng giọng nói trực tiếp và 3 lần giải bài từ ảnh chụp). Trên macOS và Windows, cửa sổ yêu cầu hệ điều hành không đưa nó vào ảnh chụp/chia sẻ màn hình; trên Linux (bản beta) cửa sổ vẫn hiển thị, và kết quả còn phụ thuộc phần mềm chia sẻ màn hình, nên hãy thử bằng chế độ chia sẻ riêng tư. Xem thêm trang về cửa sổ ẩn.
Về quy tắc: mỗi công ty và nền tảng có quy định riêng và có thể thay đổi. Trước buổi phỏng vấn thật, hãy hỏi nhà tuyển dụng xem có được dùng công cụ hỗ trợ không; nếu không được, đừng dùng và chỉ dùng để luyện tập.
Nguồn tham khảo
- Dev.java — Learn: trung tâm hướng dẫn Java do Oracle xuất bản
- Java SE 21 API — Object: hợp đồng equals và hashCode
- Java SE 21 API — Optional
- Java SE 21 API — ConcurrentHashMap
- Java SE 21 API — ExecutorService: shutdown hai pha
Kiểm tra ngày 12/11/2026.
Nguồn tham khảo
- Dev.java — tài liệu chính thức
FAQ
Câu hỏi phỏng vấn Java nào hay gặp nhất?
Thường gặp: equals và hashCode, Collections, generics, exception, Optional, Stream, dependency injection, đa luồng (synchronized, volatile, ExecutorService), tính bất biến, hiệu năng JVM và cách kiểm thử. Fresher thiên về nền tảng OOP và Collections; senior bị hỏi thêm về đồng thời và điều tra hiệu năng.
Giải thích equals và hashCode thế nào cho gọn?
equals định nghĩa bằng nhau về logic; hashCode giúp bảng băm tìm ứng viên. Theo Javadoc, hai đối tượng bằng nhau theo equals phải có cùng hashCode, và các trường dùng trong cả hai không nên đổi khi đối tượng đang là key của map.
Khi nào dùng ArrayList, khi nào LinkedList?
ArrayList thường là mặc định tốt cho truy cập theo chỉ số và duyệt. LinkedList chỉ có ích ở trường hợp hẹp, khi bạn đã giữ nút và liên tục chèn/xóa quanh nó. Hãy nói rằng bạn sẽ đo theo khối lượng công việc thực tế.
volatile và synchronized khác nhau thế nào?
volatile đảm bảo visibility và thứ tự cho một biến nhưng không đảm bảo nguyên tử cho thao tác ghép như count++. synchronized điều phối truy cập qua monitor nên bảo vệ được cả một bất biến dùng chung lớn hơn.
Chuẩn bị phỏng vấn live coding Java thế nào?
Luyện chọn collection theo ràng buộc, viết test nhỏ, giải thích equals và độ phức tạp, nói rõ ai sở hữu trạng thái dùng chung. Hỏi nhà tuyển dụng về phiên bản Java và thư viện được phép dùng trong bài.
Có được dùng AI hỗ trợ trong buổi phỏng vấn thật không?
Tùy quy định của công ty và nền tảng, và quy định có thể thay đổi. Hãy hỏi nhà tuyển dụng trước; nếu không được phép thì không dùng, chỉ dùng AI để luyện tập trước buổi phỏng vấn.