Xin chào mừng bạn đã ghé thăm blog của Nguyễn Văn Tiến!.Chúc bạn sức khỏe, niềm vui và an lành!.

Thứ Năm, 7 tháng 4, 2016

10 Framework PHP tốt nhất dành cho lập trình viên

Bài viết được dịch từ trang web Hongkiat
PHP được xem là ngôn ngữ kịch bản phía máy chủ phổ biến nhất trên thế giới, nó đã phát triển rất nhiều kể từ khi các đoạn code inline đầu tiên xuất hiện trong các tập tin HTML tĩnh.
Ngày nay khi các lập trình viên cần xây dựng các website và các ứng dụng web phức tạp, họ có thể sẽ mất quá nhiều thời gian và rắc rối nếu cứ xây dựng ứng dụng từ đầu, vì thế cần đến một cách tự nhiên hơn để xây dựng sản phẩm. PHP framework ra đời và cung cấp cho các nhà phát triển với một giải pháp thỏa đáng cho điều đó.
Trong bài này chúng tôi sẽ lựa chọn cẩn thận 10 framework PHP phổ biến mà có thể tạo điều kiện tốt nhất và hỗ trợ quá trình phát triển web của bạn.

Tại sao lại sử dụng một framework PHP 

Nhưng trước tiên, chúng ta hãy xem qua những lý do hàng đầu tại sao nhiều nhà phát triển phần mềm muốn sử dụng các framework PHP và làm thế nào những framework này có thể nâng cao hiệu suất quá trình phát triển web của bạn. Dưới đây là những gì các framework PHP hỗ trợ:
  • Nâng cao tốc độ phát triển sản phẩm
  • Cung cấp code được tổ chức tốt, có thể sử dụng lại và dễ dàng bảo trì
  • Cho phép bạn phát triển theo thời gian khi các ứng dụng web chạy trên các framework này có khả năng mở rộng
  • Giải phóng bạn khỏi những lo ngại về bảo mật ở mức thấp của một trang web
  • Tuân theo mô hình MVC (Model-View-Controller) đảm bảo sự tách biệt phần trình diễn và phần logic nghiệp vụ
  • Thúc đẩy phương thức phát triển web hiện đại như các công cụ lập trình hướng đối tượng

1. Laravel

Học lập trình web trực tuyến bằng framework Laravel
Mặc dù Laravel là một framework PHP tương đối mới (nó được phát hành vào năm 2011), theo khảo sát trực tuyến gần đây của Sitepoint thì nó là framework phổ biến nhất mà các nhà phát triển hay sử dụng. Laravel có một hệ sinh thái rất lớn với một nền tảng giúp triển khai ứng dụng của bạn một cách nhanh chóng, và trang web chính thức của nó cung cấp nhiều hướng dẫn bằng video gọi là Laracasts.
Laravel có nhiều tính năng giúp cho việc phát triển ứng dụng nhanh chóng nhất có thể. Laravel sở hữu một light-weight templating engine có tên là "Blade", cú pháp sáng sủa hỗ trợ cho các tác vụ thường xuyên cần phải làm trong ứng dụng của bạn, chẳng hạn như authentication, sessions, queueing, caching và RESTful routing. Laravel cũng bao gồm một môi trường phát triển cục bộ gọi là Homestead - đây thực chất là một Vagrant box được đóng gói.

2. Symfony

Học lập trình web trực tuyến bằng framework Symfony
Các thành phần của framework Symfony 2 được sử dụng bởi nhiều dự án ấn tượng như hệ quản trị nội dung Drupal, hoặc phần mềm diễn đàn phpBB, kể cả Laravel - framework được liệt kê ở trên - cũng dựa vào nó. Symfony có một cộng đồng phát triển rộng lớn và nhiều fan hâm mộ cuồng nhiệt.
Symfony Componentscác thư viện PHP có thể sử dụng lại giúp bạn hoàn thành nhiều tác vụ khác nhau, chẳng hạn như việc tạo form, cấu hình đối tượng, routing, authentication, templating, và nhiều thứ khác. Bạn có thể cài đặt bất kỳ Components nào bằng trình quản lý dependency PHP Composer. Trang web của Symfony có một phần showcase rất đẹp mắt, nơi bạn có thể xem qua một số dự án đã hoàn thành với sự giúp đỡ của framework tiện dụng này.

3. CodeIgniter

Học lập trình web trực tuyến bằng framework CodeIgniter
CodeIgniter là một framework PHP rất nhẹ và có tuổi đời gần 10 năm (được phát hành lần đầu tiên vào năm 2006). CodeIgniter có một quá trình cài đặt rất đơn giản và chỉ đòi hỏi một cấu hình tối thiểu, do đó nó có thể giúp bạn loại bỏ được rất nhiều rắc rối. Đây cũng là một sự lựa chọn lý tưởng nếu bạn muốn tránh xung đột phiên bản PHP, vì nó hoạt động tốt trên hầu như tất cả các nền tảng shared và dedicated hosting (hiện nay nó chỉ yêu cầu phiên bản PHP 5.2.4).
CodeIgniter không hoàn toàn dựa trên mô hình phát triển MVC. Việc sử dụng các lớp Controller là bắt buộc, nhưng Models và Views là tùy chọn, và bạn có thể sử dụng các tiêu chuẩn đặt tên và viết code theo cách của riêng mình, đó là bằng chứng cho thấy CodeIgniter cung cấp tự do tuyệt vời cho các nhà phát triển. Nếu bạn tải mã nguồn về, bạn sẽ thấy nó chỉ có dung lượng khoảng 2MB, vì đây là một lean framework, nhưng nó cho phép bạn bổ sung thêm các plugin của hãng thứ ba nếu bạn cần các chức năng phức tạp hơn.

4. Yii 2

Học lập trình web trực tuyến bằng framework Yii 2
Nếu bạn chọn framework Yii thì trang web của bạn sẽ có tốc độ thực thi rất nhanh, nhanh hơn so với các framework PHP khác, bởi vì nó sử dụng kỹ thuật lazy loading một cách rộng rãi. Yii 2 hoàn toàn hướng đối tượng, và nó dựa trên khái niệm lập trình DRY (Don’t Repeat Yourself), do đó cung cấp cho bạn một code base sạch sẽ và hợp lý.
Yii 2 được tích hợp với jQuery đi kèm với một bộ tính năng AJAX-enabled, nó thực hiện một cơ chế để dễ dàng sử dụng skinning và theming, do đó đây có thể là một lựa chọn tuyệt vời cho những người đến từ một nền tảng frontend. Nó cũng có một bộ sinh code (class code generator) mạnh mẽ được gọi là Gii tạo điều kiện cho lập trình hướng đối tượng và tạo nguyên mẫu (prototyping) nhanh chóng, và cung cấp một giao diện dạng web cho phép bạn tương tác để sinh ra phần code mà bạn cần.

5. Phalcon

Học lập trình web trực tuyến bằng framework Phalcon
Framework Phalcon được phát hành vào năm 2012, và nó nhanh chóng trở nên phổ biến trong cộng đồng các nhà phát triển PHP. Phalcon được cho là nhanh như chim ưng, vì nó được viết bằng C và C++ để đạt được mức độ cao nhất của tối ưu hóa hiệu suất có thể. Tin tốt là bạn không cần phải học ngôn ngữ C, vì các chức năng được đưa ra là các class PHP sẵn sàng để sử dụng cho bất kỳ ứng dụng nào.
Phalcon được cung cấp như một phần mở rộng của ngôn ngữ C, kiến trúc của nó được tối ưu hóa ở mức độ thấp làm giảm đáng kể các chi phí điển hình của các ứng dụng dựa trên mô hình MVC. Phalcon không chỉ giúp tăng tốc độ thực thi, mà cũng làm giảm việc sử dụng tài nguyên. Phalcon cũng được đóng gói với nhiều tính năng thú vị như auto-loader, asset management, security, translation, caching, và nhiều thứ khác. Đây là một framework có tài liệu đầy đủ và rất dễ sử dụng, nó chắc chắn có giá trị để bạn dùng thử.

