1. Получаване на проследяване на стека
Езикът за програмиране Java предлага много начини за програмиста да получи информация за това, което се случва в програмата. И не само на думи.
Например, след като C++ програмите са компorрани, те се превръщат в един голям файл, пълен с машинен code, и всичко, което е достъпно за програмиста по време на изпълнение, е addressът на блока памет, който съдържа машинния code, който се изпълнява в момента. Не много, да кажем.
Но за Java, дори след като програмата е компorрана, класовете си остават класове, методите и променливите не изчезват и програмистът има много начини да получи информация за това, което се случва в програмата.
Проследяване на стека
Например, в момент от изпълнението на програма, можете да разберете класа и името на метода, който се изпълнява в момента. И не само един метод — можете да получите информация за цялата верига от извиквания на метод от текущия метод обратно към метода main()
.
Списък, който се състои от текущия метод и метода, който го е извикал, и метода, който е извикал този и т.н., се нарича проследяване на стека . Можете да го получите с това изявление:
StackTraceElement[] methods = Thread.currentThread().getStackTrace();
Можете също да го напишете като два реда:
Thread current = Thread.currentThread();
StackTraceElement[] methods = current.getStackTrace();
Статичният currentThread()
метод на Thread
класа връща препратка към Thread
обект, който съдържа информация за текущата нишка, т.е. текущата нишка на изпълнение. Ще научите повече за нишките в нива 17 и 18 на мисията Java Core .
Този Thread
обект има getStackTrace()
метод, който връща масив от StackTraceElement
обекти, всеки от които съдържа информация за метод. Взети заедно, всички тези елементи образуват проследяване на стека .
Пример:
Код |
---|
|
Конзолен изход |
|
Както можем да видим в конзолния изход на примера, getStackTrace()
методът върна масив от три елемента:
getStackTrace()
метод наThread
класаtest()
метод наMain
класаmain()
метод наMain
класа
От това проследяване на стека можем да заключим, че:
- Методът
Thread.getStackTrace()
беше извикан отMain.test()
метода на ред 11 на file Main.java - Методът
Main.test()
беше извикан отMain.main()
метода на ред 5 на file Main.java - Никой не е извикал
Main.main()
метода — това е първият метод във веригата от извиквания.
Между другото, само част от наличната информация се показваше на екрана. Всичко останало може да се получи директно от StackTraceElement
обекта
2.StackTraceElement
Както подсказва името му, StackTraceElement
класът е създаден, за да съхранява информация за елемент на проследяване на стека , т.е. един метод в stack trace
.
Този клас има следните методи за екземпляри:
Метод | Описание |
---|---|
|
Връща името на класа |
|
Връща името на метода |
|
Връща името на file (един файл може да съдържа няколко класа) |
|
Връща номера на реда във file, където е извикан методът |
|
Връща името на модула (това може да бъде null ) |
|
Връща versionта на модула (това може да бъде null ) |
Те могат да ви помогнат да получите по-пълна информация за текущия стек от повиквания:
Код | Конзолен изход | Забележка |
---|---|---|
|
|
име на клас име на метод име на файл име на ред номер на модул име на version version на клас име на метод име на файл име на ред номер на модул име на модул version име на клас име на метод име на файл име на ред номер на модул име на модул version |
3. Стек
Вече знаете Howво е проследяване на стека , но Howво е стек (клас на стека)?
Стекът е структура от данни, към която можете да добавяте елементи и от която можете да извличате елементи. При това можете да вземете елементи само от края: първо вземате последния добавен, след това предпоследния добавен и т.н.
Самият стек с имена предполага това поведение, като How бихте взаимодействали с купчина documentи. Ако поставите листове 1, 2 и 3 в стек, трябва да ги извлечете в обратен ред: първо третия лист, след това втория и едва след това първия.
Java дори има специален клас за събиране на Stack със същото име и поведение. Този клас споделя много поведения с ArrayList
и LinkedList
. Но също така има методи, които прилагат поведението на стека:
Методи | Описание |
---|---|
|
Добавя obj елемента в горната част на стека |
|
Взема елемента от върха на стека (дълбочината на стека намалява) |
|
Връща елемента в горната част на стека (стекът не се променя) |
|
Проверява дали колекцията е празна |
|
Търси обект в колекцията и го връщаindex |
Пример:
Код | Съдържание на стека (горната част на стека е вдясно) |
---|---|
|
|
Стековете се използват доста често в програмирането. Така че това е полезна колекция.
4. Показване на проследяване на стека по време на обработка на изключение
Защо списък с извиквания на методи се нарича проследяване на стека ? Защото, ако си представите списъка с методи като стек от листове хартия с имена на методи, тогава, когато извикате следващия метод, вие добавяте лист с името на този метод към стека. И следващият лист хартия отива отгоре и така нататък.
Когато даден метод приключи, листът в горната част на стека се премахва. Не можете да премахнете лист от средата на стека, без да премахнете всички листове над него. По същия начин не можете да прекратите метод в средата на верига от повиквания, без да прекратите всички методи, които е извикал.
Изключения
Друга интересна употреба на стекове е по време на обработка на изключения.
Когато възникне грешка в програма и бъде хвърлено изключение , изключението съдържа текущото проследяване на стека — масив, състоящ се от списък с методи, започвайки от основния метод и завършвайки с метода, при който е възникнала грешката. Има дори реда, където е хвърлено изключението!
Това проследяване на стека се съхранява в изключението и може лесно да бъде извлечено от него чрез следния метод:StackTraceElement[] getStackTrace()
Пример:
Код | Забележка |
---|---|
|
Улавяне на изключението Вземете проследяването на стека, което е съществувало, когато е възникнала грешката. |
Това е метод на Throwable
класа, така че всички негови потомци (т.е. всички изключения) имат getStackTrace()
метода. Супер удобно, а?
Показване на трасирането на стека на изключението
Между другото, Throwable
класът има друг метод за работа с проследяване на стека, метод, който показва цялата информация за проследяване на стека, съхранена в изключението. Нарича се printStackTrace()
.
Доста удобно, можете да го извикате по всяко изключение.
Пример:
Код |
---|
|
Конзолен изход |
|
GO TO FULL VERSION