-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathquestions.json
More file actions
3044 lines (3044 loc) · 384 KB
/
Copy pathquestions.json
File metadata and controls
3044 lines (3044 loc) · 384 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
[
{
"num": 1,
"numStr": "01",
"question": "JDK, JRE, JVM khác nhau thế nào?",
"answerHtml": "<table class=\"compare-table\">\n <tr><th>Thành phần</th><th>Là gì</th><th>Dùng khi nào</th></tr>\n <tr><td><strong>JVM</strong></td><td>Máy ảo Java, thực thi bytecode (.class)</td><td>Runtime</td></tr>\n <tr><td><strong>JRE</strong></td><td>JVM + thư viện runtime chuẩn (rt.jar...)</td><td>Chỉ cần chạy app</td></tr>\n <tr><td><strong>JDK</strong></td><td>JRE + compiler (javac), debugger, tools</td><td>Phát triển ứng dụng</td></tr>\n </table>\n <div class=\"tip-box\">💡 Quy tắc nhớ: <strong>JDK ⊃ JRE ⊃ JVM</strong>. Trên máy dev cài JDK; server production chỉ cần JRE là đủ.</div>",
"tags": "java oop basics",
"level": "intern",
"section": "Java Core",
"sectionIcon": "☕",
"sectionColor": "#f97316",
"sectionColorClass": "java-color",
"subsection": "OOP & Basics"
},
{
"num": 2,
"numStr": "02",
"question": "Java là pass-by-value hay pass-by-reference?",
"answerHtml": "<p>Java <span class=\"highlight\">luôn luôn là pass-by-value</span>. Tuy nhiên với object, giá trị được pass là <strong>bản sao của reference</strong> (địa chỉ), không phải object gốc.</p>\n <div class=\"code-block\"><span class=\"kw\">void</span> <span class=\"fn\">change</span>(StringBuilder sb) {\n sb.append(<span class=\"st\">\" World\"</span>); <span class=\"cm\">// OK - thay đổi object gốc qua reference</span>\n sb = <span class=\"kw\">new</span> StringBuilder(); <span class=\"cm\">// KHÔNG ảnh hưởng caller - reassign local copy</span>\n}\n\nStringBuilder s = <span class=\"kw\">new</span> StringBuilder(<span class=\"st\">\"Hello\"</span>);\nchange(s);\nSystem.out.println(s); <span class=\"cm\">// \"Hello World\" - append có, nhưng reassign không</span></div>\n <div class=\"tip-box\">💡 Cách nhớ: bạn truyền vào địa chỉ nhà (copy), người nhận có thể vào nhà sửa đồ đạc, nhưng không thể thay đổi địa chỉ trong danh bạ của bạn.</div>",
"tags": "java basics",
"level": "junior",
"section": "Java Core",
"sectionIcon": "☕",
"sectionColor": "#f97316",
"sectionColorClass": "java-color",
"subsection": "OOP & Basics"
},
{
"num": 3,
"numStr": "03",
"question": "4 tính chất OOP trong Java?",
"answerHtml": "<ul>\n <li><strong>Encapsulation (Đóng gói):</strong> Che giấu data bên trong class, chỉ expose qua getter/setter. Tăng bảo mật, kiểm soát truy cập.</li>\n <li><strong>Inheritance (Kế thừa):</strong> Class con kế thừa field/method của class cha. Tái sử dụng code. Java chỉ hỗ trợ đơn kế thừa (<code>extends</code>).</li>\n <li><strong>Polymorphism (Đa hình):</strong> Cùng một method nhưng hành vi khác nhau tuỳ object. Có 2 loại: compile-time (overloading) và runtime (overriding).</li>\n <li><strong>Abstraction (Trừu tượng):</strong> Ẩn chi tiết implement, chỉ show interface. Dùng abstract class hoặc interface.</li>\n </ul>",
"tags": "java oop",
"level": "intern",
"section": "Java Core",
"sectionIcon": "☕",
"sectionColor": "#f97316",
"sectionColorClass": "java-color",
"subsection": "OOP & Basics"
},
{
"num": 4,
"numStr": "04",
"question": "Abstract class vs Interface khác nhau thế nào?",
"answerHtml": "<table class=\"compare-table\">\n <tr><th></th><th>Abstract Class</th><th>Interface</th></tr>\n <tr><td>Constructor</td><td>✅ Có</td><td>❌ Không</td></tr>\n <tr><td>Field</td><td>Mọi loại</td><td>Chỉ public static final</td></tr>\n <tr><td>Method</td><td>Abstract + concrete</td><td>Abstract + default + static (Java 8+)</td></tr>\n <tr><td>Kế thừa</td><td>Chỉ extend 1</td><td>Implement nhiều</td></tr>\n <tr><td>Dùng khi</td><td>Chia sẻ code chung, có quan hệ \"is-a\"</td><td>Định nghĩa contract, \"can-do\"</td></tr>\n </table>\n <div class=\"tip-box\">💡 Ví dụ: <code>Animal</code> (abstract class có method <code>sleep()</code>) vs <code>Flyable</code> (interface - Bird, Plane đều implement được).</div>",
"tags": "java oop",
"level": "junior",
"section": "Java Core",
"sectionIcon": "☕",
"sectionColor": "#f97316",
"sectionColorClass": "java-color",
"subsection": "OOP & Basics"
},
{
"num": 5,
"numStr": "05",
"question": "== vs .equals() khác nhau thế nào?",
"answerHtml": "<p><code>==</code> so sánh <strong>địa chỉ bộ nhớ</strong> (reference). <code>.equals()</code> so sánh <strong>nội dung giá trị</strong> (nếu được override).</p>\n <div class=\"code-block\">String a = <span class=\"kw\">new</span> String(<span class=\"st\">\"hello\"</span>);\nString b = <span class=\"kw\">new</span> String(<span class=\"st\">\"hello\"</span>);\n\nSystem.out.println(a == b); <span class=\"cm\">// false - khác địa chỉ</span>\nSystem.out.println(a.equals(b)); <span class=\"cm\">// true - cùng nội dung</span>\n\nString c = <span class=\"st\">\"hello\"</span>;\nString d = <span class=\"st\">\"hello\"</span>;\nSystem.out.println(c == d); <span class=\"cm\">// true - cùng String Pool</span></div>\n <div class=\"warn-box\">⚠️ Với Integer: <code>Integer a = 127; Integer b = 127; a == b</code> là <strong>true</strong> (Integer cache -128 đến 127). Nhưng <code>Integer a = 200; Integer b = 200; a == b</code> là <strong>false</strong>!</div>",
"tags": "java basics",
"level": "intern",
"section": "Java Core",
"sectionIcon": "☕",
"sectionColor": "#f97316",
"sectionColorClass": "java-color",
"subsection": "OOP & Basics"
},
{
"num": 6,
"numStr": "06",
"question": "String, StringBuilder, StringBuffer khác nhau thế nào?",
"answerHtml": "<table class=\"compare-table\">\n <tr><th></th><th>String</th><th>StringBuilder</th><th>StringBuffer</th></tr>\n <tr><td>Mutable</td><td>❌ Immutable</td><td>✅</td><td>✅</td></tr>\n <tr><td>Thread-safe</td><td>✅ (immutable)</td><td>❌</td><td>✅ (synchronized)</td></tr>\n <tr><td>Hiệu năng</td><td>Chậm khi nối nhiều</td><td>Nhanh nhất</td><td>Chậm hơn Builder</td></tr>\n </table>\n <p><strong>Khi nào dùng:</strong></p>\n <ul>\n <li>String: giá trị không đổi, key trong HashMap</li>\n <li>StringBuilder: nối chuỗi trong loop, single-thread</li>\n <li>StringBuffer: multi-thread (hiếm dùng, thường dùng StringBuilder + sync riêng)</li>\n </ul>\n <div class=\"code-block\"><span class=\"cm\">// BAD - tạo nhiều String object</span>\nString s = <span class=\"st\">\"\"</span>;\n<span class=\"kw\">for</span> (<span class=\"kw\">int</span> i = <span class=\"num\">0</span>; i < <span class=\"num\">1000</span>; i++) s += i;\n\n<span class=\"cm\">// GOOD</span>\nStringBuilder sb = <span class=\"kw\">new</span> StringBuilder();\n<span class=\"kw\">for</span> (<span class=\"kw\">int</span> i = <span class=\"num\">0</span>; i < <span class=\"num\">1000</span>; i++) sb.append(i);</div>",
"tags": "java basics",
"level": "intern",
"section": "Java Core",
"sectionIcon": "☕",
"sectionColor": "#f97316",
"sectionColorClass": "java-color",
"subsection": "OOP & Basics"
},
{
"num": 7,
"numStr": "07",
"question": "final, finally, finalize khác nhau thế nào?",
"answerHtml": "<ul>\n <li><code>final</code> — <strong>keyword</strong>: biến không thể gán lại, method không thể override, class không thể extend.</li>\n <li><code>finally</code> — <strong>block</strong>: luôn chạy sau try-catch, dùng để giải phóng resource (đóng connection, file...).</li>\n <li><code>finalize()</code> — <strong>method</strong>: GC gọi trước khi thu hồi object. <span class=\"warn\">Deprecated Java 9+</span>, không nên dùng — không đảm bảo khi nào được gọi.</li>\n </ul>\n <div class=\"code-block\"><span class=\"kw\">final int</span> MAX = <span class=\"num\">100</span>; <span class=\"cm\">// không thể thay đổi</span>\n\n<span class=\"kw\">try</span> {\n connection.execute();\n} <span class=\"kw\">catch</span> (Exception e) {\n log.error(e);\n} <span class=\"kw\">finally</span> {\n connection.close(); <span class=\"cm\">// luôn chạy dù có exception hay không</span>\n}</div>",
"tags": "java basics",
"level": "intern",
"section": "Java Core",
"sectionIcon": "☕",
"sectionColor": "#f97316",
"sectionColorClass": "java-color",
"subsection": "OOP & Basics"
},
{
"num": 8,
"numStr": "08",
"question": "static keyword dùng để làm gì?",
"answerHtml": "<p><code>static</code> nghĩa là thuộc về <strong>class</strong>, không phải instance cụ thể. Dùng chung cho tất cả object.</p>\n <ul>\n <li><strong>Static field:</strong> Biến chia sẻ giữa tất cả instance (đếm số lượng object)</li>\n <li><strong>Static method:</strong> Gọi qua tên class, không cần tạo object (<code>Math.abs()</code>)</li>\n <li><strong>Static block:</strong> Chạy một lần khi class được load — dùng để init</li>\n <li><strong>Static nested class:</strong> Inner class không cần instance của outer class</li>\n </ul>\n <div class=\"code-block\"><span class=\"kw\">class</span> <span class=\"cl\">Counter</span> {\n <span class=\"kw\">static int</span> count = <span class=\"num\">0</span>; <span class=\"cm\">// chia sẻ cho tất cả object</span>\n <span class=\"cl\">Counter</span>() { count++; }\n\n <span class=\"kw\">static int</span> <span class=\"fn\">getCount</span>() { <span class=\"cm\">// gọi qua Counter.getCount()</span>\n <span class=\"kw\">return</span> count;\n }\n}</div>",
"tags": "java basics",
"level": "intern",
"section": "Java Core",
"sectionIcon": "☕",
"sectionColor": "#f97316",
"sectionColorClass": "java-color",
"subsection": "OOP & Basics"
},
{
"num": 9,
"numStr": "09",
"question": "Overloading vs Overriding khác nhau thế nào?",
"answerHtml": "<table class=\"compare-table\">\n <tr><th></th><th>Overloading</th><th>Overriding</th></tr>\n <tr><td>Xảy ra ở đâu</td><td>Cùng một class</td><td>Subclass với superclass</td></tr>\n <tr><td>Tham số</td><td>Khác nhau (số lượng/kiểu)</td><td>Phải giống hệt</td></tr>\n <tr><td>Return type</td><td>Có thể khác</td><td>Phải giống (hoặc covariant)</td></tr>\n <tr><td>Quyết định lúc nào</td><td>Compile-time</td><td>Runtime</td></tr>\n <tr><td>Gọi là</td><td>Static polymorphism</td><td>Dynamic polymorphism</td></tr>\n </table>\n <div class=\"code-block\"><span class=\"cm\">// Overloading</span>\n<span class=\"kw\">int</span> <span class=\"fn\">add</span>(<span class=\"kw\">int</span> a, <span class=\"kw\">int</span> b) { <span class=\"kw\">return</span> a+b; }\n<span class=\"kw\">double</span> <span class=\"fn\">add</span>(<span class=\"kw\">double</span> a, <span class=\"kw\">double</span> b) { <span class=\"kw\">return</span> a+b; }\n\n<span class=\"cm\">// Overriding</span>\n<span class=\"kw\">class</span> <span class=\"cl\">Animal</span> { String <span class=\"fn\">sound</span>() { <span class=\"kw\">return</span> <span class=\"st\">\"...\"</span>; } }\n<span class=\"kw\">class</span> <span class=\"cl\">Dog</span> <span class=\"kw\">extends</span> <span class=\"cl\">Animal</span> {\n <span class=\"an\">@Override</span>\n String <span class=\"fn\">sound</span>() { <span class=\"kw\">return</span> <span class=\"st\">\"Woof\"</span>; } <span class=\"cm\">// quyết định lúc runtime</span>\n}</div>",
"tags": "java oop",
"level": "junior",
"section": "Java Core",
"sectionIcon": "☕",
"sectionColor": "#f97316",
"sectionColorClass": "java-color",
"subsection": "OOP & Basics"
},
{
"num": 10,
"numStr": "10",
"question": "Constructor có thể được override không?",
"answerHtml": "<p><span class=\"highlight\">Không thể override constructor</span>. Constructor không được kế thừa — subclass không kế thừa constructor của superclass, nên không có gì để override.</p>\n <p>Tuy nhiên, constructor <strong>có thể overload</strong> (nhiều constructor khác tham số trong cùng 1 class).</p>\n <p>Subclass có thể <strong>gọi constructor cha</strong> bằng <code>super()</code> — nhưng đó là gọi, không phải override.</p>\n <div class=\"code-block\"><span class=\"kw\">class</span> <span class=\"cl\">Animal</span> {\n <span class=\"cl\">Animal</span>(String name) { ... }\n}\n<span class=\"kw\">class</span> <span class=\"cl\">Dog</span> <span class=\"kw\">extends</span> <span class=\"cl\">Animal</span> {\n <span class=\"cl\">Dog</span>(String name) {\n <span class=\"kw\">super</span>(name); <span class=\"cm\">// gọi constructor cha, không phải override</span>\n }\n}</div>",
"tags": "java oop",
"level": "intern",
"section": "Java Core",
"sectionIcon": "☕",
"sectionColor": "#f97316",
"sectionColorClass": "java-color",
"subsection": "OOP & Basics"
},
{
"num": 11,
"numStr": "11",
"question": "ArrayList vs LinkedList khác nhau thế nào?",
"answerHtml": "<table class=\"compare-table\">\n <tr><th>Thao tác</th><th>ArrayList</th><th>LinkedList</th></tr>\n <tr><td>Truy cập theo index (get)</td><td>O(1) ⚡</td><td>O(n) 🐢</td></tr>\n <tr><td>Thêm/xóa ở đầu/giữa</td><td>O(n) 🐢</td><td>O(1) ⚡</td></tr>\n <tr><td>Thêm ở cuối</td><td>O(1) amortized</td><td>O(1)</td></tr>\n <tr><td>Bộ nhớ</td><td>Ít hơn</td><td>Nhiều hơn (lưu node + 2 pointer)</td></tr>\n </table>\n <div class=\"tip-box\">💡 <strong>Thực tế:</strong> Hầu hết dùng ArrayList vì access theo index nhiều hơn insert/delete. Dùng LinkedList khi cần Queue/Deque hoặc insert/delete đầu list thường xuyên.</div>",
"tags": "java collections",
"level": "junior",
"section": "Java Core",
"sectionIcon": "☕",
"sectionColor": "#f97316",
"sectionColorClass": "java-color",
"subsection": "Collections & Generics"
},
{
"num": 12,
"numStr": "12",
"question": "HashMap hoạt động như thế nào?",
"answerHtml": "<p>HashMap dùng <strong>hashing</strong>: khi put(key, value), Java tính <code>hash(key)</code> → xác định vị trí (bucket index) trong mảng nội bộ.</p>\n <ul>\n <li><strong>Collision:</strong> Nếu 2 key có cùng bucket → lưu thành chain (LinkedList). Từ Java 8, nếu chain dài ≥ 8 → chuyển sang TreeNode (O(log n)).</li>\n <li><strong>Load factor:</strong> Mặc định 0.75. Khi fill > 75% capacity → resize (double size, rehash tất cả).</li>\n <li><strong>Độ phức tạp:</strong> get/put trung bình O(1), tệ nhất O(log n).</li>\n </ul>\n <div class=\"code-block\"><span class=\"cm\">// Khi put(\"name\", \"John\"):</span>\n<span class=\"num\">1</span>. hash = <span class=\"st\">\"name\"</span>.hashCode() <span class=\"cm\">// → tính hash</span>\n<span class=\"num\">2</span>. index = hash & (capacity - <span class=\"num\">1</span>) <span class=\"cm\">// → tìm bucket</span>\n<span class=\"num\">3</span>. Nếu bucket trống → lưu vào\n<span class=\"num\">4</span>. Nếu đã có key giống → update value\n<span class=\"num\">5</span>. Nếu collision → thêm vào chain</div>\n <div class=\"warn-box\">⚠️ HashMap không đảm bảo thứ tự. Dùng <strong>LinkedHashMap</strong> nếu cần giữ insertion order, <strong>TreeMap</strong> nếu cần sorted order.</div>",
"tags": "java collections",
"level": "middle",
"section": "Java Core",
"sectionIcon": "☕",
"sectionColor": "#f97316",
"sectionColorClass": "java-color",
"subsection": "Collections & Generics"
},
{
"num": 13,
"numStr": "13",
"question": "HashMap vs HashTable khác nhau thế nào?",
"answerHtml": "<table class=\"compare-table\">\n <tr><th></th><th>HashMap</th><th>HashTable</th></tr>\n <tr><td>Thread-safe</td><td>❌</td><td>✅ (synchronized toàn bộ method)</td></tr>\n <tr><td>Null key/value</td><td>✅ 1 null key, nhiều null value</td><td>❌</td></tr>\n <tr><td>Hiệu năng</td><td>Nhanh hơn</td><td>Chậm hơn (lock toàn bộ)</td></tr>\n <tr><td>Iterator</td><td>fail-fast</td><td>Enumerator (cũ hơn)</td></tr>\n </table>\n <div class=\"tip-box\">💡 Trong thực tế: <strong>không dùng HashTable nữa</strong>. Cần thread-safe thì dùng <code>ConcurrentHashMap</code> — hiệu năng tốt hơn nhiều.</div>",
"tags": "java collections",
"level": "junior",
"section": "Java Core",
"sectionIcon": "☕",
"sectionColor": "#f97316",
"sectionColorClass": "java-color",
"subsection": "Collections & Generics"
},
{
"num": 14,
"numStr": "14",
"question": "HashMap vs ConcurrentHashMap khác nhau thế nào?",
"answerHtml": "<p><strong>ConcurrentHashMap</strong> thread-safe nhưng <span class=\"green\">hiệu năng tốt hơn HashTable</span> vì không lock toàn bộ map.</p>\n <ul>\n <li>Java 7: chia thành nhiều <strong>Segment</strong>, mỗi segment có lock riêng → nhiều thread read/write song song trên segment khác nhau.</li>\n <li>Java 8+: dùng <strong>CAS (Compare-And-Swap)</strong> + synchronized chỉ trên từng bucket khi cần — ít blocking hơn nhiều.</li>\n <li>Không cho phép <strong>null key/value</strong> (HashMap cho phép 1 null key).</li>\n </ul>\n <div class=\"tip-box\">💡 Rule of thumb: single-thread → HashMap; multi-thread → ConcurrentHashMap.</div>",
"tags": "java collections thread",
"level": "middle",
"section": "Java Core",
"sectionIcon": "☕",
"sectionColor": "#f97316",
"sectionColorClass": "java-color",
"subsection": "Collections & Generics"
},
{
"num": 15,
"numStr": "15",
"question": "HashSet hoạt động như thế nào?",
"answerHtml": "<p>HashSet thực chất là <strong>HashMap bên trong</strong>: element được lưu làm <em>key</em>, value là một dummy object <code>PRESENT</code>.</p>\n <p>Tính duy nhất đảm bảo bởi: <code>hashCode()</code> + <code>equals()</code>. Nếu 2 object có cùng hashCode VÀ equals trả về true → được coi là trùng → không thêm vào.</p>\n <div class=\"code-block\"><span class=\"cm\">// Khi add(\"hello\"):</span>\nmap.put(<span class=\"st\">\"hello\"</span>, PRESENT); <span class=\"cm\">// PRESENT = new Object()</span>\n\n<span class=\"cm\">// Nếu \"hello\" đã tồn tại → put chỉ update value (PRESENT lại)</span>\n<span class=\"cm\">// → HashSet báo là đã có, không thêm</span></div>\n <div class=\"warn-box\">⚠️ Phải override cả <strong>hashCode()</strong> và <strong>equals()</strong> nếu dùng custom object trong HashSet/HashMap!</div>",
"tags": "java collections",
"level": "junior",
"section": "Java Core",
"sectionIcon": "☕",
"sectionColor": "#f97316",
"sectionColorClass": "java-color",
"subsection": "Collections & Generics"
},
{
"num": 16,
"numStr": "16",
"question": "equals() và hashCode() contract là gì?",
"answerHtml": "<p>Java quy định <strong>contract bắt buộc</strong>:</p>\n <ul>\n <li>Nếu <code>a.equals(b) == true</code> → <code>a.hashCode() == b.hashCode()</code> <span class=\"highlight\">BẮT BUỘC</span></li>\n <li>Nếu <code>a.hashCode() == b.hashCode()</code> → chưa chắc <code>a.equals(b)</code> (collision bình thường)</li>\n </ul>\n <div class=\"warn-box\">⚠️ Vi phạm contract này khiến HashMap/HashSet hoạt động sai: 2 object \"bằng nhau\" nhưng lại nằm ở 2 bucket khác nhau → tìm không ra.</div>\n <div class=\"code-block\"><span class=\"cm\">// Ví dụ SAI - chỉ override equals, quên hashCode</span>\n<span class=\"kw\">class</span> <span class=\"cl\">User</span> {\n String name;\n <span class=\"an\">@Override</span>\n <span class=\"kw\">boolean</span> <span class=\"fn\">equals</span>(Object o) { <span class=\"kw\">return</span> name.equals(((User)o).name); }\n <span class=\"cm\">// ❌ không override hashCode → HashMap hoạt động sai!</span>\n}</div>",
"tags": "java collections",
"level": "middle",
"section": "Java Core",
"sectionIcon": "☕",
"sectionColor": "#f97316",
"sectionColorClass": "java-color",
"subsection": "Collections & Generics"
},
{
"num": 17,
"numStr": "17",
"question": "Comparable vs Comparator khác nhau thế nào?",
"answerHtml": "<table class=\"compare-table\">\n <tr><th></th><th>Comparable</th><th>Comparator</th></tr>\n <tr><td>Package</td><td>java.lang</td><td>java.util</td></tr>\n <tr><td>Method</td><td>compareTo(T o)</td><td>compare(T o1, T o2)</td></tr>\n <tr><td>Định nghĩa ở đâu</td><td>Trong class cần so sánh</td><td>Bên ngoài class</td></tr>\n <tr><td>Số cách sắp xếp</td><td>1 (natural order)</td><td>Nhiều (linh hoạt)</td></tr>\n </table>\n <div class=\"code-block\"><span class=\"cm\">// Comparable - class tự định nghĩa cách sort</span>\n<span class=\"kw\">class</span> <span class=\"cl\">Student</span> <span class=\"kw\">implements</span> <span class=\"cl\">Comparable</span><<span class=\"cl\">Student</span>> {\n <span class=\"kw\">public int</span> <span class=\"fn\">compareTo</span>(<span class=\"cl\">Student</span> o) { <span class=\"kw\">return</span> <span class=\"kw\">this</span>.gpa - o.gpa; }\n}\n\n<span class=\"cm\">// Comparator - định nghĩa ngoài, linh hoạt</span>\nstudents.sort(Comparator.comparing(<span class=\"cl\">Student</span>::getName));\nstudents.sort(Comparator.comparingDouble(<span class=\"cl\">Student</span>::getGpa).reversed());</div>",
"tags": "java collections",
"level": "junior",
"section": "Java Core",
"sectionIcon": "☕",
"sectionColor": "#f97316",
"sectionColorClass": "java-color",
"subsection": "Collections & Generics"
},
{
"num": 18,
"numStr": "18",
"question": "List, Set, Map khác nhau thế nào?",
"answerHtml": "<table class=\"compare-table\">\n <tr><th>Interface</th><th>Thứ tự</th><th>Duplicate</th><th>Ví dụ</th></tr>\n <tr><td><strong>List</strong></td><td>✅ Có (insertion order)</td><td>✅ Cho phép</td><td>ArrayList, LinkedList</td></tr>\n <tr><td><strong>Set</strong></td><td>❌ (trừ Linked/Tree)</td><td>❌ Không cho phép</td><td>HashSet, TreeSet</td></tr>\n <tr><td><strong>Map</strong></td><td>Tuỳ impl</td><td>Key không, Value có</td><td>HashMap, TreeMap</td></tr>\n </table>",
"tags": "java collections",
"level": "intern",
"section": "Java Core",
"sectionIcon": "☕",
"sectionColor": "#f97316",
"sectionColorClass": "java-color",
"subsection": "Collections & Generics"
},
{
"num": 19,
"numStr": "19",
"question": "Iterator vs ListIterator khác nhau thế nào?",
"answerHtml": "<table class=\"compare-table\">\n <tr><th></th><th>Iterator</th><th>ListIterator</th></tr>\n <tr><td>Dùng cho</td><td>Mọi Collection</td><td>Chỉ List</td></tr>\n <tr><td>Hướng duyệt</td><td>Một chiều (forward)</td><td>Hai chiều (forward + backward)</td></tr>\n <tr><td>Thêm element</td><td>❌</td><td>✅ (add())</td></tr>\n <tr><td>Lấy index</td><td>❌</td><td>✅ (nextIndex(), previousIndex())</td></tr>\n </table>",
"tags": "java collections",
"level": "middle",
"section": "Java Core",
"sectionIcon": "☕",
"sectionColor": "#f97316",
"sectionColorClass": "java-color",
"subsection": "Collections & Generics"
},
{
"num": 20,
"numStr": "20",
"question": "fail-fast vs fail-safe iterator là gì?",
"answerHtml": "<ul>\n <li><span class=\"highlight\">fail-fast:</span> Ném <code>ConcurrentModificationException</code> ngay lập tức nếu collection bị sửa đổi trong khi đang duyệt. Dùng biến <code>modCount</code> để phát hiện. Ví dụ: ArrayList, HashMap iterator.</li>\n <li><span class=\"green\">fail-safe:</span> Duyệt trên <strong>bản sao (snapshot)</strong> của collection → không ảnh hưởng bởi thay đổi. Không throw exception nhưng có thể không phản ánh thay đổi mới nhất. Ví dụ: CopyOnWriteArrayList, ConcurrentHashMap.</li>\n </ul>\n <div class=\"code-block\"><span class=\"cm\">// fail-fast - sẽ throw ConcurrentModificationException</span>\nList<String> list = <span class=\"kw\">new</span> ArrayList<>(Arrays.asList(<span class=\"st\">\"a\"</span>,<span class=\"st\">\"b\"</span>,<span class=\"st\">\"c\"</span>));\n<span class=\"kw\">for</span> (String s : list) {\n <span class=\"kw\">if</span> (s.equals(<span class=\"st\">\"b\"</span>)) list.remove(s); <span class=\"cm\">// ❌ Exception!</span>\n}\n\n<span class=\"cm\">// Cách đúng: dùng iterator.remove()</span>\nIterator<String> it = list.iterator();\n<span class=\"kw\">while</span> (it.hasNext()) {\n <span class=\"kw\">if</span> (it.next().equals(<span class=\"st\">\"b\"</span>)) it.remove(); <span class=\"cm\">// ✅ OK</span>\n}</div>",
"tags": "java collections thread",
"level": "middle",
"section": "Java Core",
"sectionIcon": "☕",
"sectionColor": "#f97316",
"sectionColorClass": "java-color",
"subsection": "Collections & Generics"
},
{
"num": 21,
"numStr": "21",
"question": "Checked vs Unchecked Exception khác nhau thế nào?",
"answerHtml": "<table class=\"compare-table\">\n <tr><th></th><th>Checked Exception</th><th>Unchecked Exception</th></tr>\n <tr><td>Extends</td><td>Exception (trừ RuntimeException)</td><td>RuntimeException</td></tr>\n <tr><td>Bắt buộc xử lý</td><td>✅ (try-catch hoặc throws)</td><td>❌</td></tr>\n <tr><td>Xảy ra khi</td><td>Lỗi ngoài tầm kiểm soát (IO, network, DB)</td><td>Lỗi lập trình (null, out of bounds)</td></tr>\n <tr><td>Ví dụ</td><td>IOException, SQLException</td><td>NullPointerException, IllegalArgumentException</td></tr>\n </table>\n <div class=\"tip-box\">💡 Triết lý: Checked = <em>\"Tôi biết điều này có thể xảy ra, hãy xử lý\"</em>. Unchecked = <em>\"Code bạn có bug\"</em>. Spring khuyến khích dùng Unchecked (RuntimeException) để tránh boilerplate.</div>",
"tags": "java exception",
"level": "junior",
"section": "Java Core",
"sectionIcon": "☕",
"sectionColor": "#f97316",
"sectionColorClass": "java-color",
"subsection": "Exception Handling"
},
{
"num": 22,
"numStr": "22",
"question": "Error vs Exception khác nhau thế nào?",
"answerHtml": "<p>Cả hai đều extends <code>Throwable</code>, nhưng:</p>\n <ul>\n <li><strong>Error:</strong> Lỗi <span class=\"highlight\">nghiêm trọng từ JVM/system</span>, thường không thể recover. Ví dụ: <code>OutOfMemoryError</code>, <code>StackOverflowError</code>. Không nên catch (và thường không thể handle được).</li>\n <li><strong>Exception:</strong> Lỗi <span class=\"green\">có thể dự đoán và xử lý</span> được trong ứng dụng. Nên catch và handle phù hợp.</li>\n </ul>\n <div class=\"code-block\">Throwable\n├── Error (không nên catch)\n│ ├── OutOfMemoryError\n│ └── StackOverflowError\n└── Exception (nên handle)\n ├── IOException (checked)\n └── RuntimeException (unchecked)\n ├── NullPointerException\n └── IllegalArgumentException</div>",
"tags": "java exception",
"level": "junior",
"section": "Java Core",
"sectionIcon": "☕",
"sectionColor": "#f97316",
"sectionColorClass": "java-color",
"subsection": "Exception Handling"
},
{
"num": 23,
"numStr": "23",
"question": "try-with-resources là gì?",
"answerHtml": "<p>Cú pháp Java 7+ tự động gọi <code>close()</code> trên resource sau khi dùng xong, dù có exception hay không. Resource phải implement <code>AutoCloseable</code>.</p>\n <div class=\"code-block\"><span class=\"cm\">// Cách cũ - dễ quên close(), rò rỉ resource</span>\nBufferedReader br = <span class=\"kw\">null</span>;\n<span class=\"kw\">try</span> {\n br = <span class=\"kw\">new</span> BufferedReader(<span class=\"kw\">new</span> FileReader(<span class=\"st\">\"file.txt\"</span>));\n <span class=\"kw\">return</span> br.readLine();\n} <span class=\"kw\">finally</span> {\n <span class=\"kw\">if</span> (br != <span class=\"kw\">null</span>) br.close();\n}\n\n<span class=\"cm\">// try-with-resources - gọn hơn, an toàn hơn</span>\n<span class=\"kw\">try</span> (BufferedReader br = <span class=\"kw\">new</span> BufferedReader(<span class=\"kw\">new</span> FileReader(<span class=\"st\">\"file.txt\"</span>))) {\n <span class=\"kw\">return</span> br.readLine();\n} <span class=\"cm\">// br.close() tự động gọi ở đây</span></div>",
"tags": "java exception",
"level": "middle",
"section": "Java Core",
"sectionIcon": "☕",
"sectionColor": "#f97316",
"sectionColorClass": "java-color",
"subsection": "Exception Handling"
},
{
"num": 24,
"numStr": "24",
"question": "finally block có luôn chạy không?",
"answerHtml": "<p><strong>Gần như luôn luôn</strong>. Nhưng có 3 trường hợp ngoại lệ mà finally KHÔNG chạy:</p>\n <ul>\n <li><code>System.exit()</code> được gọi trong try/catch</li>\n <li>JVM crash (OutOfMemoryError, kill process)</li>\n <li>Thread bị kill đột ngột (<code>Thread.stop()</code> - deprecated)</li>\n </ul>\n <div class=\"code-block\"><span class=\"kw\">try</span> {\n <span class=\"kw\">return</span> <span class=\"num\">1</span>; <span class=\"cm\">// return trong try vẫn chạy finally trước</span>\n} <span class=\"kw\">finally</span> {\n System.out.println(<span class=\"st\">\"Luôn chạy!\"</span>); <span class=\"cm\">// Chạy trước khi return</span>\n <span class=\"cm\">// Nếu return ở đây → override giá trị return từ try!</span>\n}</div>",
"tags": "java exception",
"level": "junior",
"section": "Java Core",
"sectionIcon": "☕",
"sectionColor": "#f97316",
"sectionColorClass": "java-color",
"subsection": "Exception Handling"
},
{
"num": 25,
"numStr": "25",
"question": "Custom Exception tạo như thế nào?",
"answerHtml": "<div class=\"code-block\"><span class=\"cm\">// Checked Exception</span>\n<span class=\"kw\">public class</span> <span class=\"cl\">InsufficientFundsException</span> <span class=\"kw\">extends</span> <span class=\"cl\">Exception</span> {\n <span class=\"kw\">private final double</span> amount;\n \n <span class=\"kw\">public</span> <span class=\"fn\">InsufficientFundsException</span>(<span class=\"kw\">double</span> amount) {\n <span class=\"kw\">super</span>(<span class=\"st\">\"Insufficient funds: \"</span> + amount);\n <span class=\"kw\">this</span>.amount = amount;\n }\n \n <span class=\"kw\">public double</span> <span class=\"fn\">getAmount</span>() { <span class=\"kw\">return</span> amount; }\n}\n\n<span class=\"cm\">// Unchecked Exception (phổ biến hơn trong Spring)</span>\n<span class=\"kw\">public class</span> <span class=\"cl\">UserNotFoundException</span> <span class=\"kw\">extends</span> <span class=\"cl\">RuntimeException</span> {\n <span class=\"kw\">public</span> <span class=\"fn\">UserNotFoundException</span>(Long id) {\n <span class=\"kw\">super</span>(<span class=\"st\">\"User not found with id: \"</span> + id);\n }\n}</div>",
"tags": "java exception",
"level": "middle",
"section": "Java Core",
"sectionIcon": "☕",
"sectionColor": "#f97316",
"sectionColorClass": "java-color",
"subsection": "Exception Handling"
},
{
"num": 26,
"numStr": "26",
"question": "Thread vs Runnable khác nhau thế nào?",
"answerHtml": "<table class=\"compare-table\">\n <tr><th></th><th>extends Thread</th><th>implements Runnable</th></tr>\n <tr><td>Kế thừa class khác</td><td>❌ (đã dùng 1 slot extend)</td><td>✅ Tự do</td></tr>\n <tr><td>Tách logic/thread</td><td>❌ Gộp chung</td><td>✅ Tách biệt rõ ràng</td></tr>\n <tr><td>Tái sử dụng task</td><td>❌</td><td>✅ Dùng với ThreadPool</td></tr>\n </table>\n <div class=\"code-block\"><span class=\"cm\">// Cách khuyến khích - implements Runnable</span>\n<span class=\"cl\">Runnable</span> task = () -> System.out.println(<span class=\"st\">\"Running in: \"</span> + Thread.currentThread().getName());\n<span class=\"kw\">new</span> Thread(task).start();\n\n<span class=\"cm\">// Dùng với ThreadPool</span>\nExecutorService pool = Executors.newFixedThreadPool(<span class=\"num\">4</span>);\npool.submit(task);</div>",
"tags": "java thread",
"level": "junior",
"section": "Java Core",
"sectionIcon": "☕",
"sectionColor": "#f97316",
"sectionColorClass": "java-color",
"subsection": "Multithreading & Concurrency"
},
{
"num": 27,
"numStr": "27",
"question": "synchronized keyword dùng để làm gì?",
"answerHtml": "<p><code>synchronized</code> đảm bảo <strong>chỉ 1 thread</strong> được vào block/method tại một thời điểm, tránh race condition. Thread khác phải chờ (blocked).</p>\n <ul>\n <li><strong>synchronized method:</strong> Lock trên <code>this</code> (instance)</li>\n <li><strong>static synchronized method:</strong> Lock trên <code>Class</code> object</li>\n <li><strong>synchronized block:</strong> Lock trên object chỉ định, phạm vi hẹp hơn → ít blocking hơn</li>\n </ul>\n <div class=\"code-block\"><span class=\"cm\">// synchronized method</span>\n<span class=\"kw\">public synchronized void</span> <span class=\"fn\">increment</span>() { count++; }\n\n<span class=\"cm\">// synchronized block - tốt hơn vì chỉ lock khi cần</span>\n<span class=\"kw\">public void</span> <span class=\"fn\">increment</span>() {\n doSomethingWithoutLock(); <span class=\"cm\">// Không cần lock - chạy song song</span>\n <span class=\"kw\">synchronized</span> (<span class=\"kw\">this</span>) {\n count++; <span class=\"cm\">// Chỉ lock phần cần thiết</span>\n }\n}</div>",
"tags": "java thread",
"level": "middle",
"section": "Java Core",
"sectionIcon": "☕",
"sectionColor": "#f97316",
"sectionColorClass": "java-color",
"subsection": "Multithreading & Concurrency"
},
{
"num": 28,
"numStr": "28",
"question": "volatile keyword dùng để làm gì?",
"answerHtml": "<p><code>volatile</code> đảm bảo biến được đọc/ghi trực tiếp từ <strong>main memory</strong>, không bị cache trong CPU register của từng thread.</p>\n <p>Giải quyết <strong>visibility problem</strong>: Thread A thay đổi biến nhưng Thread B vẫn thấy giá trị cũ từ cache.</p>\n <div class=\"code-block\"><span class=\"kw\">class</span> <span class=\"cl\">StopThread</span> {\n <span class=\"kw\">private volatile boolean</span> running = <span class=\"kw\">true</span>; <span class=\"cm\">// không có volatile, thread có thể không thấy thay đổi</span>\n \n <span class=\"kw\">void</span> <span class=\"fn\">run</span>() {\n <span class=\"kw\">while</span> (running) { doWork(); } <span class=\"cm\">// đọc từ main memory mỗi lần</span>\n }\n \n <span class=\"kw\">void</span> <span class=\"fn\">stop</span>() { running = <span class=\"kw\">false</span>; } <span class=\"cm\">// ghi vào main memory ngay</span>\n}</div>\n <div class=\"warn-box\">⚠️ volatile <strong>KHÔNG</strong> đảm bảo atomicity! <code>count++</code> gồm 3 bước (read, increment, write) — vẫn cần synchronized hoặc AtomicInteger.</div>",
"tags": "java thread",
"level": "middle",
"section": "Java Core",
"sectionIcon": "☕",
"sectionColor": "#f97316",
"sectionColorClass": "java-color",
"subsection": "Multithreading & Concurrency"
},
{
"num": 29,
"numStr": "29",
"question": "wait(), notify(), notifyAll() dùng để làm gì?",
"answerHtml": "<p>Dùng trong <code>synchronized</code> block để điều phối các thread chờ nhau (Producer-Consumer pattern):</p>\n <ul>\n <li><code>wait()</code>: Thread <strong>giải phóng lock</strong> và đi ngủ, chờ được đánh thức</li>\n <li><code>notify()</code>: Đánh thức <strong>1 thread ngẫu nhiên</strong> đang wait trên cùng object</li>\n <li><code>notifyAll()</code>: Đánh thức <strong>tất cả</strong> thread đang wait → các thread cạnh tranh lại lock</li>\n </ul>\n <div class=\"code-block\"><span class=\"cm\">// Producer-Consumer đơn giản</span>\n<span class=\"kw\">synchronized</span> (queue) {\n <span class=\"kw\">while</span> (queue.isEmpty()) {\n queue.wait(); <span class=\"cm\">// giải phóng lock, chờ có data</span>\n }\n process(queue.poll());\n}\n\n<span class=\"cm\">// Khi Producer thêm data:</span>\n<span class=\"kw\">synchronized</span> (queue) {\n queue.add(item);\n queue.notifyAll(); <span class=\"cm\">// đánh thức consumer</span>\n}</div>\n <div class=\"tip-box\">💡 Thực tế dùng <code>BlockingQueue</code> (LinkedBlockingQueue, ArrayBlockingQueue) thay vì tự implement — đơn giản và an toàn hơn.</div>",
"tags": "java thread",
"level": "middle",
"section": "Java Core",
"sectionIcon": "☕",
"sectionColor": "#f97316",
"sectionColorClass": "java-color",
"subsection": "Multithreading & Concurrency"
},
{
"num": 30,
"numStr": "30",
"question": "Deadlock là gì? Cách tránh?",
"answerHtml": "<p>Deadlock xảy ra khi 2+ thread <strong>chờ nhau giải phóng lock</strong> vô thời hạn.</p>\n <div class=\"code-block\"><span class=\"cm\">// Thread 1: lock A → chờ B</span>\n<span class=\"cm\">// Thread 2: lock B → chờ A → DEADLOCK!</span></div>\n <p><strong>Cách tránh Deadlock:</strong></p>\n <ul>\n <li>✅ <strong>Thứ tự lock nhất quán:</strong> Luôn lock A trước B, không bao giờ ngược lại</li>\n <li>✅ <strong>tryLock với timeout:</strong> <code>lock.tryLock(1, TimeUnit.SECONDS)</code> — nếu không được thì bỏ qua</li>\n <li>✅ <strong>Giảm phạm vi lock:</strong> Chỉ lock khi thực sự cần, release sớm nhất có thể</li>\n <li>✅ <strong>Dùng concurrent collections:</strong> ConcurrentHashMap, BlockingQueue... thay vì tự lock</li>\n </ul>",
"tags": "java thread",
"level": "middle",
"section": "Java Core",
"sectionIcon": "☕",
"sectionColor": "#f97316",
"sectionColorClass": "java-color",
"subsection": "Multithreading & Concurrency"
},
{
"num": 31,
"numStr": "31",
"question": "ThreadPool và ExecutorService là gì?",
"answerHtml": "<p><strong>ThreadPool</strong> là nhóm thread được tạo sẵn và tái sử dụng — tránh chi phí tạo/hủy thread liên tục.</p>\n <p><strong>ExecutorService</strong> là interface quản lý ThreadPool: submit task, lấy kết quả, shutdown.</p>\n <div class=\"code-block\">ExecutorService pool = Executors.newFixedThreadPool(<span class=\"num\">4</span>);\n\n<span class=\"cm\">// Submit Runnable (không cần kết quả)</span>\npool.execute(() -> processTask());\n\n<span class=\"cm\">// Submit Callable (cần kết quả)</span>\nFuture<String> future = pool.submit(() -> fetchData());\nString result = future.get(); <span class=\"cm\">// block cho đến khi có kết quả</span>\n\npool.shutdown(); <span class=\"cm\">// dừng nhận task mới, chờ task hiện tại xong</span></div>\n <table class=\"compare-table\">\n <tr><th>Factory method</th><th>Dùng khi</th></tr>\n <tr><td>newFixedThreadPool(n)</td><td>Số lượng task nhiều, giới hạn tài nguyên</td></tr>\n <tr><td>newCachedThreadPool()</td><td>Nhiều task ngắn, số lượng thay đổi</td></tr>\n <tr><td>newSingleThreadExecutor()</td><td>Task cần chạy tuần tự</td></tr>\n <tr><td>newScheduledThreadPool(n)</td><td>Task định kỳ</td></tr>\n </table>",
"tags": "java thread",
"level": "middle",
"section": "Java Core",
"sectionIcon": "☕",
"sectionColor": "#f97316",
"sectionColorClass": "java-color",
"subsection": "Multithreading & Concurrency"
},
{
"num": 32,
"numStr": "32",
"question": "Callable vs Runnable khác nhau thế nào?",
"answerHtml": "<table class=\"compare-table\">\n <tr><th></th><th>Runnable</th><th>Callable<V></th></tr>\n <tr><td>Return value</td><td>void</td><td>V (generic type)</td></tr>\n <tr><td>Checked Exception</td><td>❌ Không throw được</td><td>✅ Có thể throw</td></tr>\n <tr><td>Dùng với</td><td>execute(), Thread</td><td>submit() → Future<V></td></tr>\n </table>\n <div class=\"code-block\"><span class=\"cl\">Callable</span><Integer> task = () -> {\n <span class=\"cm\">// có thể throw checked exception</span>\n <span class=\"kw\">return</span> computeHeavyTask(); <span class=\"cm\">// trả về kết quả</span>\n};\n\nFuture<Integer> future = pool.submit(task);\nInteger result = future.get(); <span class=\"cm\">// block đợi kết quả</span>\nInteger result2 = future.get(<span class=\"num\">5</span>, TimeUnit.SECONDS); <span class=\"cm\">// timeout</span></div>",
"tags": "java thread",
"level": "middle",
"section": "Java Core",
"sectionIcon": "☕",
"sectionColor": "#f97316",
"sectionColorClass": "java-color",
"subsection": "Multithreading & Concurrency"
},
{
"num": 33,
"numStr": "33",
"question": "synchronized vs ReentrantLock khác nhau thế nào?",
"answerHtml": "<table class=\"compare-table\">\n <tr><th></th><th>synchronized</th><th>ReentrantLock</th></tr>\n <tr><td>Tự động release</td><td>✅</td><td>❌ (phải gọi unlock())</td></tr>\n <tr><td>tryLock(timeout)</td><td>❌</td><td>✅</td></tr>\n <tr><td>Interruptible lock</td><td>❌</td><td>✅ lockInterruptibly()</td></tr>\n <tr><td>Fairness</td><td>❌</td><td>✅ new ReentrantLock(true)</td></tr>\n <tr><td>Nhiều Condition</td><td>❌</td><td>✅ newCondition()</td></tr>\n </table>\n <div class=\"code-block\">ReentrantLock lock = <span class=\"kw\">new</span> ReentrantLock();\n<span class=\"kw\">try</span> {\n <span class=\"kw\">if</span> (lock.tryLock(<span class=\"num\">1</span>, TimeUnit.SECONDS)) {\n <span class=\"kw\">try</span> { doWork(); }\n <span class=\"kw\">finally</span> { lock.unlock(); } <span class=\"cm\">// PHẢI gọi trong finally!</span>\n }\n} <span class=\"kw\">catch</span> (InterruptedException e) { ... }</div>\n <div class=\"tip-box\">💡 Dùng synchronized khi đủ đơn giản. Dùng ReentrantLock khi cần timeout, interruptible, fairness hoặc multiple conditions.</div>",
"tags": "java thread",
"level": "senior",
"section": "Java Core",
"sectionIcon": "☕",
"sectionColor": "#f97316",
"sectionColorClass": "java-color",
"subsection": "Multithreading & Concurrency"
},
{
"num": 34,
"numStr": "34",
"question": "Atomic classes là gì?",
"answerHtml": "<p>Các class trong <code>java.util.concurrent.atomic</code> thực hiện thao tác <strong>thread-safe không cần synchronized</strong>, dùng <strong>CAS (Compare-And-Swap)</strong> ở CPU level — nhanh hơn synchronized.</p>\n <div class=\"code-block\"><span class=\"cm\">// Không thread-safe</span>\n<span class=\"kw\">int</span> count = <span class=\"num\">0</span>;\ncount++; <span class=\"cm\">// 3 bước: read, increment, write → race condition</span>\n\n<span class=\"cm\">// Thread-safe với AtomicInteger</span>\nAtomicInteger count = <span class=\"kw\">new</span> AtomicInteger(<span class=\"num\">0</span>);\ncount.incrementAndGet(); <span class=\"cm\">// atomic, không cần synchronized</span>\ncount.compareAndSet(<span class=\"num\">5</span>, <span class=\"num\">10</span>); <span class=\"cm\">// chỉ set 10 nếu hiện tại là 5</span></div>\n <p><strong>Các class phổ biến:</strong> AtomicInteger, AtomicLong, AtomicBoolean, AtomicReference, LongAdder (hiệu năng cao hơn trong high-contention).</p>",
"tags": "java thread",
"level": "middle",
"section": "Java Core",
"sectionIcon": "☕",
"sectionColor": "#f97316",
"sectionColorClass": "java-color",
"subsection": "Multithreading & Concurrency"
},
{
"num": 136,
"numStr": "136",
"question": "CompletableFuture là gì? Dùng thế nào?",
"answerHtml": "<p><code>CompletableFuture</code> (Java 8+) cho phép lập trình <strong>bất đồng bộ (async)</strong> và <strong>kết hợp nhiều task</strong> dễ dàng hơn <code>Future</code>. Không cần block thread để đợi kết quả.</p>\n <table class=\"compare-table\">\n <tr><th>Method</th><th>Dùng để</th></tr>\n <tr><td>thenApply(fn)</td><td>Transform kết quả (giống map trong Stream)</td></tr>\n <tr><td>thenAccept(fn)</td><td>Consume kết quả, không trả về</td></tr>\n <tr><td>thenCompose(fn)</td><td>Chain 2 CompletableFuture (giống flatMap)</td></tr>\n <tr><td>thenCombine(cf, fn)</td><td>Kết hợp 2 future song song</td></tr>\n <tr><td>allOf(...)</td><td>Chờ tất cả future hoàn thành</td></tr>\n <tr><td>exceptionally(fn)</td><td>Xử lý exception (như catch)</td></tr>\n </table>\n <div class=\"code-block\"><span class=\"cm\">// Async gọi 2 API song song, combine kết quả</span>\nCompletableFuture<User> userFuture = CompletableFuture\n .supplyAsync(() -> userService.findById(<span class=\"num\">1L</span>));\n\nCompletableFuture<List<Order>> orderFuture = CompletableFuture\n .supplyAsync(() -> orderService.findByUser(<span class=\"num\">1L</span>));\n\nCompletableFuture<UserProfile> profile = userFuture\n .thenCombine(orderFuture, (user, orders) -> <span class=\"kw\">new</span> UserProfile(user, orders));\n\n<span class=\"cm\">// Chain + error handling</span>\nCompletableFuture.supplyAsync(() -> fetchData())\n .thenApply(data -> process(data))\n .thenApply(result -> save(result))\n .exceptionally(ex -> handleError(ex))\n .thenAccept(System.out::println);</div>\n <div class=\"tip-box\">💡 Mặc định dùng ForkJoinPool.commonPool(). Production nên truyền Executor riêng để kiểm soát số thread và tránh starvation.</div>",
"tags": "java thread java8",
"level": "senior",
"section": "Java Core",
"sectionIcon": "☕",
"sectionColor": "#f97316",
"sectionColorClass": "java-color",
"subsection": "Multithreading & Concurrency"
},
{
"num": 137,
"numStr": "137",
"question": "Thread vs Process khác nhau thế nào?",
"answerHtml": "<table class=\"compare-table\">\n <tr><th></th><th>Process</th><th>Thread</th></tr>\n <tr><td>Bộ nhớ</td><td>Không gian địa chỉ riêng biệt</td><td>Chia sẻ heap với các thread cùng process</td></tr>\n <tr><td>Tạo</td><td>Nặng (fork OS)</td><td>Nhẹ hơn nhiều</td></tr>\n <tr><td>Giao tiếp</td><td>IPC (pipe, socket, shared mem)</td><td>Trực tiếp qua shared memory</td></tr>\n <tr><td>Fault isolation</td><td>✅ Process crash không ảnh hưởng nhau</td><td>❌ Thread crash có thể crash cả process</td></tr>\n <tr><td>Ví dụ</td><td>JVM chạy = 1 process</td><td>Các thread trong ThreadPool</td></tr>\n </table>\n <div class=\"tip-box\">💡 JVM (1 process) có thể chạy nhiều thread. Các microservice khác nhau là các process riêng biệt — lý do chúng fault-isolate nhau.</div>",
"tags": "java thread",
"level": "junior",
"section": "Java Core",
"sectionIcon": "☕",
"sectionColor": "#f97316",
"sectionColorClass": "java-color",
"subsection": "Multithreading & Concurrency"
},
{
"num": 138,
"numStr": "138",
"question": "Livelock là gì? Khác Deadlock thế nào?",
"answerHtml": "<table class=\"compare-table\">\n <tr><th></th><th>Deadlock</th><th>Livelock</th></tr>\n <tr><td>Thread state</td><td>BLOCKED (dừng chờ)</td><td>RUNNING (đang chạy, nhưng vô ích)</td></tr>\n <tr><td>Tiến triển</td><td>Không có</td><td>Không có (dù thread vẫn active)</td></tr>\n <tr><td>CPU</td><td>Thấp (không làm gì)</td><td>Cao (busy loop)</td></tr>\n <tr><td>Phát hiện</td><td>Thread dump: BLOCKED state</td><td>Khó hơn, CPU cao nhưng không progress</td></tr>\n </table>\n <div class=\"code-block\"><span class=\"cm\">// Livelock: 2 người nhường nhau mãi (đi lại không thoát)</span>\n<span class=\"kw\">while</span> (!done) {\n <span class=\"kw\">if</span> (other.isMovingLeft()) {\n moveRight(); <span class=\"cm\">// tránh bên phải</span>\n } <span class=\"kw\">else</span> {\n moveLeft(); <span class=\"cm\">// nhưng other cũng tránh → lặp mãi</span>\n }\n}</div>\n <div class=\"tip-box\">💡 Cách fix Livelock: thêm randomized backoff (chờ ngẫu nhiên trước khi retry) để phá vỡ sự đồng bộ giữa các thread.</div>",
"tags": "java thread",
"level": "senior",
"section": "Java Core",
"sectionIcon": "☕",
"sectionColor": "#f97316",
"sectionColorClass": "java-color",
"subsection": "Multithreading & Concurrency"
},
{
"num": 139,
"numStr": "139",
"question": "Race Condition là gì? Cách phòng tránh?",
"answerHtml": "<p>Race Condition xảy ra khi 2+ thread cùng truy cập <strong>shared resource</strong> mà không có đồng bộ hoá → kết quả phụ thuộc vào thứ tự thực hiện (không đoán trước được).</p>\n <div class=\"code-block\"><span class=\"cm\">// ❌ Race condition: 2 thread cùng đọc-ghi count</span>\n<span class=\"kw\">int</span> count = <span class=\"num\">0</span>;\n<span class=\"cm\">// Thread A: read count=5, Thread B: read count=5</span>\n<span class=\"cm\">// Thread A: write count=6, Thread B: write count=6 ← mất 1 lần increment!</span>\n\n<span class=\"cm\">// ✅ Fix 1: synchronized</span>\n<span class=\"kw\">synchronized void</span> increment() { count++; }\n\n<span class=\"cm\">// ✅ Fix 2: AtomicInteger (tốt hơn - dùng CAS)</span>\nAtomicInteger count = <span class=\"kw\">new</span> AtomicInteger(<span class=\"num\">0</span>);\ncount.incrementAndGet();\n\n<span class=\"cm\">// ✅ Fix 3: dùng concurrent collection</span>\nConcurrentHashMap, CopyOnWriteArrayList...</div>\n <div class=\"warn-box\">⚠️ Race condition rất khó reproduce (chỉ xuất hiện trong điều kiện specific). Luôn design thread-safe từ đầu thay vì debug sau.</div>",
"tags": "java thread",
"level": "middle",
"section": "Java Core",
"sectionIcon": "☕",
"sectionColor": "#f97316",
"sectionColorClass": "java-color",
"subsection": "Multithreading & Concurrency"
},
{
"num": 140,
"numStr": "140",
"question": "Debug Deadlock trong production bằng cách nào?",
"answerHtml": "<p><strong>Khi app bị \"treo\" hoặc response time tăng đột biến</strong>, có thể là deadlock. Quy trình xử lý:</p>\n <div class=\"code-block\"><span class=\"cm\"># Bước 1: Lấy thread dump - tìm BLOCKED threads</span>\njstack <PID> <span class=\"cm\"># lấy thread dump từ process</span>\nkill -3 <PID> <span class=\"cm\"># hoặc signal SIGQUIT</span>\n\n<span class=\"cm\"># Bước 2: Tìm trong output</span>\n\"Found one Java-level deadlock:\" <span class=\"cm\">← JVM tự detect!</span>\n\n<span class=\"cm\"> Thread-1: waiting to lock <0x1234> (held by Thread-2)</span>\n<span class=\"cm\"> Thread-2: waiting to lock <0x5678> (held by Thread-1)</span>\n\n<span class=\"cm\"># Bước 3: Với Spring Boot Actuator</span>\nGET /actuator/threaddump <span class=\"cm\"># xem thread state qua HTTP</span></div>\n <p><strong>Công cụ khác:</strong></p>\n <ul>\n <li><strong>VisualVM / JConsole:</strong> GUI để xem thread state và detect deadlock</li>\n <li><strong>Async Profiler:</strong> Low-overhead profiling trong production</li>\n <li><strong>APM tools:</strong> Datadog, New Relic tự alert khi phát hiện deadlock</li>\n </ul>\n <div class=\"tip-box\">💡 Prevention > Debug: dùng timeout lock (<code>tryLock(1s)</code>), nhất quán thứ tự acquire lock, tránh nested locks.</div>",
"tags": "java thread",
"level": "senior",
"section": "Java Core",
"sectionIcon": "☕",
"sectionColor": "#f97316",
"sectionColorClass": "java-color",
"subsection": "Multithreading & Concurrency"
},
{
"num": 35,
"numStr": "35",
"question": "Lambda Expression là gì?",
"answerHtml": "<p>Lambda là cú pháp ngắn gọn để implement <strong>Functional Interface</strong> (interface có đúng 1 abstract method), thay thế anonymous class dài dòng.</p>\n <p><strong>Cú pháp:</strong> <code>(params) -> { body }</code></p>\n <div class=\"code-block\"><span class=\"cm\">// Trước Java 8 - dài dòng</span>\nRunnable r = <span class=\"kw\">new</span> Runnable() {\n <span class=\"an\">@Override</span>\n <span class=\"kw\">public void</span> <span class=\"fn\">run</span>() { System.out.println(<span class=\"st\">\"Hello\"</span>); }\n};\n\n<span class=\"cm\">// Lambda - gọn hơn rất nhiều</span>\nRunnable r = () -> System.out.println(<span class=\"st\">\"Hello\"</span>);\n\n<span class=\"cm\">// Với tham số</span>\nComparator<String> c = (a, b) -> a.compareTo(b);\nlist.sort((a, b) -> a.length() - b.length());</div>",
"tags": "java java8",
"level": "junior",
"section": "Java Core",
"sectionIcon": "☕",
"sectionColor": "#f97316",
"sectionColorClass": "java-color",
"subsection": "Java 8+ Features"
},
{
"num": 36,
"numStr": "36",
"question": "Functional Interface là gì?",
"answerHtml": "<p>Interface có <strong>đúng 1 abstract method</strong>. Dùng <code>@FunctionalInterface</code> để compiler kiểm tra. Là nền tảng cho Lambda và Stream API.</p>\n <table class=\"compare-table\">\n <tr><th>Interface</th><th>Method</th><th>Dùng cho</th></tr>\n <tr><td>Predicate<T></td><td>test(T) → boolean</td><td>Điều kiện lọc</td></tr>\n <tr><td>Function<T,R></td><td>apply(T) → R</td><td>Chuyển đổi kiểu</td></tr>\n <tr><td>Consumer<T></td><td>accept(T) → void</td><td>Xử lý không trả về</td></tr>\n <tr><td>Supplier<T></td><td>get() → T</td><td>Tạo/cung cấp giá trị</td></tr>\n <tr><td>BiFunction<T,U,R></td><td>apply(T,U) → R</td><td>Function 2 input</td></tr>\n </table>",
"tags": "java java8",
"level": "junior",
"section": "Java Core",
"sectionIcon": "☕",
"sectionColor": "#f97316",
"sectionColorClass": "java-color",
"subsection": "Java 8+ Features"
},
{
"num": 37,
"numStr": "37",
"question": "Stream API là gì?",
"answerHtml": "<p>API xử lý collection theo phong cách <strong>functional/declarative</strong>: filter, transform, aggregate... Lazy evaluation (chỉ tính khi có terminal operation), hỗ trợ parallel.</p>\n <p><strong>2 loại operation:</strong></p>\n <ul>\n <li><strong>Intermediate</strong> (lazy, trả về Stream): filter, map, sorted, distinct, limit, skip</li>\n <li><strong>Terminal</strong> (trigger execution, trả về kết quả): collect, forEach, count, reduce, findFirst</li>\n </ul>\n <div class=\"code-block\">List<String> names = employees.stream()\n .filter(e -> e.getSalary() > <span class=\"num\">5000</span>) <span class=\"cm\">// intermediate</span>\n .map(Employee::getName) <span class=\"cm\">// intermediate</span>\n .sorted() <span class=\"cm\">// intermediate</span>\n .collect(Collectors.toList()); <span class=\"cm\">// terminal - pipeline chạy ở đây</span>\n\n<span class=\"cm\">// Parallel stream - xử lý song song</span>\n<span class=\"kw\">long</span> count = list.parallelStream()\n .filter(s -> s.startsWith(<span class=\"st\">\"A\"</span>))\n .count();</div>",
"tags": "java java8",
"level": "middle",
"section": "Java Core",
"sectionIcon": "☕",
"sectionColor": "#f97316",
"sectionColorClass": "java-color",
"subsection": "Java 8+ Features"
},
{
"num": 38,
"numStr": "38",
"question": "Optional là gì? Tại sao dùng?",
"answerHtml": "<p>Optional là <strong>container có thể chứa hoặc không chứa giá trị</strong>, thay thế <code>null</code>. Buộc lập trình viên xử lý trường hợp không có giá trị một cách rõ ràng → tránh NullPointerException.</p>\n <div class=\"code-block\"><span class=\"cm\">// Trước Optional - dễ quên check null</span>\nUser user = userRepo.findById(id);\nSystem.out.println(user.getName()); <span class=\"cm\">// NPE nếu user = null!</span>\n\n<span class=\"cm\">// Với Optional</span>\nOptional<User> optional = userRepo.findById(id);\n\noptional.isPresent(); <span class=\"cm\">// check có value không</span>\noptional.get(); <span class=\"cm\">// lấy value (throws nếu empty)</span>\noptional.orElse(<span class=\"kw\">new</span> User(<span class=\"st\">\"default\"</span>)); <span class=\"cm\">// default nếu empty</span>\noptional.orElseThrow(() -> <span class=\"kw\">new</span> RuntimeException()); \noptional.map(User::getName).orElse(<span class=\"st\">\"Unknown\"</span>); <span class=\"cm\">// chain an toàn</span></div>\n <div class=\"warn-box\">⚠️ Không dùng Optional làm field trong Entity hoặc method parameter. Chỉ dùng làm return type.</div>",
"tags": "java java8",
"level": "middle",
"section": "Java Core",
"sectionIcon": "☕",
"sectionColor": "#f97316",
"sectionColorClass": "java-color",
"subsection": "Java 8+ Features"
},
{
"num": 39,
"numStr": "39",
"question": "Method Reference là gì?",
"answerHtml": "<p>Cú pháp ngắn hơn lambda khi lambda chỉ gọi một method có sẵn: <code>ClassName::methodName</code></p>\n <table class=\"compare-table\">\n <tr><th>Loại</th><th>Cú pháp</th><th>Tương đương lambda</th></tr>\n <tr><td>Static method</td><td>Integer::parseInt</td><td>s -> Integer.parseInt(s)</td></tr>\n <tr><td>Instance method (object)</td><td>str::toUpperCase</td><td>() -> str.toUpperCase()</td></tr>\n <tr><td>Instance method (class)</td><td>String::toLowerCase</td><td>s -> s.toLowerCase()</td></tr>\n <tr><td>Constructor</td><td>User::new</td><td>() -> new User()</td></tr>\n </table>\n <div class=\"code-block\">list.stream().map(String::toUpperCase).forEach(System.out::println);\n<span class=\"cm\">// thay vì: .map(s -> s.toUpperCase()).forEach(s -> System.out.println(s))</span></div>",
"tags": "java java8",
"level": "junior",
"section": "Java Core",
"sectionIcon": "☕",
"sectionColor": "#f97316",
"sectionColorClass": "java-color",
"subsection": "Java 8+ Features"
},
{
"num": 40,
"numStr": "40",
"question": "default method trong Interface là gì?",
"answerHtml": "<p>Java 8 cho phép interface có method với <strong>implementation sẵn</strong> (default method). Mục đích chính: thêm tính năng mới vào interface mà không break các class đã implement.</p>\n <div class=\"code-block\"><span class=\"kw\">interface</span> <span class=\"cl\">Collection</span><E> {\n <span class=\"cm\">// Trước Java 8: thêm method mới → tất cả impl phải update!</span>\n \n <span class=\"cm\">// Java 8: default method - có implementation sẵn</span>\n <span class=\"kw\">default void</span> <span class=\"fn\">forEach</span>(Consumer<E> action) {\n <span class=\"kw\">for</span> (E e : <span class=\"kw\">this</span>) action.accept(e);\n }\n}\n<span class=\"cm\">// ArrayList, LinkedList... không cần thay đổi gì → backward compatible</span></div>\n <div class=\"warn-box\">⚠️ Nếu class implement 2 interface có cùng default method → compile error! Phải override để resolve.</div>",
"tags": "java java8",
"level": "middle",
"section": "Java Core",
"sectionIcon": "☕",
"sectionColor": "#f97316",
"sectionColorClass": "java-color",
"subsection": "Java 8+ Features"
},
{
"num": 41,
"numStr": "41",
"question": "Heap vs Stack trong JVM?",
"answerHtml": "<table class=\"compare-table\">\n <tr><th></th><th>Stack</th><th>Heap</th></tr>\n <tr><td>Lưu gì</td><td>Stack frame, local variables, references</td><td>Objects, arrays</td></tr>\n <tr><td>Per thread</td><td>✅ Mỗi thread 1 stack riêng</td><td>❌ Chia sẻ tất cả thread</td></tr>\n <tr><td>Kích thước</td><td>Nhỏ (~512KB-1MB)</td><td>Lớn (theo -Xmx config)</td></tr>\n <tr><td>Tốc độ</td><td>Rất nhanh (LIFO)</td><td>Chậm hơn</td></tr>\n <tr><td>Quản lý</td><td>Tự động (pop khi method return)</td><td>GC thu hồi</td></tr>\n <tr><td>Lỗi</td><td>StackOverflowError</td><td>OutOfMemoryError</td></tr>\n </table>\n <div class=\"code-block\"><span class=\"kw\">void</span> <span class=\"fn\">method</span>() {\n <span class=\"kw\">int</span> x = <span class=\"num\">5</span>; <span class=\"cm\">// x lưu trong Stack</span>\n String s = <span class=\"st\">\"hi\"</span>; <span class=\"cm\">// reference s trong Stack, object \"hi\" trong Heap</span>\n User u = <span class=\"kw\">new</span> User(); <span class=\"cm\">// reference u trong Stack, User object trong Heap</span>\n}</div>",
"tags": "java jvm",
"level": "middle",
"section": "Java Core",
"sectionIcon": "☕",
"sectionColor": "#f97316",
"sectionColorClass": "java-color",
"subsection": "Memory & JVM"
},
{
"num": 42,
"numStr": "42",
"question": "Garbage Collection hoạt động như thế nào?",
"answerHtml": "<p>GC tự động thu hồi object trong Heap không còn được tham chiếu, dùng <strong>Generational GC</strong>:</p>\n <div class=\"code-block\">Heap\n├── Young Generation\n│ ├── Eden Space ← object mới tạo tại đây\n│ ├── Survivor S0 ← sống sót sau Minor GC\n│ └── Survivor S1\n├── Old Generation ← object sống lâu được promote\n└── Metaspace ← class metadata (Java 8+)</div>\n <ul>\n <li><strong>Minor GC:</strong> Dọn Young Generation, nhanh (~ms). Object sống sót được chuyển sang Survivor.</li>\n <li><strong>Major/Full GC:</strong> Dọn Old Generation, chậm hơn → Stop-The-World pause.</li>\n <li><strong>Thuật toán:</strong> G1GC (default Java 9+), ZGC (Java 15+, pause <1ms), Shenandoah.</li>\n </ul>",
"tags": "java jvm",
"level": "middle",
"section": "Java Core",
"sectionIcon": "☕",
"sectionColor": "#f97316",
"sectionColorClass": "java-color",
"subsection": "Memory & JVM"
},
{
"num": 43,
"numStr": "43",
"question": "String Pool là gì?",
"answerHtml": "<p>Vùng nhớ đặc biệt trong Heap (Metaspace Java 7+) lưu <strong>String literals</strong>. Các String có cùng nội dung sẽ dùng chung 1 reference → tiết kiệm bộ nhớ.</p>\n <div class=\"code-block\">String a = <span class=\"st\">\"hello\"</span>; <span class=\"cm\">// Tạo trong String Pool</span>\nString b = <span class=\"st\">\"hello\"</span>; <span class=\"cm\">// Trỏ đến cùng object trong Pool</span>\nSystem.out.println(a == b); <span class=\"cm\">// true - cùng reference từ pool</span>\n\nString c = <span class=\"kw\">new</span> String(<span class=\"st\">\"hello\"</span>); <span class=\"cm\">// Tạo mới trong Heap, ngoài pool</span>\nSystem.out.println(a == c); <span class=\"cm\">// false</span>\nSystem.out.println(a == c.intern()); <span class=\"cm\">// true - intern() lấy từ pool</span></div>",
"tags": "java jvm basics",
"level": "junior",
"section": "Java Core",
"sectionIcon": "☕",
"sectionColor": "#f97316",
"sectionColorClass": "java-color",
"subsection": "Memory & JVM"
},
{
"num": 44,
"numStr": "44",
"question": "Strong, Weak, Soft, Phantom Reference khác nhau thế nào?",
"answerHtml": "<table class=\"compare-table\">\n <tr><th>Loại</th><th>GC thu hồi khi nào</th><th>Use case</th></tr>\n <tr><td>Strong</td><td>Khi không còn reference</td><td>Mặc định mọi object</td></tr>\n <tr><td>Soft</td><td>Chỉ khi sắp OutOfMemory</td><td>Memory-sensitive cache</td></tr>\n <tr><td>Weak</td><td>Ngay khi GC chạy, dù còn memory</td><td>WeakHashMap, canonical mapping</td></tr>\n <tr><td>Phantom</td><td>Sau khi finalize, trước khi thu hồi</td><td>Cleanup action, off-heap resources</td></tr>\n </table>",
"tags": "java jvm",
"level": "senior",
"section": "Java Core",
"sectionIcon": "☕",
"sectionColor": "#f97316",
"sectionColorClass": "java-color",
"subsection": "Memory & JVM"
},
{
"num": 45,
"numStr": "45",
"question": "ClassLoader là gì?",
"answerHtml": "<p>ClassLoader load file <code>.class</code> vào JVM. Dùng mô hình <strong>delegation</strong>: trước khi tự load, uỷ thác cho parent.</p>\n <div class=\"code-block\">Bootstrap ClassLoader <span class=\"cm\">← load java.lang, java.util...</span>\n ↑ delegate\nExtension ClassLoader <span class=\"cm\">← load thư viện trong ext/</span>\n ↑ delegate\nApplication ClassLoader <span class=\"cm\">← load classpath app</span>\n ↑ delegate\nCustom ClassLoader <span class=\"cm\">← load từ DB, network, encrypted jar...</span></div>\n <div class=\"tip-box\">💡 Trong Spring Boot: có thêm ClassLoader riêng để load nested JARs trong fat JAR. Đây là lý do cần <code>spring-boot-loader</code>.</div>",
"tags": "java jvm",
"level": "senior",
"section": "Java Core",
"sectionIcon": "☕",
"sectionColor": "#f97316",
"sectionColorClass": "java-color",
"subsection": "Memory & JVM"
},
{
"num": 141,
"numStr": "141",
"question": "JIT Compiler là gì? Tại sao JVM khởi động chậm nhưng sau đó nhanh?",
"answerHtml": "<p><strong>JIT (Just-In-Time) Compiler</strong> biên dịch bytecode thành <strong>native machine code</strong> tại runtime — chỉ với những method được gọi nhiều lần (<em>hot spots</em>). Đây là lý do Java nhanh sau khi \"warm up\".</p>\n <div class=\"code-block\">JVM lifecycle:\n1. Load .class → bytecode (interpreted mode) ← CHẬM ban đầu\n2. JIT phát hiện \"hot method\" (gọi nhiều lần)\n3. JIT compile hot method → native code + cache\n4. Lần sau gọi → chạy native code trực tiếp ← NHANH\n\nThreshold mặc định: ~10,000 lần gọi = hot method</div>\n <ul>\n <li><strong>C1 Compiler (Client):</strong> Compile nhanh, ít optimize — cho startup nhanh</li>\n <li><strong>C2 Compiler (Server):</strong> Compile chậm hơn nhưng optimize sâu hơn — performance đỉnh</li>\n <li><strong>Tiered Compilation (default Java 8+):</strong> Dùng C1 trước → sau đó C2 cho hot spots</li>\n </ul>\n <div class=\"tip-box\">💡 Đây là lý do khi load test Spring Boot app: 5 phút đầu chậm hơn, sau đó \"warm up\" xong và throughput tăng đáng kể.</div>",
"tags": "java jvm",
"level": "senior",
"section": "Java Core",
"sectionIcon": "☕",
"sectionColor": "#f97316",
"sectionColorClass": "java-color",
"subsection": "Memory & JVM"
},
{
"num": 142,
"numStr": "142",
"question": "JVM Tuning — các JVM flags quan trọng là gì?",
"answerHtml": "<div class=\"code-block\"><span class=\"cm\"># Memory sizing</span>\n-Xms512m <span class=\"cm\"># Initial heap size (tránh resize liên tục)</span>\n-Xmx2g <span class=\"cm\"># Max heap size</span>\n-Xss512k <span class=\"cm\"># Stack size mỗi thread</span>\n-XX:MetaspaceSize=256m <span class=\"cm\"># Initial Metaspace</span>\n\n<span class=\"cm\"># GC Collector</span>\n-XX:+UseG1GC <span class=\"cm\"># G1GC (default Java 9+) - balanced</span>\n-XX:+UseZGC <span class=\"cm\"># ZGC (Java 15+) - ultra-low pause (<1ms)</span>\n-XX:MaxGCPauseMillis=200 <span class=\"cm\"># G1: target pause time</span>\n\n<span class=\"cm\"># GC Logging (để debug GC issues)</span>\n-Xlog:gc*:file=/logs/gc.log:time,uptime:filecount=5,filesize=20m\n\n<span class=\"cm\"># Heap dump khi OOM</span>\n-XX:+HeapDumpOnOutOfMemoryError\n-XX:HeapDumpPath=/dumps/heap.hprof\n\n<span class=\"cm\"># Spring Boot production recommended</span>\njava -Xms512m -Xmx1g -XX:+UseG1GC -XX:+HeapDumpOnOutOfMemoryError \\\n -jar app.jar</div>\n <table class=\"compare-table\">\n <tr><th>Vấn đề</th><th>Dấu hiệu</th><th>Tuning</th></tr>\n <tr><td>High GC time</td><td>CPU spike định kỳ</td><td>Tăng heap, dùng G1GC</td></tr>\n <tr><td>OOM Heap</td><td>OutOfMemoryError</td><td>Tăng -Xmx, tìm memory leak</td></tr>\n <tr><td>High latency</td><td>GC pause lớn</td><td>Dùng ZGC/Shenandoah</td></tr>\n <tr><td>Slow startup</td><td>Khởi động lâu</td><td>CDS, GraalVM native image</td></tr>\n </table>",
"tags": "java jvm",
"level": "senior",
"section": "Java Core",
"sectionIcon": "☕",
"sectionColor": "#f97316",
"sectionColorClass": "java-color",
"subsection": "Memory & JVM"
},
{
"num": 46,
"numStr": "46",
"question": "Singleton Pattern là gì? Implement thread-safe?",
"answerHtml": "<p>Đảm bảo một class <strong>chỉ có duy nhất 1 instance</strong> trong toàn bộ ứng dụng.</p>\n <div class=\"code-block\"><span class=\"cm\">// Cách 1: Eager initialization - đơn giản, thread-safe</span>\n<span class=\"kw\">public class</span> <span class=\"cl\">Config</span> {\n <span class=\"kw\">private static final</span> <span class=\"cl\">Config</span> INSTANCE = <span class=\"kw\">new</span> <span class=\"cl\">Config</span>();\n <span class=\"kw\">private</span> <span class=\"fn\">Config</span>() {}\n <span class=\"kw\">public static</span> <span class=\"cl\">Config</span> <span class=\"fn\">getInstance</span>() { <span class=\"kw\">return</span> INSTANCE; }\n}\n\n<span class=\"cm\">// Cách 2: Enum Singleton - best practice, safe với serialization</span>\n<span class=\"kw\">public enum</span> <span class=\"cl\">Database</span> {\n INSTANCE;\n <span class=\"kw\">public void</span> <span class=\"fn\">connect</span>() { ... }\n}\n\n<span class=\"cm\">// Cách 3: Double-checked locking (Lazy + thread-safe)</span>\n<span class=\"kw\">private static volatile</span> <span class=\"cl\">Config</span> instance;\n<span class=\"kw\">public static</span> <span class=\"cl\">Config</span> <span class=\"fn\">getInstance</span>() {\n <span class=\"kw\">if</span> (instance == <span class=\"kw\">null</span>) {\n <span class=\"kw\">synchronized</span> (<span class=\"cl\">Config</span>.<span class=\"kw\">class</span>) {\n <span class=\"kw\">if</span> (instance == <span class=\"kw\">null</span>) instance = <span class=\"kw\">new</span> <span class=\"cl\">Config</span>();\n }\n }\n <span class=\"kw\">return</span> instance;\n}</div>",
"tags": "java pattern",
"level": "middle",
"section": "Java Core",
"sectionIcon": "☕",
"sectionColor": "#f97316",
"sectionColorClass": "java-color",
"subsection": "Design Patterns & Misc"
},
{
"num": 47,
"numStr": "47",
"question": "Immutable class là gì? Tạo như thế nào?",
"answerHtml": "<p>Immutable class là class mà <strong>state không thể thay đổi</strong> sau khi tạo. Ví dụ có sẵn: String, Integer, LocalDate.</p>\n <p><strong>5 quy tắc tạo Immutable class:</strong></p>\n <ul>\n <li>Khai báo class là <code>final</code></li>\n <li>Tất cả field là <code>private final</code></li>\n <li>Không có setter</li>\n <li>Khởi tạo qua constructor</li>\n <li>Nếu field là mutable object (List, Date) → trả về <strong>defensive copy</strong></li>\n </ul>\n <div class=\"code-block\"><span class=\"kw\">public final class</span> <span class=\"cl\">Money</span> {\n <span class=\"kw\">private final double</span> amount;\n <span class=\"kw\">private final</span> String currency;\n <span class=\"kw\">private final</span> List<String> tags;\n\n <span class=\"kw\">public</span> <span class=\"fn\">Money</span>(<span class=\"kw\">double</span> amount, String currency, List<String> tags) {\n <span class=\"kw\">this</span>.amount = amount;\n <span class=\"kw\">this</span>.currency = currency;\n <span class=\"kw\">this</span>.tags = <span class=\"kw\">new</span> ArrayList<>(tags); <span class=\"cm\">// defensive copy!</span>\n }\n \n <span class=\"kw\">public</span> List<String> <span class=\"fn\">getTags</span>() {\n <span class=\"kw\">return</span> Collections.unmodifiableList(tags); <span class=\"cm\">// trả về view chỉ đọc</span>\n }\n}</div>",
"tags": "java pattern",
"level": "middle",
"section": "Java Core",
"sectionIcon": "☕",
"sectionColor": "#f97316",
"sectionColorClass": "java-color",
"subsection": "Design Patterns & Misc"
},
{
"num": 48,
"numStr": "48",
"question": "Serialization là gì?",
"answerHtml": "<p>Serialization là quá trình <strong>chuyển object thành byte stream</strong> để lưu vào file/DB hoặc truyền qua network. Deserialization là chiều ngược lại.</p>\n <div class=\"code-block\"><span class=\"kw\">class</span> <span class=\"cl\">User</span> <span class=\"kw\">implements</span> Serializable {\n <span class=\"kw\">private static final long</span> serialVersionUID = <span class=\"num\">1L</span>; <span class=\"cm\">// version control</span>\n String name;\n <span class=\"kw\">transient</span> String password; <span class=\"cm\">// transient = không serialize field này</span>\n}\n\n<span class=\"cm\">// Serialize</span>\nObjectOutputStream oos = <span class=\"kw\">new</span> ObjectOutputStream(<span class=\"kw\">new</span> FileOutputStream(<span class=\"st\">\"user.dat\"</span>));\noos.writeObject(user);\n\n<span class=\"cm\">// Deserialize</span>\nObjectInputStream ois = <span class=\"kw\">new</span> ObjectInputStream(<span class=\"kw\">new</span> FileInputStream(<span class=\"st\">\"user.dat\"</span>));\nUser loaded = (User) ois.readObject();</div>\n <div class=\"tip-box\">💡 Trong web API, Jackson serialize object thành JSON, không cần implement Serializable.</div>",
"tags": "java basics",
"level": "middle",
"section": "Java Core",
"sectionIcon": "☕",
"sectionColor": "#f97316",
"sectionColorClass": "java-color",
"subsection": "Design Patterns & Misc"
},
{
"num": 49,
"numStr": "49",
"question": "Java Reflection là gì?",
"answerHtml": "<p>Reflection API cho phép <strong>inspect và thay đổi class/method/field tại runtime</strong> mà không cần biết tên ở compile time. Là nền tảng của Spring, Hibernate, Jackson.</p>\n <div class=\"code-block\">Class<?> clazz = Class.forName(<span class=\"st\">\"com.example.User\"</span>);\n\n<span class=\"cm\">// Xem tất cả method</span>\nMethod[] methods = clazz.getDeclaredMethods();\n\n<span class=\"cm\">// Gọi method private</span>\nMethod m = clazz.getDeclaredMethod(<span class=\"st\">\"getName\"</span>);\nm.setAccessible(<span class=\"kw\">true</span>); <span class=\"cm\">// bypass access control</span>\nString name = (String) m.invoke(userObject);\n\n<span class=\"cm\">// Đọc/ghi field</span>\nField f = clazz.getDeclaredField(<span class=\"st\">\"age\"</span>);\nf.setAccessible(<span class=\"kw\">true</span>);\nf.set(userObject, <span class=\"num\">25</span>);</div>\n <div class=\"warn-box\">⚠️ Reflection chậm hơn (~10x), bỏ qua access control, khó debug. Chỉ dùng trong framework/library, không dùng trong business code thường ngày.</div>",
"tags": "java basics",
"level": "senior",
"section": "Java Core",
"sectionIcon": "☕",
"sectionColor": "#f97316",
"sectionColorClass": "java-color",
"subsection": "Design Patterns & Misc"
},
{
"num": 50,
"numStr": "50",
"question": "try-catch có ảnh hưởng hiệu năng không?",
"answerHtml": "<p><strong>try block bình thường: gần như không có overhead</strong> (JVM tối ưu rất tốt).</p>\n <p>Overhead xảy ra khi <strong>exception thực sự được throw</strong>:</p>\n <ul>\n <li>JVM tạo stack trace → tốn kém O(depth of call stack)</li>\n <li>Tạo Exception object, fill stack frames</li>\n </ul>\n <div class=\"warn-box\">⚠️ Anti-pattern: dùng exception để kiểm soát luồng bình thường (if/else) → rất chậm! Exception nên chỉ dùng cho trường hợp <em>bất thường</em>, không phải flow thông thường.</div>\n <div class=\"code-block\"><span class=\"cm\">// BAD - dùng exception thay if</span>\n<span class=\"kw\">try</span> {\n <span class=\"kw\">int</span> value = Integer.parseInt(str);\n} <span class=\"kw\">catch</span> (NumberFormatException e) {\n value = <span class=\"num\">0</span>; <span class=\"cm\">// chậm nếu str thường xuyên không phải số</span>\n}\n\n<span class=\"cm\">// GOOD</span>\n<span class=\"kw\">int</span> value = str.matches(<span class=\"st\">\"-?\\\\d+\"</span>) ? Integer.parseInt(str) : <span class=\"num\">0</span>;</div>",
"tags": "java basics",
"level": "middle",
"section": "Java Core",
"sectionIcon": "☕",
"sectionColor": "#f97316",
"sectionColorClass": "java-color",
"subsection": "Design Patterns & Misc"
},
{
"num": 51,
"numStr": "51",
"question": "Spring Boot là gì? Khác gì với Spring Framework?",
"answerHtml": "<p><strong>Spring Framework</strong> là framework nền tảng: mạnh mẽ nhưng cần nhiều config XML/Java phức tạp.</p>\n <p><strong>Spring Boot</strong> = Spring Framework + <em>\"convention over configuration\"</em>:</p>\n <ul>\n <li>✅ <strong>Auto-configuration:</strong> Tự detect classpath và cấu hình bean phù hợp</li>\n <li>✅ <strong>Starter dependencies:</strong> Bundle thư viện liên quan vào 1 dependency</li>\n <li>✅ <strong>Embedded server:</strong> Tomcat/Jetty tích hợp sẵn — chạy <code>java -jar</code> là xong</li>\n <li>✅ <strong>Actuator:</strong> Monitoring endpoints sẵn có</li>\n <li>✅ Không cần XML config, không cần deploy WAR</li>\n </ul>",
"tags": "spring core",
"level": "junior",
"section": "Spring Boot",
"sectionIcon": "🌱",
"sectionColor": "#34d399",
"sectionColorClass": "spring-color",
"subsection": "Core Concepts"
},
{
"num": 52,
"numStr": "52",
"question": "@SpringBootApplication gồm những annotation nào?",
"answerHtml": "<p><code>@SpringBootApplication</code> là meta-annotation gộp 3 annotation:</p>\n <ul>\n <li><code>@Configuration</code>: Đánh dấu class là nguồn bean config</li>\n <li><code>@EnableAutoConfiguration</code>: Kích hoạt auto-configuration</li>\n <li><code>@ComponentScan</code>: Tự động scan tìm component trong package hiện tại và sub-package</li>\n </ul>\n <div class=\"code-block\"><span class=\"an\">@SpringBootApplication</span> <span class=\"cm\">// = 3 annotation dưới đây</span>\n<span class=\"cm\">// @Configuration</span>\n<span class=\"cm\">// @EnableAutoConfiguration</span>\n<span class=\"cm\">// @ComponentScan(basePackages = \"com.example\")</span>\n<span class=\"kw\">public class</span> <span class=\"cl\">Application</span> {\n <span class=\"kw\">public static void</span> <span class=\"fn\">main</span>(String[] args) {\n SpringApplication.run(<span class=\"cl\">Application</span>.<span class=\"kw\">class</span>, args);\n }\n}</div>",
"tags": "spring core",
"level": "middle",
"section": "Spring Boot",
"sectionIcon": "🌱",
"sectionColor": "#34d399",
"sectionColorClass": "spring-color",
"subsection": "Core Concepts"
},
{
"num": 53,
"numStr": "53",
"question": "Auto-configuration hoạt động như thế nào?",
"answerHtml": "<p>Khi Spring Boot khởi động, <code>@EnableAutoConfiguration</code> kích hoạt cơ chế scan file cấu hình auto-config, sau đó dùng <code>@Conditional</code> để quyết định có tạo bean hay không.</p>\n <div class=\"code-block\"><span class=\"cm\">// Spring Boot đọc file này (Boot 3.x):</span>\nMETA-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports\n\n<span class=\"cm\">// Mỗi auto-config class có điều kiện:</span>\n<span class=\"an\">@ConditionalOnClass</span>(DataSource.<span class=\"kw\">class</span>) <span class=\"cm\">// có class này trong classpath?</span>\n<span class=\"an\">@ConditionalOnMissingBean</span>(DataSource.<span class=\"kw\">class</span>) <span class=\"cm\">// chưa có bean nào tự định nghĩa?</span>\n<span class=\"an\">@ConditionalOnProperty</span>(name = <span class=\"st\">\"spring.datasource.url\"</span>)</div>\n <div class=\"tip-box\">💡 Debug auto-config: chạy với flag <code>--debug</code> hoặc thêm <code>logging.level.org.springframework.boot.autoconfigure=DEBUG</code> để thấy bean nào được/không được tạo.</div>",
"tags": "spring core",
"level": "senior",
"section": "Spring Boot",
"sectionIcon": "🌱",
"sectionColor": "#34d399",
"sectionColorClass": "spring-color",
"subsection": "Core Concepts"
},
{
"num": 54,
"numStr": "54",
"question": "Dependency Injection là gì?",
"answerHtml": "<p>DI là pattern trong đó object <strong>không tự tạo dependency</strong> — thay vào đó, container (Spring) cung cấp (inject) từ bên ngoài. Đảo ngược quyền kiểm soát (IoC).</p>\n <table class=\"compare-table\">\n <tr><th>Cách inject</th><th>Ưu điểm</th><th>Nhược điểm</th></tr>\n <tr><td>Constructor injection ✅</td><td>Immutable, dễ test, phát hiện circular dep sớm</td><td>Nhiều dependency → constructor dài</td></tr>\n <tr><td>Setter injection</td><td>Optional dependency</td><td>Mutable, dễ quên inject</td></tr>\n <tr><td>Field injection ❌</td><td>Ngắn gọn</td><td>Khó test, không rõ dependency, dùng reflection</td></tr>\n </table>\n <div class=\"code-block\"><span class=\"cm\">// ✅ Constructor injection - khuyến khích</span>\n<span class=\"an\">@Service</span>\n<span class=\"kw\">public class</span> <span class=\"cl\">OrderService</span> {\n <span class=\"kw\">private final</span> <span class=\"cl\">OrderRepository</span> orderRepo;\n <span class=\"kw\">private final</span> <span class=\"cl\">PaymentService</span> paymentService;\n\n <span class=\"cm\">// Spring tự inject khi có 1 constructor (không cần @Autowired)</span>\n <span class=\"kw\">public</span> <span class=\"fn\">OrderService</span>(<span class=\"cl\">OrderRepository</span> orderRepo, <span class=\"cl\">PaymentService</span> paymentService) {\n <span class=\"kw\">this</span>.orderRepo = orderRepo;\n <span class=\"kw\">this</span>.paymentService = paymentService;\n }\n}</div>",
"tags": "spring core",
"level": "junior",
"section": "Spring Boot",
"sectionIcon": "🌱",
"sectionColor": "#34d399",
"sectionColorClass": "spring-color",
"subsection": "Core Concepts"
},
{
"num": 55,
"numStr": "55",
"question": "IoC Container là gì?",
"answerHtml": "<p><strong>IoC (Inversion of Control):</strong> Đảo ngược quyền kiểm soát — thay vì code tự tạo object, container đảm nhận việc tạo, quản lý vòng đời, inject dependency.</p>\n <p>Spring IoC Container có 2 loại:</p>\n <ul>\n <li><code>BeanFactory</code>: Lazy, cơ bản, ít dùng trực tiếp</li>\n <li><code>ApplicationContext</code>: Extends BeanFactory, thêm i18n, events, AOP, eager init. <strong>Đây là loại chính dùng trong Spring Boot.</strong></li>\n </ul>\n <div class=\"tip-box\">💡 Ví dụ thực tế: Bạn không viết <code>new UserService(new UserRepository(dataSource))</code> nữa — Spring tự làm điều đó, bạn chỉ cần khai báo.</div>",
"tags": "spring core",
"level": "junior",
"section": "Spring Boot",
"sectionIcon": "🌱",
"sectionColor": "#34d399",
"sectionColorClass": "spring-color",
"subsection": "Core Concepts"
},
{
"num": 56,
"numStr": "56",
"question": "Bean là gì?",
"answerHtml": "<p>Bean là <strong>object được Spring IoC Container quản lý</strong> (tạo, khởi tạo, inject dependency, destroy). Không phải mọi object Java đều là bean — chỉ những object được register với container.</p>\n <p><strong>Cách khai báo bean:</strong></p>\n <ul>\n <li><code>@Component</code>, <code>@Service</code>, <code>@Repository</code>, <code>@Controller</code> → Spring tự scan</li>\n <li><code>@Bean</code> trong <code>@Configuration</code> class → Manual config, dùng cho third-party class</li>\n </ul>\n <div class=\"code-block\"><span class=\"cm\">// Cách 1: @Component (Spring scan tự động)</span>\n<span class=\"an\">@Service</span>\n<span class=\"kw\">public class</span> <span class=\"cl\">UserService</span> { ... }\n\n<span class=\"cm\">// Cách 2: @Bean (khi không thể sửa source class)</span>\n<span class=\"an\">@Configuration</span>\n<span class=\"kw\">public class</span> <span class=\"cl\">AppConfig</span> {\n <span class=\"an\">@Bean</span>\n <span class=\"kw\">public</span> ObjectMapper <span class=\"fn\">objectMapper</span>() {\n <span class=\"kw\">return new</span> ObjectMapper()\n .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, <span class=\"kw\">false</span>);\n }\n}</div>",
"tags": "spring core",
"level": "intern",
"section": "Spring Boot",
"sectionIcon": "🌱",
"sectionColor": "#34d399",
"sectionColorClass": "spring-color",
"subsection": "Core Concepts"
},
{
"num": 57,
"numStr": "57",
"question": "@Component vs @Service vs @Repository vs @Controller khác nhau thế nào?",
"answerHtml": "<p>Về chức năng DI cơ bản: <strong>giống nhau</strong> (đều là Component). Khác nhau về semantic và tính năng bổ sung:</p>\n <table class=\"compare-table\">\n <tr><th>Annotation</th><th>Layer</th><th>Tính năng đặc biệt</th></tr>\n <tr><td>@Component</td><td>Generic</td><td>Không có gì đặc biệt thêm</td></tr>\n <tr><td>@Service</td><td>Business Logic</td><td>Semantic rõ ràng, không có thêm tính năng kỹ thuật</td></tr>\n <tr><td>@Repository</td><td>Data Access</td><td>✅ Tự động translate SQL Exception → DataAccessException</td></tr>\n <tr><td>@Controller</td><td>Web Layer</td><td>✅ Hỗ trợ @RequestMapping, trả về view name</td></tr>\n <tr><td>@RestController</td><td>Web Layer</td><td>✅ = @Controller + @ResponseBody</td></tr>\n </table>",
"tags": "spring core",
"level": "intern",
"section": "Spring Boot",
"sectionIcon": "🌱",
"sectionColor": "#34d399",
"sectionColorClass": "spring-color",
"subsection": "Core Concepts"
},
{
"num": 58,
"numStr": "58",
"question": "Bean Scope là gì? Các loại scope?",
"answerHtml": "<table class=\"compare-table\">\n <tr><th>Scope</th><th>Số instance</th><th>Khi nào dùng</th></tr>\n <tr><td><strong>Singleton</strong> (default)</td><td>1 cho toàn container</td><td>Service, Repository, thường dùng nhất</td></tr>\n <tr><td><strong>Prototype</strong></td><td>Mới mỗi lần inject/getBean</td><td>Object có state, không thread-safe</td></tr>\n <tr><td><strong>Request</strong></td><td>1 cho mỗi HTTP request</td><td>Web app - lưu request context</td></tr>\n <tr><td><strong>Session</strong></td><td>1 cho mỗi HTTP session</td><td>Web app - user session data</td></tr>\n <tr><td><strong>Application</strong></td><td>1 cho mỗi ServletContext</td><td>Shared giữa sessions</td></tr>\n </table>\n <div class=\"code-block\"><span class=\"an\">@Service</span>\n<span class=\"an\">@Scope</span>(<span class=\"st\">\"prototype\"</span>) <span class=\"cm\">// hoặc @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)</span>\n<span class=\"kw\">public class</span> <span class=\"cl\">TaskProcessor</span> { ... }</div>\n <div class=\"warn-box\">⚠️ Inject Prototype bean vào Singleton bean → vẫn chỉ lấy 1 instance (vì Singleton chỉ inject 1 lần). Dùng <code>@Lookup</code> hoặc <code>ApplicationContext.getBean()</code> để giải quyết.</div>",
"tags": "spring core",
"level": "middle",
"section": "Spring Boot",
"sectionIcon": "🌱",
"sectionColor": "#34d399",
"sectionColorClass": "spring-color",
"subsection": "Core Concepts"
},
{
"num": 59,
"numStr": "59",
"question": "@Autowired hoạt động như thế nào?",
"answerHtml": "<p>Spring inject dependency <strong>theo type</strong>. Nếu tìm thấy đúng 1 bean → inject. Nhiều bean cùng type → cần <code>@Qualifier</code>. Không tìm thấy → Exception (trừ <code>@Autowired(required = false)</code>).</p>\n <div class=\"code-block\"><span class=\"cm\">// Field injection (không khuyến khích)</span>\n<span class=\"an\">@Autowired</span>\n<span class=\"kw\">private</span> UserRepository userRepo;\n\n<span class=\"cm\">// Constructor injection (khuyến khích - không cần @Autowired nếu 1 constructor)</span>\n<span class=\"kw\">public</span> <span class=\"fn\">UserService</span>(UserRepository userRepo) {\n <span class=\"kw\">this</span>.userRepo = userRepo;\n}\n\n<span class=\"cm\">// Optional dependency</span>\n<span class=\"an\">@Autowired</span>(required = <span class=\"kw\">false</span>)\n<span class=\"kw\">private</span> CacheService cacheService; <span class=\"cm\">// null nếu không có bean</span></div>",
"tags": "spring core",
"level": "middle",
"section": "Spring Boot",
"sectionIcon": "🌱",
"sectionColor": "#34d399",
"sectionColorClass": "spring-color",
"subsection": "Core Concepts"
},
{
"num": 60,
"numStr": "60",
"question": "@Qualifier dùng để làm gì?",
"answerHtml": "<p>Khi có <strong>nhiều bean cùng type</strong>, Spring không biết inject cái nào → Exception. <code>@Qualifier</code> chỉ định tên bean cụ thể cần dùng.</p>\n <div class=\"code-block\"><span class=\"an\">@Service</span>(<span class=\"st\">\"emailNotifier\"</span>)\n<span class=\"kw\">class</span> <span class=\"cl\">EmailNotificationService</span> <span class=\"kw\">implements</span> <span class=\"cl\">NotificationService</span> { ... }\n\n<span class=\"an\">@Service</span>(<span class=\"st\">\"smsNotifier\"</span>)\n<span class=\"kw\">class</span> <span class=\"cl\">SmsNotificationService</span> <span class=\"kw\">implements</span> <span class=\"cl\">NotificationService</span> { ... }\n\n<span class=\"cm\">// Inject bean cụ thể</span>\n<span class=\"kw\">public</span> <span class=\"fn\">OrderService</span>(<span class=\"an\">@Qualifier</span>(<span class=\"st\">\"emailNotifier\"</span>) NotificationService notifier) {\n <span class=\"kw\">this</span>.notifier = notifier;\n}</div>",
"tags": "spring core",
"level": "middle",
"section": "Spring Boot",
"sectionIcon": "🌱",
"sectionColor": "#34d399",
"sectionColorClass": "spring-color",
"subsection": "Core Concepts"
},
{
"num": 61,
"numStr": "61",
"question": "@Primary dùng để làm gì?",
"answerHtml": "<p>Khi có nhiều bean cùng type, đánh dấu 1 bean là <strong>ưu tiên mặc định</strong> — Spring inject bean này nếu không có <code>@Qualifier</code> cụ thể.</p>\n <div class=\"code-block\"><span class=\"an\">@Service</span>\n<span class=\"an\">@Primary</span> <span class=\"cm\">// bean này được inject mặc định</span>\n<span class=\"kw\">class</span> <span class=\"cl\">EmailNotificationService</span> <span class=\"kw\">implements</span> <span class=\"cl\">NotificationService</span> { ... }\n\n<span class=\"an\">@Service</span>\n<span class=\"kw\">class</span> <span class=\"cl\">SmsNotificationService</span> <span class=\"kw\">implements</span> <span class=\"cl\">NotificationService</span> { ... }\n\n<span class=\"cm\">// Không cần @Qualifier → nhận EmailNotificationService</span>\n<span class=\"kw\">public</span> <span class=\"fn\">OrderService</span>(NotificationService notifier) { ... }</div>",
"tags": "spring core",
"level": "middle",
"section": "Spring Boot",
"sectionIcon": "🌱",
"sectionColor": "#34d399",
"sectionColorClass": "spring-color",
"subsection": "Core Concepts"
},
{
"num": 62,
"numStr": "62",
"question": "Constructor injection vs Field injection — cái nào tốt hơn?",
"answerHtml": "<p><strong>Constructor injection được khuyến khích</strong> bởi cả Spring team và Baeldung:</p>\n <table class=\"compare-table\">\n <tr><th>Tiêu chí</th><th>Constructor ✅</th><th>Field ❌</th></tr>\n <tr><td>Immutable</td><td>✅ final field</td><td>❌</td></tr>\n <tr><td>Dễ Unit Test</td><td>✅ Tự tạo object thường</td><td>❌ Phải dùng reflection/Mockito</td></tr>\n <tr><td>Circular Dependency</td><td>✅ Phát hiện khi start</td><td>❌ Khó phát hiện</td></tr>\n <tr><td>Rõ dependency</td><td>✅ Thấy ngay ở constructor</td><td>❌ Ẩn trong field</td></tr>\n <tr><td>Không cần Spring context khi test</td><td>✅</td><td>❌</td></tr>\n </table>",
"tags": "spring core",
"level": "senior",
"section": "Spring Boot",
"sectionIcon": "🌱",
"sectionColor": "#34d399",
"sectionColorClass": "spring-color",
"subsection": "Core Concepts"
},
{
"num": 63,
"numStr": "63",
"question": "Circular Dependency là gì? Cách xử lý?",
"answerHtml": "<p>Circular Dependency: A cần B để khởi tạo, B cần A để khởi tạo → Spring không biết tạo cái nào trước → Exception.</p>\n <div class=\"code-block\"><span class=\"cm\">// Circular: A → B → A</span>\n<span class=\"kw\">class</span> <span class=\"cl\">A</span> { <span class=\"kw\">public</span> <span class=\"fn\">A</span>(<span class=\"cl\">B</span> b) { ... } }\n<span class=\"kw\">class</span> <span class=\"cl\">B</span> { <span class=\"kw\">public</span> <span class=\"fn\">B</span>(<span class=\"cl\">A</span> a) { ... } } <span class=\"cm\">// ❌ BeanCurrentlyInCreationException</span></div>\n <p><strong>Cách giải quyết (theo thứ tự ưu tiên):</strong></p>\n <ul>\n <li>✅ <strong>Tái cấu trúc code</strong>: Tách ra class C chứa logic dùng chung → loại bỏ vòng lặp</li>\n <li>✅ <strong>@Lazy</strong>: Một trong 2 bean lazy init → inject proxy trước, tạo thật khi dùng</li>\n <li>⚠️ <strong>Setter injection</strong>: Spring tạo object trước, inject sau → phá vòng nhưng mutable</li>\n </ul>",
"tags": "spring core",
"level": "senior",
"section": "Spring Boot",
"sectionIcon": "🌱",
"sectionColor": "#34d399",
"sectionColorClass": "spring-color",
"subsection": "Core Concepts"
},
{
"num": 64,
"numStr": "64",
"question": "DispatcherServlet là gì?",
"answerHtml": "<p>DispatcherServlet là <strong>Front Controller</strong> trong Spring MVC. Mọi HTTP request đều đi qua đây trước khi được điều phối đến handler phù hợp.</p>\n <div class=\"code-block\">HTTP Request\n ↓\nDispatcherServlet\n ↓\nHandlerMapping <span class=\"cm\">← tìm controller phù hợp cho URL</span>\n ↓\nHandlerAdapter <span class=\"cm\">← gọi method của controller</span>\n ↓\nController Method <span class=\"cm\">← business logic, trả về data/view</span>\n ↓\nViewResolver <span class=\"cm\">← (nếu MVC) resolve tên view → template</span>\n ↓\nHTTP Response</div>",
"tags": "spring web",
"level": "senior",
"section": "Spring Boot",
"sectionIcon": "🌱",
"sectionColor": "#34d399",
"sectionColorClass": "spring-color",
"subsection": "Spring MVC & Web"
},
{
"num": 65,
"numStr": "65",
"question": "@RestController vs @Controller khác nhau thế nào?",
"answerHtml": "<p><code>@RestController</code> = <code>@Controller</code> + <code>@ResponseBody</code></p>\n <table class=\"compare-table\">\n <tr><th></th><th>@Controller</th><th>@RestController</th></tr>\n <tr><td>Return giá trị</td><td>Tên view (String) → resolve thành HTML</td><td>Object → serialize thành JSON/XML</td></tr>\n <tr><td>Cần @ResponseBody?</td><td>Có nếu muốn trả data</td><td>Mặc định có rồi</td></tr>\n <tr><td>Dùng cho</td><td>Web MVC (Thymeleaf, JSP)</td><td>REST API</td></tr>\n </table>\n <div class=\"code-block\"><span class=\"an\">@Controller</span>\n<span class=\"kw\">class</span> <span class=\"cl\">PageController</span> {\n <span class=\"an\">@GetMapping</span>(<span class=\"st\">\"/home\"</span>)\n String <span class=\"fn\">home</span>() { <span class=\"kw\">return</span> <span class=\"st\">\"home\"</span>; } <span class=\"cm\">// → resolve \"home.html\"</span>\n}\n\n<span class=\"an\">@RestController</span>\n<span class=\"kw\">class</span> <span class=\"cl\">UserController</span> {\n <span class=\"an\">@GetMapping</span>(<span class=\"st\">\"/api/users\"</span>)\n List<User> <span class=\"fn\">getUsers</span>() { <span class=\"kw\">return</span> users; } <span class=\"cm\">// → serialize thành JSON</span>\n}</div>",
"tags": "spring web",
"level": "junior",
"section": "Spring Boot",
"sectionIcon": "🌱",
"sectionColor": "#34d399",
"sectionColorClass": "spring-color",
"subsection": "Spring MVC & Web"
},
{
"num": 66,
"numStr": "66",
"question": "@PathVariable vs @RequestParam khác nhau thế nào?",
"answerHtml": "<table class=\"compare-table\">\n <tr><th></th><th>@PathVariable</th><th>@RequestParam</th></tr>\n <tr><td>Lấy từ đâu</td><td>URL path: /users/{id}</td><td>Query string: ?name=abc</td></tr>\n <tr><td>Bắt buộc</td><td>Mặc định có</td><td>Tuỳ (required = false)</td></tr>\n <tr><td>Default value</td><td>❌</td><td>✅ defaultValue = \"...\"</td></tr>\n </table>\n <div class=\"code-block\"><span class=\"cm\">// GET /users/42</span>\n<span class=\"an\">@GetMapping</span>(<span class=\"st\">\"/users/{id}\"</span>)\nUser <span class=\"fn\">getById</span>(<span class=\"an\">@PathVariable</span> Long id) { ... }\n\n<span class=\"cm\">// GET /users?page=1&size=10&sort=name</span>\n<span class=\"an\">@GetMapping</span>(<span class=\"st\">\"/users\"</span>)\nPage<User> <span class=\"fn\">getAll</span>(\n <span class=\"an\">@RequestParam</span>(defaultValue = <span class=\"st\">\"0\"</span>) <span class=\"kw\">int</span> page,\n <span class=\"an\">@RequestParam</span>(defaultValue = <span class=\"st\">\"10\"</span>) <span class=\"kw\">int</span> size,\n <span class=\"an\">@RequestParam</span>(required = <span class=\"kw\">false</span>) String sort\n) { ... }</div>",
"tags": "spring web",
"level": "intern",
"section": "Spring Boot",
"sectionIcon": "🌱",
"sectionColor": "#34d399",
"sectionColorClass": "spring-color",
"subsection": "Spring MVC & Web"
},
{
"num": 67,
"numStr": "67",
"question": "@RequestBody vs @ResponseBody?",
"answerHtml": "<ul>\n <li><code>@RequestBody</code>: Đọc HTTP request body → deserialize (thường từ JSON) thành Java object. Dùng <strong>HttpMessageConverter</strong> (Jackson mặc định).</li>\n <li><code>@ResponseBody</code>: Serialize Java object → ghi vào HTTP response body (thường thành JSON). <code>@RestController</code> đã bao gồm sẵn.</li>\n </ul>\n <div class=\"code-block\"><span class=\"an\">@PostMapping</span>(<span class=\"st\">\"/users\"</span>)\n<span class=\"an\">@ResponseBody</span> <span class=\"cm\">// không cần nếu đã có @RestController</span>\nUser <span class=\"fn\">create</span>(<span class=\"an\">@RequestBody</span> <span class=\"an\">@Valid</span> CreateUserRequest request) {\n <span class=\"cm\">// request tự động parse từ JSON body: {\"name\":\"John\",\"email\":\"...\"}</span>\n <span class=\"kw\">return</span> userService.create(request);\n <span class=\"cm\">// return value tự serialize thành JSON response</span>\n}</div>",
"tags": "spring web",
"level": "intern",
"section": "Spring Boot",
"sectionIcon": "🌱",
"sectionColor": "#34d399",
"sectionColorClass": "spring-color",
"subsection": "Spring MVC & Web"
},
{
"num": 68,
"numStr": "68",
"question": "ResponseEntity là gì?",
"answerHtml": "<p>ResponseEntity cho phép kiểm soát <strong>toàn bộ HTTP response</strong>: status code, headers, body. Hữu ích khi cần trả về HTTP status khác 200.</p>\n <div class=\"code-block\"><span class=\"an\">@PostMapping</span>(<span class=\"st\">\"/users\"</span>)\nResponseEntity<User> <span class=\"fn\">create</span>(<span class=\"an\">@RequestBody</span> CreateUserRequest req) {\n User user = userService.create(req);\n <span class=\"kw\">return</span> ResponseEntity\n .status(HttpStatus.CREATED) <span class=\"cm\">// 201</span>\n .header(<span class=\"st\">\"Location\"</span>, <span class=\"st\">\"/users/\"</span> + user.getId())\n .body(user);\n}\n\n<span class=\"cm\">// Các shorthand phổ biến</span>\nResponseEntity.ok(data); <span class=\"cm\">// 200 + body</span>\nResponseEntity.created(uri).body(user); <span class=\"cm\">// 201 + Location header</span>\nResponseEntity.noContent().build(); <span class=\"cm\">// 204</span>\nResponseEntity.notFound().build(); <span class=\"cm\">// 404</span></div>",
"tags": "spring web",
"level": "junior",
"section": "Spring Boot",
"sectionIcon": "🌱",
"sectionColor": "#34d399",
"sectionColorClass": "spring-color",
"subsection": "Spring MVC & Web"
},
{
"num": 69,
"numStr": "69",
"question": "Exception handling trong Spring Boot thế nào?",
"answerHtml": "<p><strong>Cách 1: @ExceptionHandler trong Controller</strong> — chỉ áp dụng cho controller đó.</p>\n <p><strong>Cách 2: @ControllerAdvice + @ExceptionHandler</strong> — global, áp dụng cho tất cả controller.</p>\n <div class=\"code-block\"><span class=\"an\">@RestControllerAdvice</span> <span class=\"cm\">// = @ControllerAdvice + @ResponseBody</span>\n<span class=\"kw\">public class</span> <span class=\"cl\">GlobalExceptionHandler</span> {\n\n <span class=\"an\">@ExceptionHandler</span>(UserNotFoundException.<span class=\"kw\">class</span>)\n <span class=\"an\">@ResponseStatus</span>(HttpStatus.NOT_FOUND)\n ErrorResponse <span class=\"fn\">handleNotFound</span>(UserNotFoundException ex) {\n <span class=\"kw\">return new</span> ErrorResponse(<span class=\"st\">\"USER_NOT_FOUND\"</span>, ex.getMessage());\n }\n\n <span class=\"an\">@ExceptionHandler</span>(MethodArgumentNotValidException.<span class=\"kw\">class</span>)\n <span class=\"an\">@ResponseStatus</span>(HttpStatus.BAD_REQUEST)\n ErrorResponse <span class=\"fn\">handleValidation</span>(MethodArgumentNotValidException ex) {\n <span class=\"kw\">var</span> errors = ex.getBindingResult().getFieldErrors()\n .stream().map(e -> e.getField() + <span class=\"st\">\": \"</span> + e.getDefaultMessage())\n .toList();\n <span class=\"kw\">return new</span> ErrorResponse(<span class=\"st\">\"VALIDATION_FAILED\"</span>, errors.toString());\n }\n}</div>",
"tags": "spring web",
"level": "middle",
"section": "Spring Boot",
"sectionIcon": "🌱",
"sectionColor": "#34d399",
"sectionColorClass": "spring-color",
"subsection": "Spring MVC & Web"
},
{
"num": 70,
"numStr": "70",
"question": "Filter vs Interceptor khác nhau thế nào?",
"answerHtml": "<table class=\"compare-table\">\n <tr><th></th><th>Filter (Servlet)</th><th>Interceptor (Spring MVC)</th></tr>\n <tr><td>Level</td><td>Servlet container</td><td>Spring DispatcherServlet</td></tr>\n <tr><td>Chạy khi nào</td><td>Trước cả DispatcherServlet</td><td>Sau DispatcherServlet, trước Controller</td></tr>\n <tr><td>Truy cập Spring bean</td><td>Khó hơn</td><td>✅ Dễ dàng</td></tr>\n <tr><td>Truy cập HandlerMethod</td><td>❌</td><td>✅</td></tr>\n <tr><td>Dùng cho</td><td>CORS, encoding, security (Spring Security)</td><td>Auth check, logging, audit</td></tr>\n </table>\n <div class=\"code-block\"><span class=\"cm\">// Interceptor</span>\n<span class=\"kw\">public class</span> <span class=\"cl\">AuthInterceptor</span> <span class=\"kw\">implements</span> HandlerInterceptor {\n <span class=\"kw\">public boolean</span> <span class=\"fn\">preHandle</span>(HttpServletRequest req, HttpServletResponse res, Object handler) {\n <span class=\"cm\">// Chạy TRƯỚC controller method</span>\n <span class=\"cm\">// return false → dừng, không vào controller</span>\n <span class=\"kw\">return</span> validateToken(req);\n }\n <span class=\"kw\">public void</span> <span class=\"fn\">postHandle</span>(...) { <span class=\"cm\">/* Sau controller, trước render view */</span> }\n <span class=\"kw\">public void</span> <span class=\"fn\">afterCompletion</span>(...) { <span class=\"cm\">/* Sau tất cả, dọn dẹp */</span> }\n}</div>",
"tags": "spring web",
"level": "senior",
"section": "Spring Boot",
"sectionIcon": "🌱",
"sectionColor": "#34d399",
"sectionColorClass": "spring-color",