6. CakePHP

Học lập trình web trực tuyến bằng framework CakePHP
CakePHP đã có tuổi đời một thập kỷ (phiên bản đầu tiên được phát hành vào năm 2005), nhưng nó vẫn nằm trong số các framework PHP phổ biến nhất, và luôn được cập nhật theo thời gian. Phiên bản mới nhất, CakePHP 3.0 tăng cường việc quản lý session, cải tiến tính mô-đun hóa bằng cách tách ra một số thành phần, và tăng khả năng tạo thêm các thư viện độc lập.
CakePHP có một showcase thực sự đáng chú ý, nó tạo sức mạnh cho các trang web của các thương hiệu lớn như BMW, Hyundai, và Express. Đây là một công cụ tuyệt vời cho việc tạo ra các ứng dụng web cần cấp độ bảo mật cao, vì nó có nhiều tính năng bảo mật tích hợp như xác nhận đầu vào, phòng chống SQL injection, XSS (cross-site scripting), CSRF (cross-site request forgery), và nhiều thứ khác.

7. Zend Framework

Học lập trình web trực tuyến bằng framework Zend
Zend là một framework PHP mạnh mẽ và ổn định được đóng gói với rất nhiều cấu hình tùy chọn vì thế nó được khuyến cáo không nên sử dụng cho các dự án nhỏ nhưng rất tuyệt vời cho những dự án phức tạp. Zend có các đối tác như IBM, Microsoft, Google và Adobe. Trong phiên bản lớn phát hành sắp tới, Zend Framework 3 sẽ được tối ưu hóa cho PHP 7, nhưng vẫn sẽ hỗ trợ PHP 5.5 trở đi.
Phiên bản hiện tại, Zend Framework 2 cũng có nhiều tính năng thú vị như các công cụ mã hóa code, một editor có thể kéo & thả dễ dàng sử dụng với sự hỗ trợ cho các công nghệ front-end (HTML, CSS, JavaScript), debugging trực tuyến nhanh, các công cụ PHP Unit testing, và một Database Wizard giúp kết nối cơ sở dữ liệu. Zend Framework được tạo ra với các phương pháp Agile tạo điều kiện để cung cấp các ứng dụng chất lượng cao cho khách hàng doanh nghiệp.

8. Slim

Học lập trình web trực tuyến bằng framework Slim
Slim là một framework PHP nhỏ cung cấp cho bạn mọi thứ bạn cần và không thừa thứ gì cả. Các micro framework thường tối giản trong thiết kế, chúng là tuyệt vời cho các ứng dụng nhỏ hơn, nơi mà một full-stack framework sẽ trở nên cồng kềnh và không cần thiết. Tác giả của Slim đã được lấy cảm hứng từ một framework Ruby có tên là Sinatra.
Slim được sử dụng bởi nhiều lập trình viên PHP để phát triển các RESTful API và services. Slim đi kèm với các tính năng như URL routing, client-side HTTP caching, mã hóa session và cookie, nó cũng hỗ trợ message trên các HTTP request rất tốt. Hướng dẫn sử dụng của Slim khá dễ hiểu, và nếu bạn quan tâm đến các tính năng mới của phiên bản chính sắp tới (đã có phiên bản beta), bạn có thể xem video này về Slim 3.

9. FuelPHP

Học lập trình web trực tuyến bằng framework FuelPHP
FuelPHP là một full-stack PHP framework linh hoạt không chỉ hỗ trợ mô hình MVC thông thường mà còn phát triển phiên bản của riêng nó, HMVC (Hierarchical Model-View-Controller) ở cấp độ kiến trúc. FuelPHP bổ sung thêm một class tùy chọn gọi là Presenter (trước đây gọi là ViewModel) giữa các layer Controller và View để giữ logic cần thiết khi sinh ra Views.
FuelPHP có tính mô-đun và có khả năng mở rộng, nó rất chú ý đến vấn đề bảo mật bằng cách cung cấp các tính năng như lọc đầu vào, URI và mã hóa đầu ra, và FuelPHP đi kèm với một authentication framework của riêng nó, với nhiều tính năng phức tạp khác và một tài liệu hướng dẫn chi tiết.

10. PHPixie

Học lập trình web trực tuyến bằng framework PHPixie
PHPixie là một framework khá mới, nó xuất hiện vào năm 2012 với mục tiêu tạo ra một framework hiệu suất cao cho các trang web dạng read-only. PHPixie cũng áp dụng design pattern HMVC giống như FuelPHP, và được xây dựng bằng cách sử dụng các thành phần độc lập có thể được sử dụng rất tốt mà không cần chính bản thân framework đó. Các thành phần của PHPixie là 100% unit tested, và yêu cầu các dependencies ở mức tối thiểu.
Trang web chính thức của nó có một hướng dẫn tuyên bố rằng bạn có thể học framework này trong vòng chỉ 30 phút, và blog của họ cũng cung cấp chi tiết nhiều trường hợp sử dụng thực tế. Trong số các tính năng bạn có thể tìm thấy như standard ORM (object-relational mapping), caching, input validation, authentication và authorization. PHPixie cũng cho phép bạn sử dụng ngôn ngữ markup HAML, cho phép di chuyển lược đồ, và có một hệ thống định tuyến phức tạp.

Thứ Tư, 6 tháng 4, 2016

Tản mạn về tài năng của JavaScript

