1. Lấy dấu vết ngăn xếp
Ngôn ngữ lập trình Java cung cấp nhiều cách để lập trình viên lấy thông tin về những gì đang xảy ra trong một chương trình. Và không chỉ lời nói.
Ví dụ, sau khi các chương trình C++ được biên dịch, chúng trở thành một tệp lớn chứa đầy mã máy và tất cả những gì có sẵn cho một lập trình viên khi chạy là địa chỉ của khối bộ nhớ chứa mã máy hiện đang được thực thi. Không nhiều, hãy nói.
Nhưng đối với Java, ngay cả sau khi chương trình được biên dịch, các lớp vẫn là các lớp, các phương thức và biến không biến mất và lập trình viên có nhiều cách để lấy thông tin về những gì đang diễn ra trong chương trình.
dấu vết ngăn xếp
Ví dụ, tại thời điểm thực hiện chương trình, bạn có thể tìm ra lớp và tên của phương thức hiện đang được thực thi. Và không chỉ một phương thức — bạn có thể lấy thông tin về toàn bộ chuỗi lệnh gọi phương thức từ phương thức hiện tại trở lại phương main()
thức đó.
Một danh sách bao gồm phương thức hiện tại, phương thức đã gọi nó và phương thức đã gọi phương thức đó, v.v. được gọi là dấu vết ngăn xếp . Bạn có thể lấy nó với tuyên bố này:
StackTraceElement[] methods = Thread.currentThread().getStackTrace();
Bạn cũng có thể viết nó thành hai dòng:
Thread current = Thread.currentThread();
StackTraceElement[] methods = current.getStackTrace();
Phương thức tĩnh currentThread()
của Thread
lớp trả về một tham chiếu đến một Thread
đối tượng, chứa thông tin về luồng hiện tại, tức là luồng thực thi hiện tại. Bạn sẽ tìm hiểu thêm về các luồng trong Cấp độ 17 và 18 của nhiệm vụ Java Core .
Đối tượng này Thread
có một getStackTrace()
phương thức, trả về một mảng StackTraceElement
các đối tượng, mỗi đối tượng chứa thông tin về một phương thức. Khi được kết hợp với nhau, tất cả các phần tử này tạo thành một dấu vết ngăn xếp .
Ví dụ:
Mã số |
---|
|
Đầu ra bảng điều khiển |
|
Như chúng ta có thể thấy trong đầu ra giao diện điều khiển của ví dụ, getStackTrace()
phương thức trả về một mảng gồm ba phần tử:
getStackTrace()
phương pháp củaThread
lớptest()
phương pháp củaMain
lớpmain()
phương pháp củaMain
lớp
Từ dấu vết ngăn xếp này, chúng ta có thể kết luận rằng:
- Phương
Thread.getStackTrace()
thức được gọi bởiMain.test()
phương thức trên dòng 11 của tệp Main.java - Phương
Main.test()
thức được gọi bởiMain.main()
phương thức trên dòng 5 của tệp Main.java - Không ai gọi
Main.main()
phương thức này — đây là phương thức đầu tiên trong chuỗi các cuộc gọi.
Nhân tiện, chỉ một số thông tin có sẵn được hiển thị trên màn hình. Mọi thứ khác có thể được lấy trực tiếp từ StackTraceElement
đối tượng
2.StackTraceElement
Như tên gọi của nó, StackTraceElement
lớp này được tạo ra để lưu trữ thông tin về một phần tử theo dõi ngăn xếp , tức là một phương thức trong stack trace
.
Lớp này có các phương thức thể hiện sau:
Phương pháp | Sự miêu tả |
---|---|
|
Trả về tên của lớp |
|
Trả về tên của phương thức |
|
Trả về tên của tệp (một tệp có thể chứa nhiều lớp) |
|
Trả về số dòng trong tệp mà phương thức được gọi |
|
Trả về tên của mô-đun (có thể là null ) |
|
Trả về phiên bản của mô-đun (có thể là null ) |
Họ có thể giúp bạn có được thông tin đầy đủ hơn về ngăn xếp cuộc gọi hiện tại:
Mã số | Đầu ra bảng điều khiển | Ghi chú |
---|---|---|
|
|
tên lớp phương pháp tên tệp tên dòng số mô -đun tên mô - đun phiên bản tên lớp tên phương thức tên tệp tên dòng số mô -đun tên mô-đun phiên bản tên lớp phương pháp tên tệp tên dòng số mô-đun tên mô- đun phiên bản |
3. Ngăn xếp
Bạn đã biết dấu vết ngăn xếp là gì, nhưng ngăn xếp (lớp Stack) là gì?
Ngăn xếp là một cấu trúc dữ liệu mà bạn có thể thêm các phần tử vào và từ đó bạn có thể truy xuất các phần tử. Khi làm như vậy, bạn chỉ có thể lấy các phần tử từ cuối: trước tiên bạn lấy phần tử được thêm vào cuối cùng, sau đó là phần tử thứ hai đến phần tử cuối cùng được thêm vào, v.v.
Bản thân ngăn tên gợi ý hành vi này, giống như cách bạn tương tác với một chồng giấy. Nếu bạn đặt các trang 1, 2 và 3 trong một ngăn xếp, bạn phải lấy chúng theo thứ tự ngược lại: đầu tiên là trang thứ ba, sau đó là trang thứ hai và chỉ sau đó là trang đầu tiên.
Java thậm chí còn có một lớp tập hợp Stack đặc biệt có cùng tên và hành vi. Lớp này chia sẻ rất nhiều hành vi với ArrayList
và LinkedList
. Nhưng nó cũng có các phương thức thực hiện hành vi ngăn xếp:
phương pháp | Sự miêu tả |
---|---|
|
Thêm obj phần tử vào đầu ngăn xếp |
|
Lấy phần tử từ đỉnh ngăn xếp (độ sâu ngăn xếp giảm) |
|
Trả về mục ở đầu ngăn xếp (ngăn xếp không thay đổi) |
|
Kiểm tra xem bộ sưu tập có trống không |
|
Tìm kiếm một đối tượng trong bộ sưu tập và trả về đối tượng đóindex |
Ví dụ:
Mã số | Nội dung ngăn xếp (đỉnh của ngăn xếp ở bên phải) |
---|---|
|
|
Ngăn xếp được sử dụng khá thường xuyên trong lập trình. Vì vậy, đây là một bộ sưu tập hữu ích.
4. Hiển thị dấu vết ngăn xếp trong quá trình xử lý ngoại lệ
Tại sao danh sách các lệnh gọi phương thức được gọi là theo dõi ngăn xếp ? Bởi vì nếu bạn coi danh sách các phương thức là một tập giấy có tên phương thức, thì khi bạn gọi phương thức tiếp theo, bạn sẽ thêm một trang tính có tên phương thức đó vào tập giấy. Và tờ giấy tiếp theo nằm trên tờ giấy đó, v.v.
Khi một phương thức kết thúc, trang tính ở trên cùng của ngăn xếp sẽ bị xóa. Bạn không thể xóa một trang tính khỏi giữa ngăn xếp mà không xóa tất cả các trang tính phía trên nó. Tương tự như vậy, bạn không thể kết thúc một phương thức ở giữa chuỗi lệnh gọi mà không kết thúc tất cả các phương thức mà nó đã gọi.
ngoại lệ
Một cách sử dụng thú vị khác cho ngăn xếp là trong quá trình xử lý ngoại lệ.
Khi xảy ra lỗi trong một chương trình và một ngoại lệ được ném ra , ngoại lệ đó chứa dấu vết ngăn xếp hiện tại — một mảng bao gồm danh sách các phương thức bắt đầu, từ phương thức chính và kết thúc bằng phương thức xảy ra lỗi. Thậm chí còn có dòng ném ngoại lệ!
Dấu vết ngăn xếp này được lưu trữ bên trong ngoại lệ và có thể dễ dàng truy xuất từ ngoại lệ đó bằng phương pháp sau:StackTraceElement[] getStackTrace()
Ví dụ:
Mã số | Ghi chú |
---|---|
|
Bắt ngoại lệ Nhận dấu vết ngăn xếp đã tồn tại khi xảy ra lỗi. |
Đây là một phương thức của Throwable
lớp, vì vậy tất cả các hậu duệ của nó (tức là tất cả các ngoại lệ) đều có getStackTrace()
phương thức đó. Siêu tiện lợi nhỉ?
Hiển thị dấu vết ngăn xếp của ngoại lệ
Nhân tiện, Throwable
lớp này có một phương thức khác để làm việc với dấu vết ngăn xếp, một phương thức hiển thị tất cả thông tin theo dõi ngăn xếp được lưu trữ bên trong ngoại lệ. Nó được gọi là printStackTrace()
.
Khá thuận tiện, bạn có thể gọi nó trên bất kỳ ngoại lệ nào.
Ví dụ:
Mã số |
---|
|
Đầu ra bảng điều khiển |
|
GO TO FULL VERSION