Bài tập trắc nghiệm Java - Cơ bản
Trang này tổng hợp 200 câu hỏi trắc nghiệm Java cơ bản, sắp xếp theo chủ đề từ dễ đến khó. Mỗi câu có 4 đáp án A/B/C/D.
Chọn một đáp án cho mỗi câu - đáp án đúng/sai và phần giải thích sẽ tự động hiện ra ngay sau khi bạn chọn.
Nhóm 1: Biến và kiểu dữ liệu
Phần tiêu đề “Nhóm 1: Biến và kiểu dữ liệu”Câu 1. Trong Java, để khai báo một biến số nguyên x có giá trị 5, ta viết:
Đáp án: B
Java là ngôn ngữ định kiểu tĩnh, phải khai báo kiểu dữ liệu (int) khi tạo biến. var x = 5; cũng hợp lệ (Java 10+) nhưng không phải cách khai báo tường minh tiêu chuẩn được hỏi ở đây.
Câu 2. Kiểu dữ liệu nào dùng để lưu số thực có độ chính xác đơn (32-bit)?
Đáp án: B
float lưu số thực 32-bit (độ chính xác đơn), còn double là 64-bit (độ chính xác kép) và là kiểu mặc định cho số thực trong Java.
Câu 3. Kiểu dữ liệu nào dùng để lưu một ký tự Unicode đơn?
Đáp án: B
char lưu một ký tự Unicode 16-bit, ví dụ char c = 'A'; (dùng nháy đơn). String dùng nháy kép và có thể chứa nhiều ký tự.
Câu 4. Đâu là khai báo biến hợp lệ trong Java?
Đáp án: C
Tên biến có thể bắt đầu bằng dấu gạch dưới _. Không được bắt đầu bằng số (A), không được trùng từ khóa như class (B), và không được chứa khoảng trắng (D).
Câu 5. Giá trị mặc định của một biến boolean là trường (field) của lớp khi chưa gán là gì?
Đáp án: A
Một trường boolean chưa khởi tạo tự động nhận giá trị mặc định false. (Biến cục bộ trong phương thức thì không có giá trị mặc định, phải khởi tạo trước khi dùng.)
Câu 6. Kiểu số nguyên nào có kích thước lớn nhất trong các kiểu nguyên thủy của Java?
Đáp án: D
Thứ tự kích thước: byte (8-bit) < short (16-bit) < int (32-bit) < long (64-bit).
Câu 7. Từ khóa nào (Java 10+) cho phép trình biên dịch tự suy luận kiểu dữ liệu của biến cục bộ?
Đáp án: B
var được thêm từ Java 10, dùng cho biến cục bộ và vẫn là kiểu tĩnh (được suy luận tại thời điểm biên dịch, không phải kiểu động).
Câu 8. Đoạn code sau có biên dịch được không?
int fruit = 5;fruit = "apple";Đáp án: C
Một khi fruit đã khai báo kiểu int, không thể gán giá trị String cho nó - trình biên dịch báo lỗi ngay, không đợi đến lúc chạy.
Câu 9. Tên biến nào không hợp lệ trong Java?
Đáp án: A
Tên biến không được bắt đầu bằng chữ số. $ và _ là những ký tự hợp lệ để bắt đầu tên biến trong Java.
Câu 10. Sự khác biệt giữa 'A' và "A" trong Java là gì?
Đáp án: B
Dấu nháy đơn 'A' tạo ra một giá trị kiểu char (một ký tự), còn dấu nháy kép "A" tạo ra một đối tượng String (chuỗi ký tự, dù chỉ có 1 ký tự).
Nhóm 2: Toán tử số học
Phần tiêu đề “Nhóm 2: Toán tử số học”Câu 11. Đoạn code sau in ra gì?
System.out.println(7 / 2);Đáp án: B
Cả hai toán hạng đều là int, nên phép chia là chia số nguyên, phần thập phân bị cắt bỏ (không làm tròn): 7 / 2 = 3.
Câu 12. Đoạn code sau in ra gì?
System.out.println(7 % 2);Đáp án: A
Toán tử % trả về phần dư của phép chia: 7 % 2 = 1 (vì 7 = 2*3 + 1).
Câu 13. Đoạn code sau in ra gì?
int x = 5;double y = 2.0;System.out.println(x / y);Đáp án: C
Khi một trong hai toán hạng là double, toán hạng còn lại được tự động nâng cấp (promote) lên double, nên kết quả là phép chia số thực: 5 / 2.0 = 2.5.
Câu 14. Đoạn code sau in ra gì?
int i = 5;System.out.println(i++);System.out.println(i);Đáp án: B
i++ (hậu tố/postfix) trả về giá trị hiện tại của i (5) rồi mới tăng lên 6. Dòng in thứ hai thấy i đã là 6.
Câu 15. Đoạn code sau in ra gì?
int i = 5;System.out.println(++i);Đáp án: A
++i (tiền tố/prefix) tăng giá trị của i lên trước rồi mới trả về, nên in ra 6.
Câu 16. Toán tử nào dùng để lấy phần dư của phép chia trong Java?
Đáp án: D
Java dùng % để lấy phần dư (modulo), ví dụ 10 % 3 = 1.
Câu 17. Đoạn code sau in ra giá trị nào của x?
int x = 10;x += 5;x -= 2;System.out.println(x);Đáp án: B
x += 5 tương đương x = x + 5 → x = 15. x -= 2 tương đương x = x - 2 → x = 13.
Câu 18. Biểu thức 3 + 4 * 2 có giá trị bằng bao nhiêu?
Đáp án: C
Toán tử * có độ ưu tiên cao hơn +, nên tính 4 * 2 = 8 trước, rồi 3 + 8 = 11.
Câu 19. Đoạn code sau in ra gì?
int a = 2;int b = 3;System.out.println(a * b % 4);Đáp án: A
* và % có cùng độ ưu tiên, tính từ trái sang phải: a * b = 6, sau đó 6 % 4 = 2.
Câu 20. Đoạn code sau in ra gì?
double x = 5;System.out.println(x % 2);Đáp án: D
Khác với nhiều ngôn ngữ, Java cho phép % hoạt động trên cả số thực (double/float), trả về phần dư dạng thực: 5.0 % 2 = 1.0.
Nhóm 3: Toán tử so sánh và logic
Phần tiêu đề “Nhóm 3: Toán tử so sánh và logic”Câu 21. Đoạn code sau in ra gì?
int a = 5, b = 10;System.out.println(a > b);Đáp án: C
a > b là 5 > 10, sai nên kết quả là false. Java không dùng 0/1 cho boolean như C.
Câu 22. Toán tử nào kiểm tra “không bằng nhau” trong Java?
Đáp án: B
Java dùng != để kiểm tra hai giá trị không bằng nhau.
Câu 23. Đoạn code sau in ra gì?
boolean a = true;boolean b = false;System.out.println(a && b);Đáp án: A
&& (AND) chỉ trả về true khi cả hai vế đều true. Ở đây b là false nên kết quả là false.
Câu 24. Đoạn code sau in ra gì?
boolean a = true;boolean b = false;System.out.println(a || b);Đáp án: B
|| (OR) trả về true khi ít nhất một vế true. Ở đây a là true nên kết quả là true.
Câu 25. Đoạn code sau có biên dịch được không?
int a = 5, b = 10, c = 15;if (a < b < c) { }Đáp án: C
Java không hỗ trợ so sánh chuỗi kiểu a < b < c. Biểu thức a < b cho ra boolean, và boolean < c không hợp lệ (không thể so sánh boolean với int) → lỗi biên dịch. Phải viết a < b && b < c.
Câu 26. Toán tử ! dùng để làm gì?
Đáp án: D
! là toán tử phủ định logic (NOT), biến true thành false và ngược lại. Khác với một số ngôn ngữ khác, Java không dùng ! cho giai thừa.
Câu 27. Cho x = 0. Đoạn code sau in ra gì?
int x = 0;if (x != 0 && 10 / x > 1) { System.out.println("A");} else { System.out.println("B");}Đáp án: A
&& có short-circuit evaluation: vì x != 0 là false, Java không đánh giá tiếp 10 / x (tránh được chia cho 0), toàn bộ điều kiện là false, in ra “B”.
Câu 28. Toán tử nào có độ ưu tiên cao hơn (được tính trước) trong biểu thức a > b && c < d?
Đáp án: B
Toán tử quan hệ (>, <) có độ ưu tiên cao hơn toán tử logic (&&, ||), nên các phép so sánh được tính trước, kết quả boolean mới được đưa vào &&.
Câu 29. Đoạn code sau in ra gì?
System.out.println(5 == 5.0);Đáp án: C
Với các kiểu số nguyên thủy, 5 được tự động nâng kiểu thành 5.0 để so sánh giá trị, kết quả là true.
Câu 30. Đoạn code sau in ra gì?
int a = 5;System.out.println(!(a > 3));Đáp án: A
a > 3 là 5 > 3 → true. !true → false.
Nhóm 4: Nhập/Xuất dữ liệu với Scanner/println
Phần tiêu đề “Nhóm 4: Nhập/Xuất dữ liệu với Scanner/println”Câu 31. Sự khác biệt giữa System.out.println và System.out.print là gì?
Đáp án: C
println (print line) tự thêm ký tự xuống dòng vào cuối, còn print thì không - lần in tiếp theo sẽ nối liền ngay sau.
Câu 32. Cần import gì để sử dụng lớp Scanner?
Đáp án: B
Lớp Scanner nằm trong package java.util, nên phải import java.util.Scanner;.
Câu 33. Câu lệnh nào tạo một đối tượng Scanner đọc dữ liệu từ bàn phím?
Đáp án: A
Scanner cần một nguồn dữ liệu đầu vào, System.in là luồng nhập chuẩn (bàn phím).
Câu 34. Phương thức nào của Scanner dùng để đọc một số nguyên?
Đáp án: D
nextInt() đọc và trả về giá trị int tiếp theo từ luồng nhập.
Câu 35. Vì sao đoạn code sau thường gây lỗi/khó hiểu khi chạy?
Scanner sc = new Scanner(System.in);int age = sc.nextInt();String name = sc.nextLine();Đáp án: B
nextInt() chỉ đọc phần số, để lại ký tự xuống dòng (Enter) trong bộ đệm. nextLine() gọi ngay sau đó sẽ đọc luôn phần còn sót lại đó (một chuỗi rỗng) thay vì chờ người dùng nhập. Cách khắc phục: gọi thêm một sc.nextLine() để “ăn” ký tự xuống dòng thừa.
Câu 36. Phương thức nào của Scanner đọc toàn bộ một dòng (bao gồm khoảng trắng)?
Đáp án: C
nextLine() đọc toàn bộ nội dung cho đến ký tự xuống dòng, kể cả khoảng trắng. next() chỉ đọc đến khoảng trắng tiếp theo (một “từ”).
Câu 37. Đoạn code sau in ra gì?
String name = "Java";int year = 2025;System.out.println(name + " " + year);Đáp án: A
Toán tử + khi có một bên là String sẽ nối chuỗi, tự động chuyển các giá trị khác (như int) thành chuỗi tương ứng.
Câu 38. Chuỗi định dạng nào dùng cho một số thực trong System.out.printf?
Đáp án: D
%f dùng để định dạng số thực (float/double). %d dùng cho số nguyên, %s cho chuỗi, %c cho ký tự.
Câu 39. Đoạn code sau in ra gì?
System.out.printf("%.2f", 3.14159);Đáp án: B
%.2f giới hạn 2 chữ số thập phân, làm tròn giá trị: 3.14159 → 3.14.
Câu 40. Phương thức nào của Scanner đọc một số thực dấu chấm động (double)?
Đáp án: C
nextDouble() đọc và trả về giá trị double tiếp theo. (nextFloat() cũng tồn tại, cho kiểu float, nhưng không phải đáp án đúng ở đây.)
Nhóm 5: Câu lệnh rẽ nhánh if - else (câu 41-50)
Phần tiêu đề “Nhóm 5: Câu lệnh rẽ nhánh if - else (câu 41-50)”Câu 41. Cú pháp nào sau đây khai báo đúng một khối if trong Java?
Đáp án: B
Trong Java, điều kiện của if bắt buộc phải đặt trong dấu ngoặc đơn (), theo sau là khối lệnh trong {}.
Câu 42. Đoạn code sau in ra gì?
int x = 7;if (x > 10) { System.out.println("A");} else if (x > 5) { System.out.println("B");} else { System.out.println("C");}Đáp án: B
x = 7 không lớn hơn 10 nên bỏ qua nhánh đầu, nhưng lớn hơn 5 nên in "B".
Câu 43. Toán tử ba ngôi (ternary) ?: trong Java có cú pháp:
Đáp án: A
Cú pháp toán tử ba ngôi: điều_kiện ? giá_trị_nếu_đúng : giá_trị_nếu_sai, ví dụ int max = (a > b) ? a : b;.
Câu 44. Đoạn code sau in ra gì?
int a = 3, b = 8;int max = (a > b) ? a : b;System.out.println(max);Đáp án: D
a > b là 3 > 8 tức false, nên biểu thức trả về giá trị sau dấu :, là b (8).
Câu 45. Trong Java, biểu thức điều kiện của if phải có kiểu dữ liệu nào?
Đáp án: B
Khác với C/C++, Java không cho phép chuyển ngầm định số nguyên sang boolean - điều kiện của if bắt buộc phải là biểu thức kiểu boolean.
Câu 46. Đoạn code sau có biên dịch được không?
int x = 1;if (x) { System.out.println("yes");}Đáp án: C
Java yêu cầu điều kiện if phải là boolean; dùng trực tiếp một biến int sẽ gây lỗi biên dịch “incompatible types”.
Câu 47. if lồng nhau (nested if) nghĩa là gì?
Đáp án: A
if lồng nhau là đặt một cấu trúc if/else hoàn chỉnh bên trong nhánh if hoặc else của một cấu trúc khác, dùng để kiểm tra nhiều điều kiện phụ thuộc nhau.
Câu 48. Đoạn code sau in ra gì?
int score = 75;String result;if (score >= 90) { result = "Giỏi";} else if (score >= 70) { result = "Khá";} else { result = "Trung bình";}System.out.println(result);Đáp án: D
score = 75 không >= 90 nhưng >= 70, nên result nhận giá trị "Khá".
Câu 49. Toán tử nào KHÔNG thể dùng trực tiếp bên trong biểu thức điều kiện của if?
Đáp án: B
Dùng = (gán) thay vì == (so sánh) trong điều kiện thường gây lỗi biên dịch trong Java, trừ khi biến đó là boolean - nhưng đây vẫn là lỗi logic phổ biến cần tránh, khác với C nơi if (x = 5) biên dịch được.
Câu 50. Đoạn code sau in ra gì?
boolean isMember = true;int age = 15;String ticket = (isMember && age < 18) ? "Vé trẻ em hội viên" : "Vé thường";System.out.println(ticket);Đáp án: C
isMember là true và age < 18 (15 < 18) cũng true, nên điều kiện && đúng, kết quả là "Vé trẻ em hội viên".
Nhóm 6: Vòng lặp for (câu 51-60)
Phần tiêu đề “Nhóm 6: Vòng lặp for (câu 51-60)”Câu 51. Cú pháp đúng của vòng lặp for cổ điển trong Java là:
Đáp án: A
Vòng for cổ điển trong Java gồm ba phần cách nhau bằng dấu ;: khởi tạo, điều kiện, cập nhật.
Câu 52. Đoạn code sau in ra bao nhiêu dòng?
for (int i = 0; i < 5; i++) { System.out.println(i);}Đáp án: B
i chạy từ 0 đến 4 (khi i = 5 điều kiện i < 5 sai nên dừng), tổng cộng in 5 dòng: 0, 1, 2, 3, 4.
Câu 53. Vòng lặp “for-each” (enhanced for) dùng để làm gì?
Đáp án: D
For-each (for (int x : arr)) duyệt tuần tự từng phần tử của mảng/collection, giúp code ngắn gọn hơn khi không cần biết chỉ số phần tử.
Câu 54. Đoạn code sau in ra gì?
int[] nums = {2, 4, 6};int sum = 0;for (int n : nums) { sum += n;}System.out.println(sum);Đáp án: A
Vòng for-each cộng dồn từng phần tử: 2 + 4 + 6 = 12.
Câu 55. Đoạn code sau in ra gì?
for (int i = 1; i <= 3; i++) { for (int j = 1; j <= 2; j++) { System.out.print(i * j + " "); }}Đáp án: C
Với i = 1,2,3 và j = 1,2: các tích lần lượt là 1*1=1, 1*2=2, 2*1=2, 2*2=4, 3*1=3, 3*2=6, mỗi số theo sau một khoảng trắng do + " ".
Câu 56. Vòng lặp for sau chạy bao nhiêu lần?
for (int i = 10; i > 0; i -= 2) { // ...}Đáp án: B
i chạy 10, 8, 6, 4, 2 rồi dừng khi i = 0 (không thỏa i > 0) - tổng cộng 5 lần lặp.
Câu 57. Có thể bỏ trống phần nào trong ba phần của vòng for cổ điển?
Đáp án: D
Cả ba phần của for đều tùy chọn, ví dụ for (;;) { } tạo một vòng lặp vô hạn hợp lệ về cú pháp - chỉ cần giữ đủ hai dấu ;.
Câu 58. Đoạn code sau in ra gì?
String[] fruits = {"táo", "cam", "xoài"};for (String f : fruits) { System.out.print(f + "-");}Đáp án: A
Mỗi phần tử được nối thêm dấu - phía sau, kể cả phần tử cuối, nên kết quả là táo-cam-xoài-.
Câu 59. Trong for-each for (int x : arr), việc thay đổi giá trị x bên trong vòng lặp có ảnh hưởng đến mảng arr gốc không?
Đáp án: C
Với mảng kiểu nguyên thủy (int[]), biến lặp x trong for-each chỉ là một bản sao giá trị tại mỗi lượt, gán lại x không làm thay đổi phần tử trong mảng gốc.
Câu 60. Đoạn code sau in ra gì?
int count = 0;for (int i = 0; i < 20; i += 5) { count++;}System.out.println(count);Đáp án: B
i chạy các giá trị 0, 5, 10, 15 rồi dừng khi i = 20 - tổng cộng 4 lần lặp nên count = 4.
Nhóm 7: Vòng lặp while và do-while (câu 61-70)
Phần tiêu đề “Nhóm 7: Vòng lặp while và do-while (câu 61-70)”Câu 61. Cú pháp đúng của vòng lặp while trong Java là:
Đáp án: A
Cú pháp while trong Java giống if: điều kiện trong (), kiểm tra trước mỗi lần lặp, theo sau là khối lệnh.
Câu 62. Sự khác biệt chính giữa while và do-while là gì?
Đáp án: C
while kiểm tra điều kiện trước khi chạy khối lệnh (có thể không chạy lần nào), còn do-while chạy khối lệnh trước, kiểm tra điều kiện sau - nên luôn chạy ít nhất một lần.
Câu 63. Cú pháp đúng của do-while trong Java là:
Đáp án: D
Cú pháp do-while bắt buộc kết thúc bằng dấu chấm phẩy ; sau while (điều_kiện), khác với while thường.
Câu 64. Đoạn code sau in ra gì?
int i = 10;while (i < 5) { System.out.println(i); i++;}System.out.println("Xong");Đáp án: B
i = 10 không thỏa i < 5 ngay từ đầu, nên while không chạy lần nào - chương trình chỉ in "Xong".
Câu 65. Đoạn code sau in ra gì?
int i = 10;do { System.out.println(i); i++;} while (i < 5);Đáp án: A
do-while luôn chạy khối lệnh ít nhất một lần trước khi kiểm tra điều kiện, nên in 10 một lần rồi dừng vì 11 < 5 là sai.
Câu 66. Cách nào sau đây thoát khỏi một vòng lặp vô hạn while (true) { } một cách có kiểm soát?
Đáp án: C
break thoát ngay lập tức khỏi vòng lặp gần nhất chứa nó, là cách phổ biến để dừng một vòng while (true) khi gặp điều kiện dừng.
Câu 67. Đoạn code sau in ra bao nhiêu số?
int i = 1;while (i <= 100) { if (i > 3) { break; } System.out.println(i); i++;}Đáp án: D
Vòng lặp in 1, 2, 3 rồi khi i = 4, điều kiện i > 3 đúng nên break thoát ngay trước khi in - tổng cộng in 3 số.
Câu 68. Khi nào nên ưu tiên dùng do-while thay vì while?
Đáp án: B
do-while phù hợp khi khối lệnh cần chạy ít nhất một lần trước khi có dữ liệu để kiểm tra điều kiện dừng, ví dụ vòng lặp hiển thị menu và đọc lựa chọn người dùng.
Câu 69. Đoạn code sau in ra gì?
int sum = 0;int i = 1;while (i <= 5) { sum += i; i++;}System.out.println(sum);Đáp án: A
sum cộng dồn 1 + 2 + 3 + 4 + 5 = 15.
Câu 70. Thiếu phần nào trong đoạn code sau sẽ gây ra vòng lặp vô hạn?
int i = 0;while (i < 5) { System.out.println(i);}Đáp án: C
i không được tăng bên trong thân vòng lặp, nên điều kiện i < 5 luôn đúng - gây vòng lặp vô hạn. Đây là lỗi phổ biến khi quên cập nhật biến điều kiện.
Nhóm 8: Mảng (array) cơ bản (câu 71-80)
Phần tiêu đề “Nhóm 8: Mảng (array) cơ bản (câu 71-80)”Câu 71. Cách khai báo và khởi tạo một mảng int gồm 5 phần tử trong Java là:
Đáp án: A
Cú pháp tạo mảng trong Java: <kiểu>[] <tên> = new <kiểu>[kích_thước];.
Câu 72. Chỉ số (index) của phần tử đầu tiên trong mảng Java là bao nhiêu?
Đáp án: B
Mảng trong Java đánh chỉ số bắt đầu từ 0 (zero-based indexing), giống hầu hết ngôn ngữ hiện đại.
Câu 73. Đoạn code sau in ra gì?
int[] arr = {10, 20, 30};System.out.println(arr.length);Đáp án: D
length là một field (không phải phương thức) của mảng, cho biết số phần tử - khác với String.length() là một method có dấu ngoặc.
Câu 74. Đoạn code sau xảy ra chuyện gì?
int[] arr = new int[3];System.out.println(arr[3]);Đáp án: C
Mảng có 3 phần tử hợp lệ ở chỉ số 0, 1, 2 - truy cập arr[3] vượt phạm vi và ném ArrayIndexOutOfBoundsException khi chạy.
Câu 75. Giá trị mặc định của các phần tử trong một mảng int[] vừa được tạo bằng new int[5] là gì?
Đáp án: A
Khác với C++, Java luôn khởi tạo mảng số nguyên với giá trị mặc định 0 (mảng boolean là false, mảng object là null) - không có khái niệm “giá trị rác”.
Câu 76. Phương thức nào dùng để in nội dung mảng dưới dạng chuỗi dễ đọc, ví dụ [1, 2, 3]?
Đáp án: B
Arrays.toString(arr) (từ java.util.Arrays) trả về chuỗi dạng [1, 2, 3]. In trực tiếp arr hoặc gọi arr.toString() chỉ cho ra địa chỉ dạng [I@1b6d3586.
Câu 77. Đoạn code sau in ra gì?
int[] arr = {1, 2, 3};arr[1] = 99;System.out.println(arr[1]);Đáp án: D
Mảng trong Java có thể sửa nội dung phần tử sau khi tạo (chỉ không thể đổi kích thước) - arr[1] = 99 gán lại phần tử tại chỉ số 1.
Câu 78. Sau khi tạo, kích thước của một mảng Java có thể thay đổi được không?
Đáp án: C
Mảng trong Java có kích thước cố định (fixed-size) khi được tạo bằng new; nếu cần một cấu trúc có thể thay đổi kích thước, dùng ArrayList.
Câu 79. Đoạn code sau in ra gì?
int[] a = {1, 2, 3};int[] b = a;b[0] = 100;System.out.println(a[0]);Đáp án: A
Mảng là kiểu tham chiếu (object) - b = a chỉ sao chép tham chiếu, cả a và b cùng trỏ đến một mảng trong bộ nhớ, nên sửa qua b cũng ảnh hưởng đến a.
Câu 80. Cách nào sau đây khai báo một mảng String với 3 phần tử khởi tạo sẵn?
Đáp án: B
String[] arr = {"a", "b", "c"}; dùng cú pháp mảng literal - khai báo và khởi tạo cùng lúc với các giá trị cho sẵn.
Nhóm 9: Chuỗi (String) cơ bản
Phần tiêu đề “Nhóm 9: Chuỗi (String) cơ bản”Câu 81. Trong Java, String là:
Đáp án: C
String là một lớp trong java.lang, không phải kiểu nguyên thủy như int, double. Biến String lưu trữ tham chiếu đến đối tượng String trên heap.
Câu 82. Đặc điểm nào sau đây đúng với String trong Java?
Đáp án: B
String trong Java là bất biến (immutable): mọi phương thức như concat(), replace(), toUpperCase()… đều trả về một đối tượng String mới, không sửa đối tượng gốc.
Câu 83. Khai báo String s1 = "hello"; và String s2 = "hello"; (dùng literal). Java sẽ:
Đáp án: A
Các String literal giống nhau được Java lưu trong String pool (String constant pool) để tái sử dụng, nên s1 và s2 cùng trỏ đến một đối tượng.
Câu 84. Đoạn code sau in ra gì?
String s1 = new String("hi");String s2 = "hi";System.out.println(s1 == s2);Đáp án: D
new String("hi") luôn tạo một đối tượng mới trên heap, không nằm trong String pool, nên s1 và s2 trỏ đến hai đối tượng khác nhau - == (so sánh tham chiếu) trả về false.
Câu 85. Toán tử nào dùng để nối (concatenate) hai chuỗi trong Java?
Đáp án: B
Java dùng toán tử + để nối chuỗi, ví dụ "Hello, " + "World" cho kết quả "Hello, World".
Câu 86. Phương thức nào trả về độ dài của một chuỗi String?
Đáp án: C
String có phương thức length() để lấy số ký tự. Lưu ý khác với mảng - mảng dùng thuộc tính .length không có dấu ngoặc.
Câu 87. Đoạn code sau in ra gì?
String s = "Hello World";System.out.println(s.substring(6));Đáp án: A
substring(6) trả về phần chuỗi bắt đầu từ chỉ số 6 (ký tự 'W') đến hết chuỗi, tức "World".
Câu 88. Phương thức nào tìm vị trí xuất hiện đầu tiên của một chuỗi con?
Đáp án: B
indexOf(String) trả về chỉ số (index) xuất hiện đầu tiên của chuỗi con, hoặc -1 nếu không tìm thấy.
Câu 89. Cách chính xác để so sánh nội dung của hai chuỗi trong Java là:
Đáp án: D
.equals() so sánh nội dung chuỗi, trong khi == so sánh tham chiếu (địa chỉ đối tượng) - hai khái niệm khác nhau.
Câu 90. Đoạn code sau in ra gì?
String s = " Java ";System.out.println(s.trim());Đáp án: C
trim() loại bỏ khoảng trắng ở đầu và cuối chuỗi, trả về một String mới ("Java"), không ảnh hưởng khoảng trắng ở giữa.
Nhóm 10: Phương thức (method) cơ bản
Phần tiêu đề “Nhóm 10: Phương thức (method) cơ bản”Câu 91. Cú pháp khai báo một phương thức trong Java gồm những thành phần nào theo đúng thứ tự?
Đáp án: B
Cú pháp chuẩn: accessModifier returnType methodName(parameters) { ... }, ví dụ public static int add(int a, int b) { ... }.
Câu 92. Một phương thức không trả về giá trị nào phải khai báo kiểu trả về là:
Đáp án: A
void biểu thị phương thức không trả về giá trị nào. Java yêu cầu luôn khai báo kiểu trả về, kể cả khi không trả về gì.
Câu 93. Trong đoạn code:
static int add(int a, int b) { return a + b;}a và b được gọi là gì?
Đáp án: C
a, b là tham số (parameter) - biến được khai báo trong định nghĩa phương thức. Giá trị thực truyền vào khi gọi (ví dụ add(3, 5)) mới là đối số (argument).
Câu 94. Đoạn code sau in ra gì?
static void increment(int x) { x = x + 1;}
public static void main(String[] args) { int number = 5; increment(number); System.out.println(number);}Đáp án: B
Java truyền tham số kiểu nguyên thủy theo giá trị (pass-by-value) - x bên trong increment chỉ là bản sao, thay đổi nó không ảnh hưởng đến number bên ngoài.
Câu 95. Nạp chồng phương thức (method overloading) là:
Đáp án: D
Overloading cho phép định nghĩa nhiều phương thức cùng tên nhưng khác kiểu/số lượng tham số, ví dụ add(int, int) và add(double, double).
Câu 96. Hai phương thức sau có được xem là overloading hợp lệ không?
int calc(int a, int b) { return a + b; }double calc(int a, int b) { return a - b; }Đáp án: A
Overloading yêu cầu khác danh sách tham số (kiểu, số lượng, hoặc thứ tự). Chỉ khác kiểu trả về là không đủ để phân biệt - trình biên dịch báo lỗi trùng phương thức.
Câu 97. Giá trị mặc định trả về khi một phương thức khai báo void nhưng có return; (không kèm giá trị) là gì?
Đáp án: C
Với phương thức void, return; (không kèm giá trị) hợp lệ và chỉ dùng để kết thúc phương thức sớm, không trả về dữ liệu gì.
Câu 98. Từ khóa nào cho phép một phương thức nhận số lượng tham số không cố định (varargs)?
Đáp án: B
int... numbers (varargs) cho phép gọi phương thức với số lượng đối số int tùy ý; bên trong phương thức, numbers được xem như mảng int[].
Câu 99. Đoạn code sau in ra gì?
static void addItem(List<String> list) { list.add("mới");}
public static void main(String[] args) { List<String> items = new ArrayList<>(); items.add("ban đầu"); addItem(items); System.out.println(items);}Đáp án: D
Java truyền tham chiếu theo giá trị: list bên trong addItem là bản sao của tham chiếu, nhưng vẫn trỏ đến cùng đối tượng ArrayList - sửa nội dung đối tượng (thêm phần tử) sẽ ảnh hưởng ra ngoài.
Câu 100. Varargs (...) trong danh sách tham số phải:
Đáp án: A
Một phương thức chỉ được có tối đa một tham số varargs, và nó phải là tham số cuối cùng trong danh sách tham số.
Nhóm 11: Toán tử gán, tăng/giảm và toán tử ba ngôi
Phần tiêu đề “Nhóm 11: Toán tử gán, tăng/giảm và toán tử ba ngôi”Câu 101. Đoạn code sau in ra gì?
int x = 5;x += 3;System.out.println(x);Đáp án: C
x += 3 tương đương x = x + 3, tức 5 + 3 = 8.
Câu 102. Sự khác biệt giữa x++ (postfix) và ++x (prefix) là gì?
Đáp án: B
Postfix (x++) trả về giá trị hiện tại của biến trước khi tăng; prefix (++x) tăng biến trước rồi mới trả về giá trị đã tăng.
Câu 103. Đoạn code sau in ra gì?
int x = 5;int y = x++ + ++x;System.out.println(y);Đáp án: D
x++ trả về 5 rồi x thành 6. ++x tăng x lên 7 rồi trả về 7. Vậy y = 5 + 7 = 12.
Câu 104. Toán tử ba ngôi (ternary) trong Java có cú pháp:
Đáp án: A
Toán tử ba ngôi là một biểu thức, cú pháp condition ? valueIfTrue : valueIfFalse, ví dụ int max = (a > b) ? a : b;.
Câu 105. Đoạn code sau in ra gì?
int a = 10, b = 20;int max = (a > b) ? a : b;System.out.println(max);Đáp án: C
a > b (10 > 20) là false, nên biểu thức trả về giá trị sau dấu :, tức b = 20.
Câu 106. Đoạn code sau in ra gì?
int a, b, c;a = b = c = 5;System.out.println(a + " " + b + " " + c);Đáp án: B
Toán tử gán = trả về giá trị đã gán, nên có thể chuỗi gán (chained assignment) từ phải sang trái: c = 5, rồi b = c (=5), rồi a = b (=5).
Câu 107. Toán tử %= thực hiện điều gì?
Đáp án: A
x %= 3 tương đương x = x % 3 - gán lại x bằng phần dư của x chia cho 3.
Câu 108. Đoạn code sau in ra gì?
int x = 8;x /= 2;x *= 3;System.out.println(x);Đáp án: D
x /= 2 → x = 4. Sau đó x *= 3 → x = 12.
Câu 109. Biểu thức ternary lồng nhau nào sau đây trả về "B" khi score = 75?
String grade = (score >= 90) ? "A" : (score >= 70) ? "B" : "C";Đáp án: C
score >= 90 (75>=90) là false nên xét nhánh else: score >= 70 (75>=70) là true nên trả về "B". Ternary lồng nhau hoàn toàn hợp lệ trong Java.
Câu 110. Đoạn code sau in ra gì?
int x = 3;int y = x-- - --x;System.out.println(y);Đáp án: B
x-- trả về 3 rồi x thành 2. --x giảm x xuống 1 rồi trả về 1. Vậy y = 3 - 1 = 2.
Nhóm 12: Ép kiểu dữ liệu và hằng số
Phần tiêu đề “Nhóm 12: Ép kiểu dữ liệu và hằng số”Câu 111. Chuyển đổi kiểu int sang double (ví dụ double d = 5;) là dạng ép kiểu nào?
Đáp án: B
Chuyển từ kiểu có phạm vi nhỏ hơn sang lớn hơn (int → double) là widening, xảy ra tự động (ngầm định), không mất dữ liệu và không cần cú pháp ép kiểu.
Câu 112. Đoạn code sau in ra gì?
double d = 9.99;int x = (int) d;System.out.println(x);Đáp án: D
Ép kiểu (int) từ double sang int cắt bỏ (truncate) phần thập phân, không làm tròn, nên 9.99 thành 9.
Câu 113. Chuyển đổi từ double sang int (narrowing) cần:
Đáp án: A
Chuyển từ kiểu có phạm vi lớn hơn sang nhỏ hơn (double → int) là narrowing, có thể mất dữ liệu nên Java yêu cầu ép kiểu tường minh (int).
Câu 114. Quy ước đặt tên phổ biến cho hằng số (final) trong Java là gì?
Đáp án: C
Quy ước phổ biến trong Java (và nhiều ngôn ngữ khác) đặt tên hằng số bằng chữ hoa, các từ cách nhau bởi dấu gạch dưới: UPPER_SNAKE_CASE.
Câu 115. Đoạn code sau xảy ra điều gì?
final int MAX = 100;MAX = 200;Đáp án: B
final khiến biến chỉ được gán giá trị một lần. Gán lại giá trị mới cho biến final gây lỗi biên dịch.
Câu 116. Đoạn code sau có hợp lệ không?
final List<String> names = new ArrayList<>();names.add("An");Đáp án: D
final chỉ khóa việc gán lại tham chiếu (names = new ArrayList<>() sẽ lỗi), nhưng vẫn có thể gọi các phương thức làm thay đổi nội dung đối tượng như add().
Câu 117. Ép kiểu (long) someInt có cần ép kiểu tường minh không?
Đáp án: A
long có phạm vi lớn hơn int, nên chuyển int sang long là widening - xảy ra tự động, không bắt buộc ép kiểu (dù viết (long) vẫn hợp lệ).
Câu 118. Đoạn code sau in ra gì?
int a = 7;int b = 2;double result = (double) a / b;System.out.println(result);Đáp án: C
(double) a ép a thành 7.0 trước, sau đó phép chia 7.0 / 2 là phép chia số thực, cho kết quả 3.5 thay vì bị cắt như chia số nguyên.
Câu 119. Từ khóa static final khi dùng cùng nhau cho một trường (field) trong lớp có nghĩa là gì?
Đáp án: B
static khiến trường thuộc về lớp (dùng chung, không nhân bản theo từng đối tượng), kết hợp với final tạo thành một hằng số cấp lớp, ví dụ static final double PI = 3.14;.
Câu 120. Đoạn code sau in ra gì?
char c = 'A';int code = (int) c;System.out.println(code);Đáp án: A
char trong Java thực chất là một số nguyên 16-bit đại diện cho mã Unicode. Ép kiểu (int) 'A' trả về mã Unicode của 'A', tức 65.
Nhóm 13: Câu lệnh switch-case
Phần tiêu đề “Nhóm 13: Câu lệnh switch-case”Câu 121. Trong switch truyền thống của Java, từ khóa nào dùng để thoát khỏi switch sau khi một case khớp, tránh “rơi” xuống case bên dưới?
Đáp án: B
break thoát khỏi khối switch ngay sau khi case khớp được xử lý xong, tránh fall-through xuống các case tiếp theo.
Câu 122. Đoạn code sau in ra gì?
int day = 2;switch (day) { case 1: System.out.println("Một"); case 2: System.out.println("Hai"); case 3: System.out.println("Ba"); break; default: System.out.println("Khác");}Đáp án: C
case 1 bị bỏ qua vì không khớp. Khớp case 2, nhưng thiếu break nên “rơi” tiếp xuống case 3 (in “Ba”) rồi mới gặp break và dừng lại.
Câu 123. Kiểu dữ liệu nào không thể dùng làm biểu thức điều kiện của switch trong Java?
Đáp án: A
switch chỉ chấp nhận kiểu số nguyên (byte, short, char, int), String, enum và các kiểu bao (wrapper) tương ứng - không chấp nhận double/float.
Câu 124. Khối nào trong switch được thực thi nếu không có case nào khớp giá trị?
Đáp án: D
default là nhánh dự phòng, chạy khi giá trị của biểu thức không khớp bất kỳ case nào (giống else trong if).
Câu 125. Đoạn code sau (Java 14+) in ra gì?
int day = 6;String type = switch (day) { case 6, 7 -> "Cuối tuần"; default -> "Ngày thường";};System.out.println(type);Đáp án: B
Switch expression hiện đại dùng mũi tên -> cho phép gộp nhiều nhãn case (6, 7) trên một dòng; day = 6 khớp nên trả về "Cuối tuần".
Câu 126. Điểm khác biệt quan trọng giữa switch expression (->, Java 14+) và switch statement truyền thống là gì?
Đáp án: C
Với cú pháp mũi tên ->, mỗi nhánh chỉ thực thi đúng nhánh khớp rồi dừng - không có hiện tượng “rơi” (fall-through) như switch truyền thống, nên không cần break.
Câu 127. Trong một khối case nhiều dòng của switch expression, từ khóa nào dùng để trả về giá trị?
Đáp án: A
Khi một nhánh case của switch expression cần nhiều câu lệnh (dùng khối {}), yield dùng để chỉ định giá trị trả về của nhánh đó thay vì return.
Câu 128. Đoạn code sau in ra gì?
String fruit = "cam";switch (fruit) { case "tao": System.out.println("Táo"); break; case "cam": System.out.println("Cam"); break; default: System.out.println("Khác");}Đáp án: C
Java hỗ trợ switch trên String (so sánh nội dung bằng .equals() ngầm định) - fruit khớp "cam" nên in "Cam".
Câu 129. Nếu quên break ở tất cả các case (trừ case cuối) trong switch truyền thống, và giá trị khớp với case đầu tiên, điều gì xảy ra?
Đáp án: B
Thiếu break khiến luồng thực thi “rơi xuyên” (fall through) tuần tự qua tất cả các case tiếp theo cho đến khi gặp break hoặc hết khối switch.
Câu 130. Cách nào sau đây không phải là cú pháp hợp lệ của switch trong Java hiện đại?
Đáp án: D
switch không chấp nhận biểu thức kiểu double/float trong bất kỳ dạng cú pháp nào - chỉ số nguyên, String, enum.
Nhóm 14: Phạm vi biến (scope)
Phần tiêu đề “Nhóm 14: Phạm vi biến (scope)”Câu 131. Đoạn code sau xảy ra điều gì?
public static void main(String[] args) { if (true) { int y = 20; } System.out.println(y);}Đáp án: B
y chỉ tồn tại trong phạm vi khối {} của if nơi nó được khai báo (block scope) - truy cập ngoài khối đó gây lỗi biên dịch “cannot find symbol”.
Câu 132. Biến khai báo trong phần khởi tạo của vòng lặp for (ví dụ for (int i = 0; ...)) có phạm vi tồn tại ở đâu?
Đáp án: C
Biến khai báo trong for (int i = 0; ...) chỉ tồn tại trong phạm vi vòng lặp đó - dùng i sau khi vòng lặp kết thúc sẽ gây lỗi biên dịch.
Câu 133. Tham số của một phương thức có phạm vi tồn tại ở đâu?
Đáp án: A
Tham số là biến cục bộ đặc biệt của phương thức - chỉ tồn tại và truy cập được bên trong thân phương thức đó, biến mất khi phương thức kết thúc.
Câu 134. Java có hỗ trợ biến toàn cục (global variable) theo kiểu như một số ngôn ngữ khác (biến ở phạm vi file, ngoài mọi class) không?
Đáp án: D
Java không có khái niệm biến toàn cục ở phạm vi file - mọi biến phải là field của một class (instance hoặc static) hoặc biến cục bộ trong một khối/phương thức.
Câu 135. “Variable shadowing” (che khuất biến) xảy ra khi nào?
Đáp án: B
Shadowing xảy ra khi biến cục bộ/tham số cùng tên với field của class - bên trong phạm vi đó, tên đó sẽ tham chiếu đến biến cục bộ chứ không phải field (muốn truy cập field phải dùng this.tenField).
Câu 136. Đoạn code sau in ra gì?
public class Counter { int count = 5; // field
void show() { int count = 10; // biến cục bộ, che field System.out.println(count); }}Gọi new Counter().show();
Đáp án: C
Biến cục bộ count bên trong show() che field count của class trong phạm vi phương thức - System.out.println(count) tham chiếu đến biến cục bộ (giá trị 10), không gây lỗi.
Câu 137. Một field (thuộc tính) của class có phạm vi tồn tại như thế nào so với biến cục bộ trong một phương thức?
Đáp án: A
Field gắn với đối tượng (instance field) hoặc class (static field), tồn tại lâu hơn nhiều so với biến cục bộ vốn chỉ sống trong phạm vi khối lệnh nơi nó được khai báo.
Câu 138. Đoạn code sau có biên dịch được không?
public static void main(String[] args) { for (int i = 0; i < 3; i++) { System.out.println(i); } for (int i = 0; i < 5; i++) { // khai báo lại i System.out.println(i); }}Đáp án: B
Mỗi vòng for tạo phạm vi riêng cho biến khởi tạo của nó - i ở vòng lặp thứ nhất đã hết phạm vi khi vòng lặp đó kết thúc, nên khai báo i mới ở vòng lặp thứ hai hoàn toàn hợp lệ.
Câu 139. Điều gì xảy ra khi biên dịch đoạn code sau?
public static void main(String[] args) { int x = 5; int x = 10; // khai báo lại cùng tên, cùng phạm vi}Đáp án: D
Không giống shadowing giữa các phạm vi lồng nhau khác nhau, khai báo lại một biến cùng tên trong cùng một phạm vi là lỗi biên dịch (“variable x is already defined”).
Câu 140. Muốn truy cập field của class bị che (shadow) bởi một biến cục bộ/tham số cùng tên, ta dùng cách nào?
Đáp án: C
this.tenField luôn tham chiếu đến field của đối tượng hiện tại, bất kể có biến cục bộ/tham số cùng tên đang che nó trong phạm vi hiện tại hay không - cách phổ biến nhất thường thấy trong constructor.
Nhóm 15: Mảng hai chiều
Phần tiêu đề “Nhóm 15: Mảng hai chiều”Câu 141. Cách khai báo mảng hai chiều đúng trong Java là gì?
Đáp án: A
Cú pháp chuẩn Java để tạo mảng hai chiều 3 hàng 4 cột là int[][] grid = new int[3][4];.
Câu 142. Java thực chất mô phỏng mảng hai chiều như thế nào?
Đáp án: B
int[][] thực chất là “mảng của mảng” (array of arrays) - mỗi phần tử của mảng ngoài là một tham chiếu đến một mảng int[] riêng biệt.
Câu 143. Đoạn code sau in ra gì?
int[][] matrix = { {1, 2, 3}, {4, 5, 6}};System.out.println(matrix[1][2]);Đáp án: D
matrix[1] là hàng thứ hai (chỉ số 1) {4, 5, 6}; matrix[1][2] là phần tử thứ ba (chỉ số 2) của hàng đó, tức 6.
Câu 144. “Mảng lởm chởm” (jagged array) trong Java là gì?
Đáp án: C
Vì mảng hai chiều thực chất là “mảng của mảng”, mỗi hàng có thể có độ dài khác nhau độc lập - gọi là mảng lởm chởm (jagged array).
Câu 145. Với int[][] matrix = new int[3][5];, biểu thức matrix.length trả về giá trị nào?
Đáp án: B
matrix.length là số phần tử của mảng ngoài cùng, tức số hàng - ở đây là 3. Số cột của hàng i là matrix[i].length.
Câu 146. Phương thức nào dùng để in đẹp nội dung một mảng hai chiều (thay vì in ra địa chỉ tham chiếu)?
Đáp án: A
Arrays.toString() chỉ in đúng cho mảng một chiều (mảng hai chiều sẽ in ra địa chỉ các mảng con) - cần Arrays.deepToString() để in đầy đủ nội dung mảng lồng nhau.
Câu 147. Đoạn code sau tính tổng các phần tử của mảng hai chiều bằng vòng lặp lồng nhau - biểu thức nào cần điền vào chỗ trống để duyệt đúng số cột của từng hàng?
int[][] matrix = {{1, 2}, {3, 4, 5}};int sum = 0;for (int i = 0; i < matrix.length; i++) { for (int j = 0; j < ____; j++) { sum += matrix[i][j]; }}Đáp án: C
Vì mảng có thể lởm chởm, số cột của mỗi hàng phải lấy theo matrix[i].length (độ dài của hàng i đang xét), không phải một giá trị cố định.
Câu 148. Giá trị mặc định của các phần tử khi tạo int[][] grid = new int[2][3]; là gì?
Đáp án: D
Giống mảng một chiều, mảng int hai chiều được Java tự động khởi tạo mọi phần tử về giá trị mặc định của int là 0.
Câu 149. Cách nào sau đây tạo đúng một mảng lởm chởm (jagged array) 3 hàng với số cột khác nhau?
Đáp án: B
Khai báo new int[3][] chỉ định số hàng (3) mà chưa cấp phát cột, sau đó mỗi hàng được cấp phát độ dài riêng độc lập bằng new int[n].
Câu 150. Với int[][] m = {{1,2,3},{4,5}};, đoạn code m[1][2] khi chạy sẽ như thế nào?
Đáp án: A
Hàng m[1] là {4, 5}, chỉ có 2 phần tử hợp lệ ở chỉ số 0 và 1. Truy cập m[1][2] vượt phạm vi, ném ArrayIndexOutOfBoundsException lúc chạy chương trình.
Nhóm 16: Lớp và đối tượng (Class & Object) cơ bản
Phần tiêu đề “Nhóm 16: Lớp và đối tượng (Class & Object) cơ bản”Câu 151. Trong lập trình hướng đối tượng Java, một class được mô tả tốt nhất là gì?
Đáp án: C
Class là khuôn mẫu (blueprint) định nghĩa các field (thuộc tính, trạng thái) và method (hành vi) mà mọi đối tượng tạo ra từ nó sẽ có.
Câu 152. Từ khóa nào dùng để tạo một đối tượng (object) mới từ một class trong Java?
Đáp án: D
Từ khóa new gọi constructor của class để cấp phát bộ nhớ và khởi tạo một đối tượng mới, ví dụ Dog dog1 = new Dog();.
Câu 153. Đoạn code sau in ra gì?
public class Dog { String name; void bark() { System.out.println(name + " sủa: Gâu gâu!"); }}
public class Main { public static void main(String[] args) { Dog dog1 = new Dog(); dog1.name = "Lucky"; Dog dog2 = new Dog(); dog2.name = "Milu"; dog1.bark(); }}Đáp án: B
Mỗi đối tượng có trạng thái (field) riêng biệt và độc lập; dog1.bark() dùng field name của chính dog1 (đã gán “Lucky”), không liên quan đến dog2.
Câu 154. Constructor trong Java có đặc điểm gì?
Đáp án: A
Constructor bắt buộc trùng tên chính xác với class và không khai báo bất kỳ kiểu trả về nào - kể cả void. Một class có thể có nhiều constructor (nạp chồng - overload).
Câu 155. Nếu một class không định nghĩa constructor nào, điều gì xảy ra khi tạo đối tượng bằng new?
Đáp án: C
Nếu lớp không khai báo constructor nào, trình biên dịch tự động tạo một constructor mặc định không tham số, không làm gì khác ngoài khởi tạo các field về giá trị mặc định.
Câu 156. Từ khóa this trong một constructor hoặc method dùng để làm gì?
Đáp án: B
this tham chiếu đến chính đối tượng đang thực thi đoạn code - thường dùng để phân biệt field của đối tượng với tham số cùng tên, ví dụ this.name = name;.
Câu 157. Tại sao nên khai báo field là private thay vì public?
Đáp án: D
Khai báo private ngăn code bên ngoài gán trực tiếp giá trị bất hợp lệ vào field - buộc phải đi qua getter/setter, nơi có thể kiểm tra điều kiện (nguyên tắc đóng gói - encapsulation).
Câu 158. Phương thức nào sau đây đóng vai trò “getter” theo quy ước đặt tên phổ biến trong Java cho field private double balance;?
Đáp án: A
Quy ước Java đặt tên getter là get + tên field viết hoa chữ cái đầu, trả về giá trị của field - ở đây getBalance() trả về balance.
Câu 159. Nếu hai constructor của cùng một class có cùng số lượng tham số nhưng khác kiểu dữ liệu, đây có phải là constructor overloading hợp lệ không?
Đáp án: C
Overload hợp lệ khi danh sách tham số khác nhau về số lượng hoặc kiểu dữ liệu (thứ tự cũng tính) - constructor không có kiểu trả về nên tiêu chí đó không áp dụng.
Câu 160. Đoạn code sau in ra gì?
public class Account { private double balance;
public void deposit(double amount) { if (amount > 0) { balance += amount; } }
public double getBalance() { return balance; }}
public class Main { public static void main(String[] args) { Account acc = new Account(); acc.deposit(100); acc.deposit(-50); System.out.println(acc.getBalance()); }}Đáp án: B
deposit(100) cộng 100 vào balance (do 100 > 0). deposit(-50) bị điều kiện amount > 0 chặn lại, không cộng gì - balance giữ nguyên 100.0.
Nhóm 17: ArrayList và Collections cơ bản
Phần tiêu đề “Nhóm 17: ArrayList và Collections cơ bản”Câu 161. Để sử dụng ArrayList, ta cần import gói nào?
Đáp án: B
ArrayList nằm trong gói java.util, cùng với các collection khác như HashMap, HashSet.
Câu 162. Cách khai báo ArrayList nào sau đây đúng và đúng quy ước (khai báo bằng interface List)?
Đáp án: A
Quy ước phổ biến là khai báo biến bằng kiểu interface List<E>, khởi tạo bằng class cụ thể ArrayList<>(). List là interface nên không thể new List<>() (phương án B), và cú pháp ở C, D không hợp lệ.
Câu 163. Đoạn code sau in ra gì?
List<String> fruits = new ArrayList<>();fruits.add("táo");fruits.add("cam");fruits.add("xoài");System.out.println(fruits.get(1));Đáp án: C
get(1) lấy phần tử ở chỉ số 1 (chỉ số bắt đầu từ 0), tức phần tử thứ hai được thêm vào là “cam”.
Câu 164. Để lấy số phần tử hiện có trong một ArrayList tên list, ta dùng:
Đáp án: B
Khác với mảng (dùng field .length), ArrayList (và các collection khác) dùng phương thức .size() để lấy số phần tử.
Câu 165. Đoạn code sau có vấn đề gì?
List<int> numbers = new ArrayList<>();numbers.add(10);Đáp án: D
Generic trong Java chỉ hoạt động với kiểu đối tượng (reference type), không chấp nhận trực tiếp kiểu nguyên thủy như int. Phải khai báo List<Integer> - khi đó add(10) sẽ tự động autobox int thành Integer.
Câu 166. Phương thức nào sau đây kiểm tra một ArrayList có chứa một giá trị cụ thể hay không?
Đáp án: A
contains(value) trả về true/false tùy vào việc phần tử có tồn tại trong danh sách hay không.
Câu 167. Khác biệt chính giữa mảng (array) và ArrayList là gì?
Đáp án: C
Mảng có độ dài cố định ngay khi khởi tạo, còn ArrayList tự động thay đổi kích thước khi thêm/xóa phần tử.
Câu 168. Cách nào sau đây để duyệt qua tất cả phần tử của một ArrayList<String> names?
Đáp án: B
Vòng lặp for-each for (KiểuPhầnTử biến : collection) là cách chuẩn để duyệt ArrayList trong Java. Phương án A dùng <= nên sẽ ném IndexOutOfBoundsException, C và D không phải cú pháp Java hợp lệ.
Câu 169. Đoạn code sau in ra gì?
Map<String, Integer> scores = new HashMap<>();scores.put("An", 8);scores.put("Binh", 9);System.out.println(scores.get("An"));Đáp án: D
scores.get("An") trả về giá trị (value) tương ứng với key "An", đã được put là 8.
Câu 170. HashMap.get() trả về gì nếu key không tồn tại trong map?
Đáp án: A
Nếu key không tồn tại, get() trả về null (không ném exception). Có thể dùng getOrDefault(key, giá trị mặc định) để tránh nhận null.
Nhóm 18: Đệ quy (recursion) cơ bản
Phần tiêu đề “Nhóm 18: Đệ quy (recursion) cơ bản”Câu 171. Đệ quy (recursion) trong lập trình là gì?
Đáp án: C
Đệ quy là kỹ thuật một phương thức gọi lại chính nó, thường để chia bài toán lớn thành các bài toán con nhỏ hơn cùng dạng.
Câu 172. Thành phần nào bắt buộc phải có trong một phương thức đệ quy để nó dừng lại?
Đáp án: B
Base case là điều kiện dừng, khi đạt tới thì phương thức không gọi lại chính nó nữa. Thiếu base case (hoặc base case không bao giờ đạt được) sẽ gây đệ quy vô hạn.
Câu 173. Cho phương thức:
static int factorial(int n) { if (n <= 1) return 1; return n * factorial(n - 1);}factorial(4) trả về giá trị nào?
Đáp án: A
factorial(4) = 4 * 3 * 2 * 1 = 24.
Câu 174. Cho phương thức:
static int fib(int n) { if (n <= 1) return n; return fib(n - 1) + fib(n - 2);}fib(5) trả về giá trị nào?
Đáp án: C
Dãy Fibonacci: fib(0)=0, fib(1)=1, fib(2)=1, fib(3)=2, fib(4)=3, fib(5)=5.
Câu 175. Điều gì xảy ra nếu một phương thức đệ quy thiếu base case (hoặc base case không bao giờ đạt được)?
Đáp án: D
Mỗi lời gọi đệ quy chiếm một khung (frame) trên call stack. Không có base case khiến các lời gọi tiếp diễn vô hạn cho đến khi stack đầy, ném StackOverflowError.
Câu 176. Trong lời gọi đệ quy return n * factorial(n - 1);, tham số truyền cho lời gọi tiếp theo có đặc điểm gì để đảm bảo đệ quy kết thúc?
Đáp án: B
Mỗi lần gọi đệ quy, tham số cần tiến gần hơn tới điều kiện base case (ở đây n giảm dần về 1), nếu không đệ quy sẽ không bao giờ dừng.
Câu 177. So với cách viết vòng lặp (iterative), cách viết đệ quy (recursive) cho cùng một bài toán thường:
Đáp án: A
Đệ quy thường giúp code ngắn gọn, tự nhiên hơn với các bài toán chia nhỏ được, nhưng mỗi lời gọi tốn thêm một khung stack - nếu độ sâu đệ quy lớn có thể chậm hơn/tốn bộ nhớ hơn vòng lặp tương đương.
Câu 178. Cho phương thức:
static int sum(int n) { if (n == 0) return 0; return n + sum(n - 1);}sum(3) trả về giá trị nào?
Đáp án: C
sum(3) = 3 + sum(2) = 3 + 2 + sum(1) = 3 + 2 + 1 + sum(0) = 3 + 2 + 1 + 0 = 6.
Câu 179. Trong lời gọi factorial(3) với định nghĩa ở câu 173, thứ tự nào mô tả đúng quá trình thực thi?
Đáp án: D
Đệ quy đi sâu dần (factorial(3) → factorial(2) → factorial(1)) cho tới base case, rồi các lời gọi lần lượt trả về (quay lui) và nhân kết quả lại: 1 → 21=2 → 32=6.
Câu 180. Đoạn code nào sau đây là một phương thức đệ quy đúng để tính tổng các số từ 1 đến n?
Đáp án: B
Phương án B có base case (n <= 0) và tham số giảm dần (n - 1) ở mỗi lần gọi, đảm bảo đệ quy kết thúc. A và D không giảm n nên đệ quy vô hạn (StackOverflowError).
Nhóm 19: Xử lý ngoại lệ (Exception) cơ bản
Phần tiêu đề “Nhóm 19: Xử lý ngoại lệ (Exception) cơ bản”Câu 181. Cấu trúc nào dùng để bắt và xử lý ngoại lệ (exception) trong Java?
Đáp án: A
try bao quanh đoạn code có thể ném lỗi, catch bắt và xử lý loại exception tương ứng.
Câu 182. Đoạn code sau in ra gì?
try { System.out.println("A"); int x = 10 / 0;} catch (ArithmeticException e) { System.out.println("B");} finally { System.out.println("C");}Đáp án: D
“A” được in trước khi lỗi xảy ra. 10 / 0 với số nguyên ném ArithmeticException, được catch bắt và in “B”. Khối finally luôn luôn chạy sau try/catch, in “C”.
Câu 183. Đoạn code int x = 10 / 0; (với x là số nguyên int) sẽ:
Đáp án: B
Chia số nguyên cho 0 ném ArithmeticException: / by zero khi chương trình chạy (đây là exception thuộc kiểu unchecked). Với số thực (double), 10.0 / 0 lại cho Infinity, không ném lỗi.
Câu 184. Exception nào bị ném khi gọi một phương thức trên một tham chiếu đang là null?
Đáp án: C
Gọi phương thức hoặc truy cập field trên một tham chiếu null ném NullPointerException (NPE) - một trong những lỗi runtime phổ biến nhất trong Java.
Câu 185. Đoạn code sau ném exception gì?
int[] arr = {1, 2, 3};System.out.println(arr[3]);Đáp án: A
Mảng arr có 3 phần tử, chỉ số hợp lệ là 0, 1, 2. Truy cập arr[3] (vượt quá phạm vi) ném ArrayIndexOutOfBoundsException lúc chạy chương trình.
Câu 186. Cú pháp nào cho phép bắt nhiều loại exception khác nhau trong cùng một khối catch?
Đáp án: C
Java hỗ trợ multi-catch với cú pháp dùng dấu | để gộp nhiều loại exception vào cùng một khối catch khi cách xử lý giống nhau.
Câu 187. Từ khóa nào dùng để chủ động ném một ngoại lệ trong Java?
Đáp án: B
throw new IllegalArgumentException("...") chủ động ném một exception. throws (có “s”) lại dùng trong khai báo phương thức để công bố các checked exception có thể phát sinh.
Câu 188. Exception nào sau đây là checked exception, bắt buộc phải khai báo throws hoặc bắt bằng try/catch?
Đáp án: D
IOException là checked exception (kế thừa trực tiếp từ Exception, không phải RuntimeException) - trình biên dịch buộc bạn phải xử lý. Ba lựa chọn còn lại đều là RuntimeException (unchecked), không bắt buộc khai báo.
Câu 189. Trong đoạn code sau, phương thức trả về giá trị nào?
static int test() { try { return 1; } finally { System.out.println("finally chạy"); }}Đáp án: A
Khối finally luôn chạy trước khi phương thức thực sự trả về, kể cả khi try đã có return. Ở đây không có exception nên try trả về 1 sau khi in “finally chạy”.
Câu 190. Khối finally trong try/catch/finally có đặc điểm gì?
Đáp án: C
finally luôn được thực thi, thường dùng để giải phóng tài nguyên (đóng file, kết nối…) bất kể try thành công, ném lỗi, hay đã có return.
Nhóm 20: Tổng hợp và lỗi thường gặp
Phần tiêu đề “Nhóm 20: Tổng hợp và lỗi thường gặp”Câu 191. Đoạn code sau in ra gì?
String a = new String("hi");String b = new String("hi");System.out.println(a == b);Đáp án: B
new String("hi") tạo ra một object mới trên heap mỗi lần gọi, nên a và b là hai tham chiếu khác nhau. == so sánh tham chiếu (địa chỉ), không phải nội dung, nên kết quả là false. Muốn so sánh nội dung phải dùng a.equals(b).
Câu 192. Đoạn code sau in ra gì?
int a = 5;int b = 2;System.out.println(a / b);Đáp án: A
Chia hai số int cho ra kết quả int, phần thập phân bị cắt bỏ (không làm tròn): 5 / 2 = 2. Muốn kết quả 2.5 cần ép ít nhất một toán hạng sang double.
Câu 193. Đoạn code sau in ra gì?
System.out.println(0.1 + 0.2 == 0.3);Đáp án: C
Do cách biểu diễn số thực nhị phân (IEEE 754), 0.1 + 0.2 thực chất cho ra 0.30000000000000004, khác với 0.3 khi so sánh bằng ==. Nên so sánh số thực bằng một khoảng sai số (epsilon) hoặc dùng BigDecimal khi cần chính xác tuyệt đối.
Câu 194. Đoạn code sau xảy ra điều gì?
String s = null;System.out.println(s.length());Đáp án: D
s đang là null, gọi phương thức .length() trên nó ném NullPointerException. Đây là một trong những lỗi runtime phổ biến nhất trong Java.
Câu 195. Đoạn code sau xảy ra điều gì?
int[] scores = new int[5];System.out.println(scores[5]);Đáp án: B
Mảng scores có 5 phần tử, chỉ số hợp lệ từ 0 đến 4. scores[5] vượt phạm vi, ném ArrayIndexOutOfBoundsException lúc chạy chương trình.
Câu 196. Đoạn code sau in ra gì?
int day = 2;switch (day) { case 1: System.out.println("Một"); case 2: System.out.println("Hai"); case 3: System.out.println("Ba"); break; default: System.out.println("Khác");}Đáp án: A
Không có break ở case 2, nên sau khi khớp case 2 và in “Hai”, luồng thực thi “rơi xuyên” (fall through) tiếp vào case 3, in “Ba”, rồi mới gặp break và dừng lại.
Câu 197. Phát biểu nào đúng khi phân biệt overloading và overriding?
Đáp án: C
Overloading (nạp chồng) xảy ra trong cùng một lớp, khác danh sách tham số, được giải quyết lúc biên dịch. Overriding (ghi đè) xảy ra khi lớp con định nghĩa lại phương thức của lớp cha với cùng chữ ký, được giải quyết lúc chạy chương trình (dynamic dispatch) - ngược với mô tả ở phương án B.
Câu 198. Đoạn code sau có vấn đề gì?
final int MAX = 100;MAX = 200;Đáp án: D
Biến khai báo final chỉ được gán giá trị một lần. Cố gán lại giá trị khác sẽ gây lỗi biên dịch.
Câu 199. Đoạn code sau xảy ra điều gì?
Object obj = "hello";Integer number = (Integer) obj;Đáp án: B
obj thực chất đang tham chiếu tới một String, không phải Integer. Ép kiểu (cast) sai loại đối tượng như vậy biên dịch được (vì Object có thể là bất kỳ kiểu nào) nhưng ném ClassCastException lúc chạy chương trình.
Câu 200. Phát biểu nào sau đây về Java là đúng?
Đáp án: A
Java là ngôn ngữ định kiểu tĩnh: kiểu của mỗi biến được khai báo tường minh và kiểm tra ngay khi biên dịch, giúp phát hiện nhiều lỗi sớm trước khi chương trình chạy.