Khởi nguồn từ giữa những năm 1990, qua 20 năm tồn tại và phát triển, Javascript đã có những thay đổi lớn để thích nghi với thời cuộc, và bây giờ trở thành một ngôn ngữ toàn năng, thiết yếu và phù hợp đối với bất cứ một nhà phát triển nào. Với ý tưởng ban đầu là tạo ra một ngôn ngữ thông dịch tích hợp vào trình duyệt nhằm tăng tính tương tác của người dùng với trang web, với sự mềm dẻo của mình thì ngày nay Javascript đã làm được nhiều điều hơn thế, chúng ta thử điểm lại những miếng võ mà chàng hiệp sĩ này có thể triển khai nhé.
1. Ngôn ngữ client-side.
Ở vị trí client-side thì Javascript chiếm vị trí độc tôn. Hiện nay, không một ngôn ngữ nào có thể cạnh tranh với Javascript trong vai trò là một ngôn ngữ tương tác cho các trang web. Điều gì đã làm cho Javascript được chấp nhận rộng rãi và trở nên phổ biến như vậy? Khó có thể có một câu trả lời thỏa đáng, nhưng chúng ta có thể kể ra những đặc điểm của Javascipt để thấy được các ưu điểm của nó.
Về cú pháp, cũng giống như nhiều ngôn ngữ khác, Javascript thừa kế nhiều cú pháp từ ngôn ngữ C nhưng đã được thêm bớt nhiều để trở nên linh hoạt hơn. Các cấu trúc lập trình cơ bản thì hầu như không có sự thay đổi nào, ví dụ ifwhileswitch…; Một thay đổi lớn mà ít người để ý đến đó là cơ chế tự chèn dấu chấm phẩy (;), việc này giúp cho chúng ta có một cú pháp ít chặt chẽ hơn nhưng “dễ thở” hơn trong khi viết code.
Kiểu dữ liệu là một trong những khái niệm quan trọng trong các ngôn ngữ lập trình. Thường thì có hai cách để thể hiện kiểu dữ liệu, đó là gắn vào biến hay gắn vào giá trị. Với các ngôn ngữ biên dịch (như C, Java,…) thì kiểu dữ liệu được gắn vào biến, có nghĩa là khi chúng ta khai báo một biến thì nhất thiết phải chỉ rõ biến đó thuộc kiểu dữ liệu nào, và nó chỉ có thể được gắn với các giá trị của kiểu đó. (Tại sao lại thế? Việc này mang lại những lợi ích gì? Chúng ta có thể tranh luận thêm). Trong Javascript (và phần lớn các ngôn ngữ kịch bản – scripting language – khác) thì kiểu dữ liệu được gắn với giá trị, có nghĩa là chúng ta có thể khai báo một biến, gán cho nó một giá trị kiểu chuỗi, rồi sau đó lại thay đổi để nó gắn nó với một giá trị số. Điều này thật dễ dàng (Tại sao?).
Javascript là một ngôn ngữ lập trình hướng đối tượng (OOP) mềm dẻo, đây là một thế mạnh nữa của Javascript. Tôi phải thêm chữ “mềm dẻo” đằng sau bởi vì cách mà nó hỗ trợ OOP thật là tuyệt vời. Bản thân mỗi đối tượng trong Javascript là một mảng, cộng thêm việc dựa trên cơ chế prototype làm cho quá trình tạo và sử dụng trong Javascript thật là “nhẹ như lông hồng”. Có hai cú pháp để sử dụng thuộc tính của một đối tượng: obj.name = ‘Bob’ và obj[‘name’] = ‘Bob’. Ngoài ra, ta có thể thêm, bớt, thay đổi các thuộc tính của đối tượng một cách tùy thích tại thời điểm thực thi (điều này thì các ngôn ngữ khác đã kể ở trên khó mà có được). Các thuộc tính cũng có thể được duyệt qua bằng cách sử dụng vòng lặp for…in. (Nhân tiện nói đến vòng lặp, mời các bạn xem thêm bài về mảng trong Javascript để thấy được nó linh hoạt như thế nào)
Hàm eval() trong Javascript giúp chúng ta làm được một việc to lớn bằng một cách rất dễ dàng. Tại thời điểm thực thi, nếu chúng ta muốn thực thi một đoạn mã mà trước đó chưa hề có, vậy phải làm sao? Thật đơn giản, chỉ cần cung cấp đoạn mã đó dưới dạng một chuỗi, chỉ là chuỗi, hàm eval() sẽ giúp ta chuyển chuỗi đó thành mã thực thi ngay tức khắc. Linh hoạt đến thế là cùng.
Còn nhiều, nhiều đặc điểm khác nữa của Javascript, nhưng chúng ta sẽ không kể hết ra đây. Tôi chỉ muốn nhắc đến một thứ cuối cùng, thứ đã tạo nên một thế giới Javascript thật đa dạng và phong phú. Đó chính là danh sách hàng triệu triệu nền tảng và thư viện Javascript được xây dựng và cung cấp hoàn toàn miễn phí (và cả có phí) cho chúng ta sẵn dùng. Các nền tảng này, kèm thêm các phần mở rộng của chúng, đã tạo nên một hệ sinh thái mà ở đó tất cả chúng ta đều hưởng lợi.
2. Ngôn ngữ server-side.
Mặc dù trước đây chúng ta đã có thể sử dụng Javascript làm ngôn ngữ lập trình cho server-side, nhưng nhìn chung thì nó vẫn không được biết đến nhiều lắm cho tới khi Nodejs ra đời. Mặc dù chỉ mới xuất hiện gần đây (năm 2009) nhưng thực sự Nodejs đã làm nên một cuộc cách mạng, làm cho Javascript trở nên mạnh mẽ, đa năng, hiệu quả hơn bao giờ hết. Với cơ chế bất đồng bộ vốn có của mình, Nodejs là lựa chọn số một cho các ứng dụng network thời gian thực với quy mô lớn. Có thể kể tên những “khách hàng” nổi tiếng của Nodejs: FacebookMicrosoftYahoo,Paypal,… và một loạt các đại gia cùng tiểu gia khác.
3. Ứng dụng desktop.
Với việc Microsoft chính thức hỗ trợ việc phát triển các ứng dụng Metro từ Windows 8 thì Javascript đã có thêm một mảnh đất lớn để dụng võ. Với cách làm này, các nhà phát triển sẽ nhanh chóng tạo ra được các ứng dụng desktop “đẹp lung linh” mà không phải mất quá nhiều công sức. Tất nhiên, về phía người dùng, họ không thể nhận ra một sự khác biệt nào giữa một ứng dụng loại này so với một ứng dụng viết bằng C#, VB.NET hay một ngôn ngữ khác. (Đọc thêm ở đây nhé). Nếu bạn thấy thú vị, tôi xin giới thiệu với bạn một nền tảng là TideSDK, nó sẽ giúp cho bạn phát triển các ứng dụng desktop nhanh, đẹp cho hầu hết tất cả các hệ điều hành phổ biến hiện nay.
4. Ứng dụng mobile
Sử dụng Javascript để viết ứng dụng cho các thiết bị di động không còn là một điều gì đó quá mới mẻ, các bạn có thể đọc thêm một bài viết ở đây. Tạo ra các ứng dụng dạng này cũng không quá khó khăn, tại sao ư? Bởi vì hiện nay có từ vài chục (cho đến vài trăm) nền tảng giúp cho chúng ta làm được việc này dễ dàng, thử liệt kê ra một số: jQuery MobilePhoneGapSencha Touch,… Hãy xem bảng so sánh ở đây và đọc thêm bài này để có được một cái nhìn toàn cảnh hơn về các nền tảng này.
5. Game
UnityConstruct 2ImpactJS… là những cái tên không còn quá xa lại đối với những nhà phát triển game (Có thể tham khảo danh sách khá đầy đủ ở đây). Sử dụng các nền tảng này sẽ giúp chúng ta nhanh chóng tạo được những game đa nền tảng với đồ họa “đẹp như mơ”. Đa nền tảng ở đây không chỉ là nói đến các nền tảng PC truyền thống, mà còn là các nền tảng di động nữa. Đặc biệt, đối với hệ điều hành di động FirefoxOS mới ra đời thì việc sử dụng Javascript (và các nền tảng hỗ trợ) là một điều bắt buộc khi bạn muốn phát triển ứng dụng hay game. Hãy bắt đầu bằng việc xem một video dài chưa đến 2 phút trình diễn việc viết game sử dụng một nền tảng nó dễ dàng như thế nào nhé.
6. All-by-One
Còn gì tuyệt vời hơn khi chỉ cần một ngôn ngữ mà bạn lại có thể tạo ra được chừng ấy thứ? Nếu là lập trình viên, bạn sẽ không mất nhiều thời gian để làm quen với nhiều ngôn ngữ. Nếu là ông chủ, bạn sẽ không phải bỏ tiền để thuê nhiều đội phát triển cho những nền tảng khác nhau. Nếu là người dùng, tôi sẽ không quan tâm tới ngôn ngữ đằng sau, miễn sao ứng dụng phù hợp với tôi, đem lại cho tôi một trải nghiệm nhất quán không phụ thuộc nền tảng. Với một thế giới toàn màu hồng như vậy, còn chần chừ gì nữa mà không kết thân ngay với chàng Hiệp sĩ Javacript toàn năng ngay từ bây giờ!
Chắc chắn sẽ còn một số các đặc điểm cũng như ứng dụng khác quan trọng (và ít quan trọng hơn một chút) của Javascipt mà chưa được đề cập trong bài viết cùng với các khiếm khuyết của nó. Chúng ta cùng thảo luận nhé.

Thứ Hai, 4 tháng 4, 2016

Câu phỏng vấn Java

