CodeGym/Blog Java/Ngẫu nhiên/Khám phá các câu hỏi và câu trả lời từ một cuộc phỏng vấn...
John Squirrels
Mức độ
San Francisco

Khám phá các câu hỏi và câu trả lời từ một cuộc phỏng vấn việc làm cho vị trí nhà phát triển Java. Phần 1

Xuất bản trong nhóm
CHÀO! CodeGym đã tập hợp một nhóm người đa dạng. Một số người trong chúng tôi không muốn gì hơn là trở thành nhà phát triển Java và chúng tôi đang đầu tư rất nhiều thời gian và công sức vào việc phát triển. Những người khác đã là nhà phát triển Java. Trong cả hai trường hợp, bạn cần sẵn sàng để được kiểm tra trong các cuộc phỏng vấn kỹ thuật. Đây không phải là dễ dàng. Chúng đòi hỏi sự chuẩn bị cả về cảm xúc và kỹ thuật. Khám phá các câu hỏi và câu trả lời từ một cuộc phỏng vấn việc làm cho vị trí nhà phát triển Java.  Phần 1 - 1Gần đây tôi đã xem qua một số danh sách lớn các câu hỏi phỏng vấn cho vị trí nhà phát triển Java. Các câu hỏi được chia thành các cấp độ khác nhau: cơ sở, trung cấp và cao cấp. Đừng lo lắng: không phải tất cả các câu hỏi đều dễ dàng, nhưng những câu hỏi có dấu hoa thị hiếm khi được hỏi. Các câu hỏi rất hay, và tôi muốn cố gắng trả lời hầu hết chúng. Rõ ràng, điều này sẽ không phù hợp với tất cả trong một bài báo. Rốt cuộc, có rất nhiều câu hỏi ở đó. Điều đó có nghĩa là sẽ có cả một loạt bài viết với câu trả lời cho những câu hỏi phỏng vấn này. Tôi xin nhấn mạnh ngay một số điểm: các câu trả lời sẽ ngắn gọn, vì các câu trả lời được viết rất chi tiết có thể được kéo ra thành một bài viết riêng. Ngoài ra, tại các cuộc phỏng vấn không cần những câu trả lời quá chi tiết và đồ sộ, bởi vì người phỏng vấn của bạn chỉ có một giờ để phỏng vấn bạn về các chủ đề thiết yếu (và,

Q&A cho vị trí lập trình viên cơ sở

Câu hỏi chung

1. Bạn biết những mẫu thiết kế nào? Hãy cho chúng tôi biết về hai mẫu thiết kế mà bạn đã sử dụng trong công việc của mình.

Có rất nhiều mẫu khác nhau. Đối với những bạn muốn làm quen hoàn toàn với các mẫu thiết kế, tôi khuyên bạn nên đọc cuốn sách "Head First. Design Patterns". Nó sẽ giúp bạn dễ dàng tìm hiểu các chi tiết của các mẫu thiết kế cơ bản nhất. Về các mẫu thiết kế mà bạn có thể đề cập trong một cuộc phỏng vấn xin việc, hãy lưu ý những điều sau:
  • Trình tạo — một mẫu được sử dụng thường xuyên, một giải pháp thay thế cho cách tiếp cận cổ điển để tạo đối tượng;
  • Chiến lược - một mẫu về cơ bản đại diện cho tính đa hình. Nghĩa là, chúng ta có một giao diện, nhưng hành vi của chương trình thay đổi tùy thuộc vào việc triển khai giao diện cụ thể được truyền cho hàm (mẫu chiến lược hiện được sử dụng gần như ở mọi nơi trong các ứng dụng Java).
Nếu điều đó vẫn chưa đủ đối với bạn, hãy chú ý đến Spring (nếu bạn đã quen thuộc với nó), bởi vì nó là một nền tảng toàn bộ gồm các khung, do đó, thấm nhuần các mẫu từ đầu đến cuối. Dưới đây là một vài ví dụ về những gì tôi đang nói về:
  • Nhà máy - mẫu này có thể được tìm thấy trong ApplicationContext (hoặc trong BeanFactory);
  • Singleton — tất cả các bean đều là singletons theo mặc định;
  • Proxy - về cơ bản, mọi thứ trong Spring đều sử dụng mẫu này theo cách này hay cách khác, ví dụ: AOP;
  • Chuỗi trách nhiệm — một khuôn mẫu làm nền tảng cho Bảo mật mùa xuân;
  • Mẫu — được sử dụng trong Spring JDBC.

Lõi Java

Khám phá các câu hỏi và câu trả lời từ một cuộc phỏng vấn việc làm cho vị trí nhà phát triển Java.  Phần 1 - 2

2. Trong Java có những kiểu dữ liệu nào?

Java có các kiểu dữ liệu nguyên thủy sau:
  • byte — số nguyên nằm trong khoảng từ -128 đến 127, chiếm 1 byte;
  • ngắn — số nguyên nằm trong khoảng từ -32768 đến 32767, chiếm 2 byte;
  • int — các số nguyên từ -2147483648 đến 2147483647, chiếm 4 byte;
  • dài — các số nguyên nằm trong khoảng từ 9223372036854775808 đến 9223372036854775807, chiếm 8 byte;
  • float — số dấu phẩy động nằm trong khoảng từ -3.4E+38 đến 3.4E+38, chiếm 4 byte;
  • double — số dấu phẩy động nằm trong khoảng từ -1.7E+308 đến 1.7E+308, chiếm 8 byte;
  • char — các ký tự đơn trong UTF-16, chiếm 2 byte;
  • giá trị đúng/sai boolean , chiếm 1 byte.
Và có các kiểu dữ liệu tham chiếu trỏ đến các đối tượng trên heap.

3. Một đối tượng khác với các kiểu dữ liệu nguyên thủy như thế nào?

Sự khác biệt đầu tiên là dung lượng bộ nhớ bị chiếm dụng: các nguyên hàm chiếm rất ít vì chúng chỉ chứa giá trị của riêng chúng, nhưng các đối tượng có thể chứa nhiều giá trị khác nhau — cả nguyên hàm và tham chiếu đến các đối tượng khác. Điểm khác biệt thứ hai là: Java là một ngôn ngữ hướng đối tượng, vì vậy mọi thứ trong Java hoạt động là sự tương tác giữa các đối tượng. Nguyên thủy không phù hợp rất tốt ở đây. Trên thực tế, đó là lý do tại sao Java không phải là ngôn ngữ hướng đối tượng 100%. Điểm khác biệt thứ ba, tiếp theo sau điểm thứ hai là vì Java tập trung vào các tương tác đối tượng nên có nhiều cơ chế khác nhau để quản lý các đối tượng. Ví dụ: hàm tạo, phương thức, ngoại lệ (hoạt động chủ yếu với các đối tượng), v.v. Và để cho phép các hàm nguyên thủy hoạt động bằng cách nào đó trong môi trường hướng đối tượng này, những người tạo ra Java đã nghĩ ratrình bao bọc cho các loại nguyên thủy ( Integer , Character , Double , Boolean ...)

4. Sự khác nhau giữa truyền đối số theo tham chiếu và theo giá trị là gì?

Các trường nguyên thủy lưu trữ giá trị của chúng: ví dụ: nếu chúng ta đặt int i = 9; , thì trường i lưu trữ giá trị 9. Khi chúng ta có một tham chiếu đến một đối tượng, điều đó có nghĩa là chúng ta có một trường có tham chiếu đến đối tượng. Nói cách khác, chúng ta có một trường lưu địa chỉ của đối tượng trong bộ nhớ.
Cat cat = new Cat();
Điều này có nghĩa là các trường có tham chiếu đến một đối tượng cũng lưu trữ các giá trị . Giá trị của chúng là địa chỉ bộ nhớ. Nghĩa là, cat lưu địa chỉ bộ nhớ của đối tượng Cat() mới . Khi chúng ta truyền một đối số cho một phương thức, giá trị của nó sẽ được sao chép. Trong trường hợp nguyên thủy, giá trị của nguyên thủy được sao chép. Theo đó, phương pháp hoạt động với bản sao. Khi bản sao được thay đổi, bản gốc không bị ảnh hưởng. Trong trường hợp kiểu tham chiếu, giá trị của địa chỉ bộ nhớ được sao chép. Theo đó, cả hai biến tham chiếu sẽ lưu các địa chỉ trỏ đến cùng một đối tượng. Và nếu chúng ta sử dụng tham chiếu mới này để thay đổi đối tượng, thì chúng ta sẽ thấy rằng nó cũng được thay đổi đối với tham chiếu cũ. Rốt cuộc, cả hai đều trỏ đến cùng một đối tượng.

5. JVM, JDK và JRE là gì?

JVM là viết tắt của Java Virtual Machine , chạy Java bytecode do trình biên dịch tạo trước. JRE là viết tắt của Môi trường chạy thi hành Java . Về cơ bản, nó là một môi trường để chạy các ứng dụng Java. Nó bao gồm JVM, các thư viện tiêu chuẩn và các thành phần khác để chạy các applet và ứng dụng được viết bằng ngôn ngữ lập trình Java. Nói cách khác, JRE là một gói chứa mọi thứ cần thiết để chạy một chương trình Java đã biên dịch, nhưng nó không bao gồm các công cụ và tiện ích như trình biên dịch hoặc trình gỡ lỗi để phát triển ứng dụng. JDK là viết tắt của Java Development Kit , là phần mở rộng của JRE. Nghĩa là, nó là một môi trường không chỉ để chạy các ứng dụng Java mà còn để phát triển chúng. JDK chứa mọi thứ trong JRE, cùng với nhiều công cụ bổ sung khác - trình biên dịch và trình gỡ lỗi - cần thiết để tạo các ứng dụng Java (bao gồm các tài liệu Java). Khám phá các câu hỏi và câu trả lời từ một cuộc phỏng vấn việc làm cho vị trí nhà phát triển Java.  Phần 1 - 3

6. Tại sao lại sử dụng JVM?

Như đã nêu ở trên, Máy ảo Java là một máy ảo chạy mã byte Java đã được trình biên dịch tạo trước. Điều này có nghĩa là JVM không hiểu mã nguồn Java. Vì vậy, trước tiên, chúng tôi biên dịch các tệp .java . Các tệp đã biên dịch có phần mở rộng .classphần mở rộng và hiện ở dạng bytecode mà JVM hiểu được. JVM khác nhau đối với mỗi hệ điều hành. Khi JVM chạy các tệp mã byte, nó sẽ điều chỉnh chúng cho hệ điều hành mà nó đang chạy. Trên thực tế, do có các JVM khác nhau nên JDK (hoặc JRE) cũng khác nhau đối với các HĐH khác nhau (mỗi phiên bản cần có JVM riêng). Hãy nhớ cách phát triển hoạt động trong các ngôn ngữ lập trình khác. Bạn viết một chương trình, sau đó mã của chương trình được biên dịch thành mã máy cho một hệ điều hành cụ thể và sau đó bạn có thể chạy chương trình đó. Nói cách khác, bạn cần viết các phiên bản khác nhau của chương trình cho từng nền tảng. Nhưng việc xử lý mã kép của Java (biên dịch mã nguồn thành mã byte, sau đó xử lý mã byte bởi JVM) cho phép bạn tận hưởng những lợi ích của giải pháp đa nền tảng. Chúng tôi tạo mã một lần và biên dịch nó thành mã byte. Sau đó, chúng tôi có thể đưa nó vào bất kỳ hệ điều hành nào và JVM gốc có thể chạy nó. Và đây chính xác là huyền thoại của Javatính năng viết một lần, chạy mọi nơi . Khám phá các câu hỏi và câu trả lời từ một cuộc phỏng vấn việc làm cho vị trí nhà phát triển Java.  Phần 1 - 4

7. Mã byte là gì?

Như tôi đã nói ở trên, trình biên dịch chuyển đổi mã Java thành mã byte trung gian (chúng tôi đi từ các tệp có phần mở rộng .java sang các tệp có phần mở rộng .class). Theo nhiều cách, mã byte tương tự như mã máy, ngoại trừ tập lệnh của nó không dành cho bộ xử lý thực mà là bộ xử lý ảo. Điều đó nói rằng, nó có thể bao gồm các phần được thiết kế cho trình biên dịch JIT, trình biên dịch này tối ưu hóa việc thực thi lệnh cho bộ xử lý thực mà chương trình đang chạy trên đó. Biên dịch JIT, còn được gọi là biên dịch nhanh, là một công nghệ giúp tăng hiệu suất của chương trình mã byte bằng cách biên dịch mã byte thành mã máy hoặc định dạng khác trong khi chương trình đang chạy. Như bạn có thể đoán, JVM sử dụng trình biên dịch JIT khi chạy mã byte. Chúng ta hãy xem một số bytecode mẫu: Khám phá các câu hỏi và câu trả lời từ một cuộc phỏng vấn việc làm cho vị trí nhà phát triển Java.  Phần 1 - 5Không quá dễ đọc, eh? Tin tốt là hướng dẫn này không dành cho chúng tôi. Nó dành cho JVM.

8. Các tính năng của JavaBean là gì?

JavaBean là một lớp Java tuân theo các quy tắc nhất định . Dưới đây là một số quy tắc để viết JavaBean :
  1. Lớp phải chứa một hàm tạo trống (không có đối số) với công cụ sửa đổi truy cập công khai . Hàm tạo này cho phép tạo một đối tượng của lớp mà không gặp bất kỳ vấn đề không cần thiết nào (do đó không phải loay hoay với các đối số không cần thiết).

  2. Các trường nội bộ được truy cập thông qua các phương thức getset instance, các phương thức này phải có cách triển khai tiêu chuẩn. Ví dụ: nếu chúng ta có trường tên , thì chúng ta nên có getNamesetName , v.v. Điều này cho phép các công cụ (khung) khác nhau tự động lấy và đặt nội dung của bean mà không gặp bất kỳ khó khăn nào.

  3. Lớp phải ghi đè các phương thức equals() , hashCode()toString() .

  4. Lớp phải được tuần tự hóa. Nghĩa là, nó phải có giao diện đánh dấu Serializable hoặc triển khai giao diện Externalizable . Điều này là để trạng thái của bean có thể được lưu, lưu trữ và khôi phục một cách đáng tin cậy.

Khám phá các câu hỏi và câu trả lời từ một cuộc phỏng vấn việc làm cho vị trí nhà phát triển Java.  Phần 1 - 6

9. Lỗi OutOfMemory là gì?

OutOfMemoryError là một lỗi thời gian chạy nghiêm trọng liên quan đến Máy ảo Java (JVM). Lỗi này xảy ra khi JVM không thể phân bổ một đối tượng vì không có đủ bộ nhớ cho nó và trình thu gom rác không thể phân bổ thêm bộ nhớ. Một vài loại OutOfMemoryError :
  • OutOfMemoryError: Java heap space — đối tượng không thể được cấp phát trên Java heap do không đủ bộ nhớ. Lỗi này có thể do rò rỉ bộ nhớ hoặc do kích thước heap mặc định quá nhỏ đối với ứng dụng hiện tại.

  • OutOfMemoryError: Đã vượt quá giới hạn GC Overhead — bởi vì dữ liệu của ứng dụng hầu như không vừa trong đống, bộ thu gom rác chạy mọi lúc, khiến chương trình Java chạy rất chậm. Do đó, vượt quá giới hạn chi phí của trình thu gom rác và ứng dụng gặp sự cố với lỗi này.

  • OutOfMemoryError: Kích thước mảng được yêu cầu vượt quá giới hạn VM — điều này cho biết ứng dụng đã cố cấp phát bộ nhớ cho một mảng vượt quá kích thước heap. Một lần nữa, điều này có thể có nghĩa là không đủ bộ nhớ được phân bổ theo mặc định.

  • OutOfMemoryError: Metaspace — heap đã hết dung lượng được phân bổ cho siêu dữ liệu (siêu dữ liệu là hướng dẫn cho các lớp và phương thức).

  • OutOfMemoryError: yêu cầu byte kích thước cho lý do. Hết dung lượng hoán đổi — một số lỗi đã xảy ra khi cố cấp phát bộ nhớ từ heap và kết quả là heap thiếu đủ dung lượng.

10. Dấu vết ngăn xếp là gì? Làm sao để tôi có được nó?

Dấu vết ngăn xếp là danh sách các lớp và phương thức đã được gọi cho đến thời điểm này trong quá trình thực thi ứng dụng. Bạn có thể lấy dấu vết ngăn xếp tại một điểm cụ thể trong ứng dụng bằng cách thực hiện việc này:
StackTraceElement[] stackTraceElements =Thread.currentThread().getStackTrace();
Điều này mang lại cho chúng ta một mảng các StackTraceElements được sắp xếp theo thứ tự Last In First Out (LIFO) . Khám phá các câu hỏi và câu trả lời từ một cuộc phỏng vấn việc làm cho vị trí nhà phát triển Java.  Phần 1 - 7Trong Java, khi mọi người nói về theo dõi ngăn xếp, họ thường có nghĩa là theo dõi ngăn xếp được hiển thị trên bảng điều khiển khi xảy ra lỗi (hoặc ngoại lệ). Bạn có thể lấy dấu vết ngăn xếp từ các ngoại lệ như thế này:
StackTraceElement[] stackTraceElements;
try{
                ...
} catch (Exception e) {
   stackTraceElements = e.getStackTrace();
}
Và nếu chúng ta muốn hiển thị dấu vết ngăn xếp của một ngoại lệ trên bảng điều khiển:
try{
                ...
} catch (Exception e) {
  e.printStackTrace();
}
Ngoài ra, nếu xảy ra lỗi, ngoại lệ không được kiểm tra hoặc ngoại lệ được kiểm tra chưa được xử lý , thì chúng tôi sẽ tự động lấy dấu vết ngăn xếp của ngoại lệ trên bảng điều khiển khi ứng dụng gặp sự cố. Đây là một ví dụ nhỏ về dấu vết ngăn xếp trên bảng điều khiển: Khám phá các câu hỏi và câu trả lời từ một cuộc phỏng vấn việc làm cho vị trí nhà phát triển Java.  Phần 1 - 8Và trên lưu ý đó, chúng ta sẽ kết thúc cuộc thảo luận về chủ đề này ngày hôm nay.Khám phá các câu hỏi và câu trả lời từ một cuộc phỏng vấn việc làm cho vị trí nhà phát triển Java.  Phần 1 - 9
Đọc thêm:
Bình luận
  • Phổ biến
  • Mới
Bạn phải đăng nhập để đăng nhận xet
Trang này chưa có bất kỳ bình luận nào