Phỏng vấn vẫn là vấn đề rất nhiều bạn ra trường khá sợ và thiếu tự tin, sợ và thiếu tự tin một phần chủ yếu do thiếu rất nhiều kiến thức nền tảng, chưa sẵn sàng cho những kiến thức mà mình đang có. Đọc qua những câu phỏng vấn về một vấn đề bạn quan tâm cũng là một cách học khá hay, bạn sẽ biết mình đang thiếu mảng kiến thức nào, cần trao dồi thêm mảng nào, để khi phỏng vấn bạn tự tin hơn với lượng kiến thức mình mang theo. Mong rằng bài dịch sẽ mang một lượng kiến thức nhỏ cho các bạn sinh viên đã hoặc sắp ra trường. Mình thấy những câu trả lời ở dưới khá chung chung và chưa có độ sâu nhất định, khi đã đọc xong cả câu hỏi và câu trả lời mà bạn vẫn còn mơ hồ, hãy tìm hiểu thêm thật rõ về vấn đề đó, đừng để mình bị thiếu hay nghĩ sai về một vấn đề, vì nhiều lúc câu dịch của mình không diễn tả đủ ý tác giả muốn truyền đạt.
Trong bài hướng dẫn này, chúng ta sẽ cùng nhau thảo luận về một vài loại câu hỏi thường hay được sử dụng trong phỏng vấn, nhằm giúp các bạn kiểm tra và củng cố lại kiến thức Java của mình, cùng với lập trình hướng đối tượng.
Xuyên suốt bài viết, chúng ta cùng thảo luận về lập trình hướng đối tượng, những câu hỏi tổng quát liên quan đến Java và những chức năng của nó, tập hợp(collections) trong Java, bộ dọn rác (garbage collectors), ngoại lệ (exception handling), Java applets, Swing, JDBC, Remote Method Invocation (RMI), Servlets and JSP …
Mục lục:
  1. Object Oriented Programming (OOP)
  2. General Questions about Java
  3. Java Threads
  4. Java Collections
  5. Garbage Collectors
  6. Exception Handling
Java Applets, Swing, JDBC, Remote Method Invocation (RMI), Servlets, JSP

LẬP TRÌNH HƯỚNG ĐỐI TƯỢNG (OBJECT ORIENTED PROGRAMMING)

Java là một ngôn ngữ lập trình mang tính đồng thời (concurrent), class-based và hướng đối tượng. Một vài lợi ích của việc phát triển phần mềm theo hướng đối tượng:
  • Modun hoá việc phát triển mã lệnh, dẫn đến bảo trì và thay đổi đơn giản.
  • Có khả năng tái sử dụng mã lệnh
  • Cải tiến độ tin cậy và mềm dẻo trong mã lệnh.
  • Giúp mã lệnh dễ hiểu hơn.
Lập trình hướng đối tượng có nhiều những đặc tính quan trọng, như encapsultation (tính bao đóng), inheritance (tính kế thừa), polymorphism (tính đa hình) và abstraction(tính trừu tượng). Chúng ta phân tích mỗi đặc tính qua từng phân đoạn.
Encapsulation
Encapsulation (tính bao đóng) cung cấp cho những đối tượng khả năng che dấu tính chất đặc thù và những hành vi bên trong chúng. Mỗi đối tượng cung cấp một số các phương thức, chúng có thể được truy cập từ những đối tượng khác và có thể bị thay đổi dữ liệu bên trong nó. Trong Java, có 3 mức(modifier) truy cập:  public, private và protected. Mỗi mức bắt buộc những quyền truy cập khác nhau từ những lớp (class) khác, dù là cùng hay khác package. Một vài lợi ích khi sử dụng encapsulation:
  • Ẩn những trạng thái (state) của đối tượng cần được bảo vệ.
  • Tăng khả năng bảo trì và sử dụng mã lênh, bởi vì những hành vi của đối tượng có thể độc lập khi bị thay đổi hay mở rộng.
  • Tăng khả năng modun hoá bằng cách tránh những đối tượng tương tác trực tiếp lẫn nhau, trong cách nhờ vả nhau.
Bạn có thể tham khảo thêm một bài hướng dẫn để nắm rõ hơn về đặc tính encapsulation :here
Polymorphism
Polymorphism (tính đa hình) là khả năng của ngôn ngữ lập trình để biểu thị những interface (giao diện) giống nhau cho những kiểu dữ liệu cơ bản khác nhau. Kiểu đa hình là kiểu mà những xử lý bên trong nó có thể được áp dụng lên giá trị của những kiểu khác.
Inheritance
Kế thừa cung cấp cho đối tượng khả năng sử dụng được những trường (field), phương thức (method) từ những lớp khác, lớp đó gọi là lớp cơ bản (lớp cha, base class). Kế thừa cung cấp khả năng tái sử dụng mã lệnh và có thể được sử dụng để thêm những tính năng mới cho một lớp đã có trước nhưng không làm thay đổi lớp đó.
Abstraction
Abstraction một một quá trình để tách biệt những ý tưởng với những thực thể cụ thể và vì vậy, phát triển lớp trong những điều khoản (term) của các chức năng bên trong nhưng không cài đặt chi tiết những chắc năng đó. Java cung cấp khả năng khởi tạo lớp trừu tượng và những lớp trừu tượng đã có như interfaces (không phải cài đặt chi tiết cho tất cả các phương thức trong lớp trừu tượng). Kỹ thuật trừu tượng nhằm giúp tách biệt việc cài đặt chi tiết của lớp từ những hành vi của nó.
Khác biệt giữa Abstraction và Encapsulation
Abstraction và encapsulation là những khái niệm bổ sung cho nhau. Abstraction tập trung vào hành vi của đối tượng, encapsulation tập trung vào việc cài đặt hành vi của đối tượng. Encapsulation sẽ đạt được bằng cách ẩn trong tin trạng thái bên trong của một đối tượng và vì vậy, encapsulation cũng là một cách sử dụng cho tính trừu tượng.
Những kiến thức trên về hướng đối tượng của tác giả cung cấp rất chung chung, hơi khó hiểu nếu bạn chưa nắm rõ hướng đối tượng. Mọi người nên tìm hiểu sâu hơn về hướng đối tượng, vì đây là phần rất quan trọng trong các cuộc phỏng vấn (theo kinh nghiệm mình thấy), và nó cũng rất hay 😀
Effective Java – Joshua Bloch
Head first object-oriented analysis and design – Brett McLaughlin
Cuối vài câu hỏi, có thể mình sẽ để thêm một vài đường dẫn tham khảo thêm cho câu hỏi đó.

NHỮNG CÂU HỎI TỔNG QUÁT VỀ JAVA (GENERAL QUESTIONS ABOUT JAVA)

1. JVM là gì? Tại sao Java là một ngôn ngữ lập trình độc lập nền tảng (Platform Independent Programming Language) ?
Java Virtual Machine (JVM) là một tiến trình như một máy ảo để có thể thực thi đượcbytecode (Các bạn đọc thêm bytecode theo dường dẫn). Mỗi tập tin mã nguồn trong Java được biên dịch ra một tập tin bytecode và chúng được thực thi bởi JVM. Java được thiết kế để cho phép những chương trình ứng dụng có thể được dựng(build) lên và chạy trên bất kỳ nền tảng nào, mà không cần phải viết lại mã lệnh khác hoặc biên dịch lại mã nguồn cho mỗi nền tảng khác nhau. JVM làm được điều trên, bởi vì JVM có thể nhận biết được các tập lệnh cụ thể và đặc thù của từng nền tảng phần cứng bên dưới.
2. Sự khác nhau giữ JDK và JRE là gì?
JRE (The Java Runtime Environment) cơ bản chính là JVM, nơi mà chương trình được thực thi. Nó còn bao gồm những plugin (trình bổ trợ) cho trình duyệt thực thi applet. JDK (The Java Development) là một bộ phát triển phần mềm đầy đủ các tính năng hỗ trợ cho Java, gồm có JRE, trình biên dịch và những công cụ hỗ trợ khác (như JavaDoc, và Trình gỡ rỗi Java), giúp cho người dùng phát triển, biên dịch và thực thi một chương trình Java.
3. Ý nghĩ của từ khoá “static”(tĩnh) trong Java là gì? Chúng ta có thể override (đè) một hàm private hoặc static trong Java không?
Từ khoá “static” biểu thị cho biến hoặc phương thức có thể được truy cập (sử dụng) mà không cần tạo ra thực thể của lớp chứa nó. Người dùng không thể override(đè) phương thức static trong Java, bởi vì kỹ thuật đè (overriding) phương thức được dựa trên quá trình gán (binding) động khi runtime (khi chương trình đang chạy) và những phương thức static  được gán tĩnh trong thời gian biên dịch. Phương thức tĩnh không ràng buộc với thực thể của lớp nên phương thức tĩnh sẽ không thể override (đè).
4. Chúng ta có thể truy cập một biến không tĩnh(non-static) trong một ngữ cảnh static được không?
Một biến static phụ thuộc vào lớp của nó và giá trị của nó sẽ tồn tại (giữ) cho tất cả các thực thể của lớp đó. Biến static được tạo ra khi lớp chứa đó được tải (load) bởi JVM. Nếu cố gắng truy cập vào một biến non-static (trong hàm static) mà không có trong thực thể nào, thì trình biên dịch sẽ báo lỗi, bởi vì những biến đó(non-static) chưa được khởi tạo và chúng không có ràng buộc với bất kỳ thực thể nào.
5. Java hỗ trợ những kiểu dữ liệu nào? Thế nào là Autoboxing và Unboxing?
8 kiểu dữ liệu cơ bản (nguyên thuỷ, primitive data type) được hỗ trợ trong Java:
  • byte
  • short
  • int
  • long
  • float
  • double
  • boolean
  • char
Autoboxing là quá trình mà trình biên dịch của Java tự động chuyển đổi giữa kiểu dữ liệu cơ bản (primitive) về đối tượng tương ứng với lớp của kiểu dữ liệu đó. Ví dụ, trình biên dịch sẽ chuyển đổi kiểu dữ liệu int sang Integer, kiểu double sang Double, … tùm lum. Và ngược lại là unboxing.
6. Thế nào là phương thức nạp chồng (Overloading) và ghi đè (Overriding) trong Java?
Nạp chồng phương thức (method overrloading) xảy ra khi trong cùng một lớp có nhiều hơn hai phương thức có cùng tên, nhưng khác tham số (số lượng hoặc kiểu). Mặt khác, ghi đè phương thức (method overriding) được dùng trong trường hợp một lớp con muốn định nghĩa lại phương thức đã có ở  lớp cha. Phương thức ghi đè (Overridden methods) phải có tên, số lượng tham số, và kiểu trả về giống với lớp cha. Overriding method cũng không giới hạn việc truy cập vào phương thức nó đã ghi đè.
7. Hàm tạo (Constructor) là gì, Nạp chồng hàm tạo(Constructor Overloading) và sao chép hàm tạo (Copy-Constructor)?
Constructor được gọi khi một đối tượng được tạo ra. Mỗi lớp đều có một constructor. Trong trường hợp người lập trình không khai báo constructor cho lớp, trình biên dịch sẽ tạo một constructor mặc định cho lớp đó. Nạp chồng hàm tạo (Constructor overloading) cũng khá giống với nạp chồng phương thức (method overrloading). Các constructor khác nhau được tạo ra cho mỗi lớp đơn lẽ. Cuối cùng, Java không hỗ trợ sao chép hàm tạo như trong C++, nhưng khác biệt ở chỗ Java sẽ không tạo ra hàm tạo sao chép nếu bạn không tạo ra nó ( chơi chữ chỗ này, Java không hỗ trợ nhưng bạn có thể tự viết cái).
8. Có phải Java hỗ trợ đa thừa kế?
Không, Java không hỗ trợ đa thừa kế. Mỗi lớp có thể extend(kế thừa) chỉ được một lớp, nhưng có thể cài đặt nhiều interface.
9. Sự khác nhau giữa Interface và lớp Abstract (lớp trừu tượng)?
Java cung cấp và hỗ trợ cả abstract class và interface. Cả 2 sự cài đặt đều có chung một số đặc tính, nhưng chúng khác nhau một vài điểm:
  • Tất cả phương thức trong interface là abstract (trừu tượng). Nhưng, trong lớp abstract có thể chứa cả phương thức abstract hoặc không abstract (non-abstract)
  • Một lớp có thể cài đặt (implement) nhiều interface, nhưng chỉ được kế thừa (extend) một lớp abstract.
  • Để cài đặt một interface, lớp đó phải cài đặt tất cả các hàm được định nghĩa trong interface. Tuy nhiên, một lớp có thể không cài đặt tất cả các hàm đã định nghĩa trong lớp abstract. Mặc dù, trong trường hợp này, lớp con cũng phải định nghĩa là lớp abstract.
    Mình giải thích thêm chỗ này: Một lớp extend một lớp trừu tượng có thể không cần định nghĩa lại (override) các hàm non-abstract nhưng bắt buộc phải override các hàm abstract. Nếu lớp con cũng là một lớp abstract thì không cần định nghĩa lại hàm nào cả. Các bạn tìm hiểu thêm về lớp trừu tượng. Vì đây chỉ là phần so sanh với interface nên tác giả nói ý chung.
  • Lớp abstract có thể cài đặt một interface mà không cần cài đặt bất kỳ hàm nào của interface đó.
  • Các biến được định nghĩa trong interface mặc định là final, còn lớp abstract thì có thể không final (non-final).
  • Các thành phần trong interface mặc định là public, còn trong lớp abstract có thể là public, private hoặc protected (tuỳ vào người định nghĩa).
  • Interface là thuần trừu tượng, không thể tạo thực thể cho nó. Một lớp abstract cũng không thể tạo thực thể, nhưng nó có thể được gọi nếu chứa hàm main.
10. Thế nào là truyền tham chiếu và truyền tham trị?
Khi một đối tượng được truyền bằng tham trị, có nghĩa là truyền giá trị sao chép của nó. Vì vậy, mặc dù có sự thay đổi lên đối tượng đó thì giá trị gốc vẫn không bị thay đổi. Khi một đối tượng được truyền kiểu tham chiếu, thì đối tượng thật không được truyền mà truyền tham chiếu đến nó. Vì vậy, bất cứ sự thay đổi nào lên giá trị được truyền vào sẽ làm thay đổi ở tất cả các nơi sử dụng đối tượng đó.

LUỒNG TRONG JAVA (JAVA THREADS)

11. Khác biệt giữa tiến trình và luồng là gì?
Một tiến trình (process) là sự thực thi của chương trình, trong khi một luồng(thread) là một sự thực thi đơn lẻ có tuần tự bên trong tiến trình. Một tiến trình có thể chứa nhiều luồng. Một luồng đôi khi được xem như một tiến trình nhỏ (tiểu trình, lightweight process).
12. Giải thích sự khác nhau giữa các cách tạo luồng(thread). Cái nào bạn hay dùng hơn (prefer) và tại sao?
Có 3 cách để tạo ra một thread:
  • Một lớp kế thừa (extends) từ lớp Thread
  • Một lớp cài đặt interface Runnable
  • Một chương trình có thể sử dụng framwork Executor, để tạo là một thread pool (giống như cái hố chứa một đống luồng).
Cách hay được sử dụng và được yêu thích là dùng interface Runnable, bởi vì nó không yêu cầu phải tạo một lớp kế thừa từ lớp Thread. Trong trường hợp ứng dụng thiết kế yêu cầu sử dụng đa kế thừa, chỉ có interface mới có thể giúp giải quyết vấn đề. Ngoài ra, thread pool rất hiểu quả và có thể được cài đặt, sử dụng rất hơn giản.
13. Giải thích các trạng thái khả dụng (available) của thread trong high-level (cấp độ cao)
Trong suốt quá trình thực thi của nó, một thread có thể giữ một trong những trạng thái:
  • Runnable: Một thread sẵn sàng để chạy, nhưng không cần thiết chạy ngay lập tức.
  • Running: Tiến trình đang chạy mã lệnh trong luồng.
  • Waiting: Một thread trong trạng thái dừng(nghẽn, blocked) để chờ một tiến trình khác chạy chấm dứt.
  • Sleeping: Một thread đang ngủ (dừng hoạt động, sleeping).
  • Blocked on I/O: Chờ một thao tác I/O(xuất nhập) hoàn thành.
  • Blocked on Synchronization: Đang chờ trong trạng thái bị khoá.
  • Dead: Một thread thực thi xong các dòng lệnh của nó.
14. Sự khác biệt giữa phương thức đồng bộ (synchronized method) và khối đồng bộ (synchronized block)?
Trong lập trình Java, mỗi đối tượng đều có một khoá (chốt, lock). Một thread có thể chốt (khoá) được đối tượng bằng cách sử dụng từ khóa  synchronized. Từ khoá synchronized có thể được áp dụng trong phương thức (method, cách khoá dở ẹt (coarse) ) và khối lệnh (block, cách khoá tốt (fine)).
Tác giả trả lời cho câu hỏi này khá chung và không đầy đủ cho câu hỏi, các bạn tham khảo thêm đường dẫn http://java67.blogspot.com/2013/01/difference-between-synchronized-block-vs-method-java-example.html (Mình sẽ cố gắng dịch bài này sau)
15. Một thread đồng bộ xảy ra bên trong một monitor như thế nào? Những cấp đồng bộ có thể được áp dụng là gì?
JVM sử dụng các khoá như sự liên kết với các monitor (các chương trình giám sát). Một monitor cơ bản là một người bảo vệ quan sát các mã lệnh tuần tự và đảm bảo chỉ một thread duy nhất tại một thời điểm thực thi được các dòng lệnh đồng bộ. Mỗi monitor gắn sát với một đối tượng tham chiếu. Thread sẽ không được phép thực tin mã lệnh trong khi nó (mã lệnh) đang được khoá (lock).
16. Deadlock(Khoá chết) là gì? 
Xảy ra khi 2 tiến trình đợi nhau hoàn thành, trước khi chạy. Kết quả của quá trình là cả 2 tiến trình không bao giờ kết thúc.
17. Làm sao để đảm bảo N thread truy cập vào N tài nguyên (resources) mà deadlock không xảy ra?
Một cách đơn giản để tránh deadlock trong khi sử dụng N thread là phải áp đặt thứ tự của các khoá (lock) và ép các thread theo sự sắp sếp đó. Vì vậy, tất cả các thread khoá và mở khoá như nhau thì deadlock sẽ không xảy ra.
Thread (Concurrency, Multithread) là chủ đề khá khó trong lập trình nói chung và cho Java nói riêng, các câu hỏi của tác giả mình thấy khá sơ sài và câu trả lời rất chung chung. Các bạn nên đào sau tìm hiểu về thread vì đây là chủ đề rất quan trọng trong lập trình, giúp bạn có cái nhìn sâu sắc hơn về hệ thống và luồng xử lý trong một chương trình phức tạp ngày nay.

TẬP HỢP TRONG JAVA (JAVA COLLECTIONS)

18. Những interface cơ bản trong Java Collections Framework?
Java Collection Framework cung cấp những thiết kế các interface và class để hỗ trợ việc thao tác trên tập hợp của các đối tuợng. Những interface cơ bản nhất đuợc cung cấp trong Java Collections Framework:
  • Collection, biểu thị cho nhóm các đối tuợng, những đối tuợng này đưọc gọi là phần tử của tập hợp.
  • Set, là một tập hợp mà không chứa những phần từ trùng nhau.
  • List, là một tập hợp đã sắp sếp và có thể chứa những phần tử trùng nhau.
  • Map, là một đối tuợng mà ánh xạ các khoá vào các giá trị và không chứa những khoá trùng nhau.
19. Tại sao Colection (interface) không kế thừa (extend) interface Cloneable và Serializable?
Interface Collection biểu thị một nhóm các đối tuợng biết đến như phần tử trong tập hợp. Mỗi sự cài đặt cụ thể của Collection có thể lựa chọn cách riêng để bảo trì và sắp sếp phần tử của nó (lớp cài đặt). Một số tập hợp chấp nhập trùng khoá, trong khi một số thì không. Mục đích và ý nghĩa của clone(bản sao) và serialization đuợc sử dụng trong những cài đặt thật. Vì vậy, những cài đặt cụ thể của tập hợp sẽ quyết định chúng sẽ sử dụng clone và serialization như thế nào.
20. Thế nào là Iterator?
Interface Iterator cung cấp một số các phương thức để duyệt(lặp) qua các phần tử bất kỳ tập hợp nào. Mỗi interface Collection trong Java đều chứa một phương thức iterator để trả về một thực thể của interface Iterator. Iterator có khả năng xoá những phần từ tập hợp trong quá trình lặp.
21. Sự khác biệt giữa Iterator và ListIterator?
Vài sự khác nhau của 2 interface trên:
  • Iterator đưọc sử dụng để duyệt qua(lặp qua) các interface Set và List, trong khi ListIterator chỉ đuợc sử dụng để duyệt qua List
  • Iterator có thể duyệt qua tập hợp chỉ một huớng, trong khi ListIterator có thể duyệt qua List tất cả các huớng (2 huớng).
  • ListIterator cài đặt interface Iterator và chứa thêm một số chức năng mới, như thêm mới một phần tử, thay thế phần từ, lấy chỉ mục (index) cho phần từ kế truớc hay sau nó, etc.
22. Sự khác nhau giữa fail-fast và fail-safe?
Thuộc tính fail-fast trong interface Iterator làm việc với bản sao của tập hợp và vì vậy, nó không ảnh huởng đến bất kỳ sự thay đổi trong tập hợp. Tất cả các lớp tập hợp trong java.util là fail-fast, trong khi các lớp trong java.util.concurrent là fail-safe. Fail-fast ném ra ngoại lệ ConcurrentModificationException, trong khi fail-safe không bao giờ ném ra ngoại lệ như thế.
23. HashMap trong Java làm việc như thế nào?
HashMap trong Java chứa những cặp khoá-giá trị. HashMap yêu cầu một hàm băm và sử dụng phương thức hashCode và equals để thêm vào và lấy lại phần từ một tập hợp tương ứng. Khi hàm put (đẩy vào, thêm vào) đuợc gọi, HashMap tính toán giá trị hash(giá trị băm) của khoá và lưu trữ cặp giá trị (key-value) đuợc đánh chỉ mục thích hợp vào tập hợp. Nếu khoá đã tồn tại, giá trị của nó đuợc cập nhập(update) bằng giá trị mới. Một vài đặc tính quan trọng của HashMap là mức chứa của nó, yếu tố tải dữ liệu và ngưỡng thay đổi kích thước tập hợp.
24. Sự quan trọng của hàm hashCode và equals là gì?
HashMap trong Java sử dụng 2 hàm hashCode và equals để xác định chỉ mục của cặp khoá-giá trị(key-value). 2 hàm này còn được sử dụng khi chúng ta yêu cầu giá trị của một khoá cụ thể. Nếu 2 hàm này không đuợc cài đặt(implement) chính xác, như 2 khoá khác nhau lại cho ra hash code (giá trị đã băm) giống nhau và vì vậy, chúng sẽ đuợc xem như là bằng nhau trong tập hợp.Xa hơn nữa, 2 hàm này còn sử dụng để phát hiện trùng lặp. Nên, việc cài đặt 2 hàm là yếu tốt then chốt để kiểm tra tính đúng đắn của HashMap.
25. Sự khác nhau giữa HashMap và Hashtable?
Cả HashMap và Hashtable đều cài đặt interface Map và vì vậy, chúng có nhiều đặc tính giống nhau. Tuy nhiên, chúng khác nhau vài điểm:
  • HashMap chấp nhận giá trị khoá hoặc giá trị(value) null, trong khi Hashtable thì không (cả key và value).
  • Hashtable thì đồng bộ (synchronized), HashMap thì không. Vì vậy, HashMap đuợc sử dụng nhiều trong môi truờng đơn luồng(single-thread), còn Hashtable sử dụng trong môi truờng đa luồng (multi-thread).
  • HashMap cung cấp bộ khoá cho nó và ứng dụng có thể lặp(duyệt) qua chúng. Vì vậy, HashMap là fail-fast(câu hỏi 22).Hastable thì cung cấp kiểu liệt kê (Enumeration) cho các khoá.
  • Hashtable đuợc xem như lớp legacy.
Mình không dịch đưọc từ legacy, mình thêm đuờng dẫn để các bạn đọc thêm legacy classes và interfaces là gì http://www.rapidprogramming.com/tutorial/JAVA-Legacy-classes-interfaces-145.
26.Sự khác nhau giữa Array và ArrayList? Khi nào chúng ta sẽ sử dụng Array thay vì ArrayList?
Array và ArrayList khác nhau :
  • Array có thể chứa kiểu dữ liệu cơ bản và đối tưọng, trong khi ArrayList chỉ chứa đối tuợng.
  • Array cố định số luợng phần từ, ArrayList thì động
  • ArrayList cung cấp nhiều hàm và chức năng hơn như addAll, removeAll, iterator, vv.
  • Đối với danh sách kiểu dữ liệu cơ bản, tập hợp (collection) sử dụng autoboxing để giảm viết mã. Tuy nhiên, điều đó sẽ làm chúng (collection) chạy chậm hơn khi làm việc với mảng kiểu dữ liệu cơ bản (fixed).
27. Sự khác biệt giữa ArrayList và LinkedList? 
Cả 2 ArrayList và LinkedList đều cài đặt interface List, nhưng chúng có vài điểm khác biệt:
  • ArrayList là một kiểu cấu trúc dữ liệu chỉ mục như Array. Nó cung cấp sự truy cập ngẫu nhiên vào phần tử với hiệu năng là O(1). Còn LinkedList chứa dữ liệu như một danh sách các phần tử và mỗi phần tử liên kết với phần tử truớc và sau nó. Trong truờng hợp này, thao tác tìm kiếm một phần tử mất thời gian là O(n).
  • Thao tác thêm và xoá phần tử của LinkedList sẽ nhanh hơn so với ArrayList, bởi vì không cần phải thay đổi kích thuớc hay cập nhập lại chỉ mục khi một phần tử được thêm vào.
  • ListedList tiêu hao nhiều bộ nhớ hơn ArrayList bởi vì mỗi phần tử (node) trong LinkedList chứa 2 tham chiếu, một cho phần tử phía trước và một cho phần tử sau nó.
28. 2 interface Comparable và Comparator là gì? Liệt kê điểm khác nhau giữa chúng.
Java cung cấp một interface là Comparable chỉ chứa một phuơng thức compareTo. Phương thức này so sánh 2 đối tuợng, để sắp đặt trật tự giữa chúng. Đặt biệt nó trả về một số dương, 0 hoặc số âm để cho biết đối tuợng nhận vào sẽ nhỏ hơn, bằng hay lớn hơn nó. Java cung cấp interface Comparator chứa 2 phuơng thức là compare và equals. Phuơng thức compare nhận vào 2 tham số và xác định trật tự (order) giữa chúng. Hàm trả về số duơng, 0 hoặc số âm để biểu thị tham số đầu tiên sẽ nhỏ, bằng hay lớn hơn tham số thứ 2. Phương thức equals yêu cầu một đối số là một đối tuợng và giúp xác định đối tuợng truyền vào có phải là một comparator. Hàm trả về true nếu đối tuợng truyền vào là một comparator và đuợc sắp xếp như một comparator.
29. Thế nào là Priority Queue?
PriorityQueue là một queue(hàng đợi) không giới hạn (unbound), dựa trên priority heap và phần tử của nó đuợc sắp sắp theo trật tự ban đầu. Tại thời gian tạo ra nó, chúng ta sẽ cung cấp một Comparator với nhiệm vụ là sắp xếp thứ tự các phần tử của PriorityQueue. PriorityQueue không chập giá trị null, bởi những đối tượnng đó không hề có thứ tự. Cuối cùng, PriorityQueue không thread-safe và nó sử dụng thời gian O(log(n)) cho thao tác enqueue(đẩy vào hàng đợi)  và dequeue (lấy ra khỏi hàng đợi).
30. Thế nào là Big-O notation, liệt kê một số ví dụ  trên các cấu trúc dữ liệu khác nhau?
Ký hiện big-O đơn giản là biểu thị khả năng của thuật toán khi mở rộng hay tính toán trong tình huống xấu nhất, như số luợng phần từ trong cấu trúc dữ liệu tăng lên. Ký hiệu O ngoài ra còn đuợc sử dụng để biểu thị cho cách hành vi khác như mức sử dụng bộ nhớ. Bởi vì những lớp Collection thật ra cũng là những cấu trúc dữ liệu, chúng ta thuờng sử dụng big-O để lựa chọn phuơng pháp cài đặt tốt nhất để sử dụng, dựa vào thời gian, bộ nhớ và kết quả. Big-O đưa ra chỉ số tốt về hiệu năng của dữ liệu lớn.
31. Khác biệt giữa mảng có thứ tự và mảng không thứ tự?
Lợi ích chính của mảng có thứ tự là thời gian tìm kiếm có độ phức tạp là O(logn), trong khi mảng không có thứ tự sẽ là O(n). Bất lợi của mảng có thứ tự là quá trình chèn thêm phần tử có độ phức tạp O(n), bởi vì những phần tử có giá trị lớn hơn phải di chuyển để chứa phần tử mới. Việc chèn thêm phần tử của mảng có thứ tự có thời gian cố định là O(1).
32. Những cách làm tốt nhất (best practices) liên quan đến  Collection trong Java?
  • Chọn loại collection phù hợp để sử dụng, dựa vào ứng dụng đang cần gì, và cốt yếu là hiệu năng (performance) khi sử dụng nó. Ví dụ, nếu kích cỡ của các phẩn tử là cố định và biết trước, chúng ta nên sử dụng Array thay vì ArrayList.
  • Một số lớp collection cho phép chúng ta đưa vào sức chứa khi khởi tạo (initial capacity). Vì vậy, nếu chúng ta ước lượng số lượng phần tử mà muốn lưu trữ, chúng ta có thể sử dụng nó (capacity) để tránh việc làm mới hay thay đổi kích thước mảng.
  • Luôn luôn sử dụng Generics cho các kiểu dữ liệu an toàn(type-safety), dễ đọc và tinh tế hơn. Ngoài ra, sử dụng Generics, bạn tránh được ClassCastException trong quá trình thực thi (runtime).
  • Sử dụng lớp bất biến(immutable classes) được cung cấp bởi JDK như khóa trong Map, để tránh việc cài đặt hàm hashCode và equals cho những lớp tự mình tùy chỉnh.
  • Program in terms of interface not implementation (Không biết dịch thế nào :D, sẽ cố gắng giải thích trong chú thích riêng)
  • Trả về một tập hợp hay mảng rỗng thay vì trả về giá trị null trong trường hợp collection thật sự rỗng.
33. Sự khác biệt giữa hai interfaces Enumeration và Iterator?
Enumeration nhanh gấp đôi so với Iterator và sử dụng rất ít bộ nhớ. Tuy nhiên, Iterator an toàn hơn Enumeration, bởi vì những thread ( luồng) khác không thể thay đổi đối tượng collection khi đang duyệt qua bởi Iterator. Ngoài ra, Iterator cho phép loại bỏ phần từ trong tập hợp, trong khi không thể làm điều đó với Enumeration.
34. Sự khác biệt giữa HashSet và TreeSet?
HashSet được cài đặt sử dụng bảng băm (hash table), nên những phần tử của nó không có thứ tự. Các phương thức add, remove và contains của HashSet có độ phức tạp là O(1). TreeSet được cài đặt sử dụng cấu trúc cây (tree structure). Những phần tử trong TreeSet được sắp xếp, nên các phương thức add, remove và contains có độ phức tạp O(logn).

GARBAGE COLLECTORS

35. Mục đích của bộ dọn rác (Garbage collection) trong Java là gì, và khi nào thì nó được sử dụng?
Mục đích của bộ dọn rác là để xác định và loại bỏ những đối tượng nào không còn cần thiết trong ứng dụng, để cho tài nguyên được tái sử dụng.
36. System.gc() và Runtime.gc() làm gì?
Những phương thức này có thể được sử dụng như một lời gợi ý đối với JVM, để khởi động một bộ dọn rác. Tuy nhiên, điều đó tùy vào JVM sẽ khởi động bộ dọn rác ngay lập tức hay đợi một thời gian sau.
37. Khi nào thì finalize() được gọi? Mục địch của finalization là gì?
Phương thức finalize được gọi bởi bộ dọn rác (garbage collector), trước khi giải phóng vùng nhớ của đối tượng. Thông thường, nó được gọi để giải phóng tài nguyên được giữ bởi đối tượng bên trong phương thức finalize.
38. Nếu một đối tượng được gán là null, có phải bộ dọn rác sẽ giải phóng vùng nhớ của đối tượng ngay tức khắc không?
Không, đối tượng đó sẽ vẫn được giữ trong bộ dọn rác đến lần dọn rác tiếp theo của bộ dọn rác.
39. Cấu trúc của Heap trong Java là gì? Thế nào là Perm Gem trong Heap?
Heap là vùng dữ liệu khi chương trình thực thi, vùng nhớ dành cho tất cả các lớp và mảng được cấp phát. Nó (heap) được khởi tạo khi JVM khởi động. Vùng nhớ heap được giải phóng bởi hệ thống quản lý bộ nhớ tự động, chính là bộ dọn rác (garbage collector). Vùng nhớ heap chứa cả đối tượng sống (live) và dead(chết). Những đối tượng sống (live) còn được truy cập bởi ứng dụng và sẽ không bị lệ thuộc vào bộ dọn rác. Những đối tượng chết(dead) là những đối tượng sẽ không giờ được truy xuất từ ứng dụng, nhưng chưa bao giờ được thu thập từ bộ dọn rác. Những đối tượng này vẫn chiếm giữ bộ nhớ đến khi một sự kiện dọn rác xảy ra.
40. Sự khác nhau giữa bộ dọn rác Serial và Throughput?
Bộ dọn rác throughput sử dụng tính toán song song của bộ dọn young generation và vì vậy nó được sử dụng trong những ứng dụng có bộ dữ liệu vừa và lớn. Còn bộ dọn Serial phù hợp với những ứng dụng nhỏ.
41. Khi nào thì một đối tượng trở thành đối tượng phù hợp vào bộ dọn rác?
Khi đối tượng không còn truy cập từ chương trình mà nó đang được sử dụng.
42. Có phải quá trình dọn rác xảy ra trong vùng Permanent Generation(PermGen) trong JVM không?
Bộ dọn rác xảy ra trong vùng PermGen và nếu PermGen đầy hay vượt ngưỡng, nó có thể gây nên đầy bộ dọn rác. Nếu bạn nhìn kỹ vào output(xuất) của bộ dọn rác, bạn sẽ thấy là PermGen cũng là bộ dọn rác. Đó là lý do tại sao phải nhập đúng dung lượng của PermGen để tránh xảy ra đầy bộ dọn rác.

EXCEPTION HANDLING

43. Hai loại exception(ngoại lệ) trong java là gì? Điểm khác biệt của chúng?
Java có 2 loại exception: checked exception và unchecked exception. Unchecked exception không cần phải khai báo trong hàm hay trong hàm khởi tạo ném ra loại lệ, nếu chúng có thể bị ném ra bởi một exception trong hàm hay hàm khởi tạo, thì sẽ truyền ra ngoài hàm hay hàm khởi tạo gọi chúng. Checked exception phải được khai báo bên trong hàm hoặc hàm khởi tạo. Xem thêm về Java Exception.
44. Sự khác nhau giữa Exception và Error trong Java là gì?
2 lớp Exception và Error đều là subclass(lớp con) của lớp Throwable. Lớp Exception được sử dụng cho ngoại lệ có điều kiện mà chương trình nên bắt. Lớp Error định nghĩa các ngoại lệ mà không thể bắt (catch) từ chương trình.
45. Sự khác nhau giữa throw và throws?
Từ khóa throw được sử dụng tường minh để tạo (raise) ngoại lệ trong chương trình. Còn throws được sử dụng để biểu thị những exception không được xử lý bởi hàm. Mỗi hàm phải chỉ ra được exception nào không được xử lý, vì vậy người gọi hàm đó có thể bảo vệ nó dựa vào các exception có thể xảy ra. Cuối cùng, nhiều exception được ngăn cách bằng dấu , (comma).
45. Khối Finally trong Exception quan trọng thế nào?
Khối finally sẽ luôn luôn được chạy (execute) cho dù exception có xảy ra hay không. Ngay trong trường hợp khối lệnh catch bị bỏ qua và exception ném ra trong khối đó, khối lệnh finally vẫn sẽ được thực thi. Điều cuối cùng được đề cập về khối lệnh finally, nó được sử dụng để giải phóng tài nguyên như I/O buffers, database connection (kết nối cơ sở dư liệu), v.v..
46. Chuyện gì xảy ra với đối tượng Exception sau khi exception được sử lý?
Đối tượng Exception sẽ được bộ dọn rác xóa trong chu kỳ dọn rác tiếp theo của nó.
47. Hàm finalize() và khối finally khác nhau như thế nào?
Khối lệnh finally sẽ được thự thi cho dù exception có xảy ra hay không và được sử dụng để giải phóng tài nguyên bị giữ bỏi ứng dụng. Fianlize là một hàm protected (modifier) của lớp Object, được gọi bởi JVM trước khi đối tượng đó được xử lý bởi bộ dọn rác.
Mình xin tạm dừng việc dịch bài 115 câu phỏng vấn java, vì các phần sau là những thành phần của J2EE, và là cả một mảng kiến thức rộng. Các câu hỏi sau các bạn có thể tham khảo bài viết gốc dùm mình, cũng khá dễ đọc. Các câu hỏi và câu trả lời thật sự không được sâu,  các bạn đọc qua câu hỏi nếu cảm thấy mình không trả lời được thì tìm hiểu sâu về các mảng đó (Mỗi mảng có thể là một cuốn sách :D)
Cảm ơn các bạn đã ghé thăm và đọc bài viết của mình, có gì sai sót các bạn comment để mình sửa.
Từ khoá, chìa khoá bắt đầu tìm kiếm và nghiên cứu vấn đề, mình chỉ cố gắng cung cấp tất cả những từ khoá mình biết để các bạn tìm hiểu trên mạng. Mình dịch cực kỳ tệ, rất lủng cũng và khó hiểu, với từ khoá và địa chỉ nguồn bài viết, mình khuyến khích các bạn nên đọc các bài viết tiếng Anh và tìm hiểu sâu hơn những từ khoá có trong bài viết của mình :)


Bài mới

Bài đăng nổi bật