В этой статье вы узнаете и поймете, How работает такое явление в Java, How StackTrace, так же известное How "Трассировка стека вызовов". Эта информация была структурирована для новичков, столкнувшихся с этим понятием в начале девятого уровня Java Syntax. Я думаю все из вас, хоть раз, но встречали похожие ошибки при работе в вашем IDE, независимо от того будь это Idea, Eclipse or что-то другое.
Exception in thread "main" java.lang.ArithmeticException
at com.example.task01.Test.division(Test.java:10)
at com.example.task01.Test.main(Test.java:6)
Это, How вы уже догадались и есть наша трассировка. Но не спешите паниковать, сейчас мы с вами разложим данный пример на пальцах. Для начала необходимо понять тот факт, что StackTrace
работает How Стэк
и это видно из его названия. На этом месте мы остановимся чуть поподробнее. На восьмом уровне вы уже познакомorсь с коллекциями и знаете что они делятся на три группы Set
— множество, List
— список, Map
— словарь (or карта). По мнению JavaRush (c). Наш Stack
входит в группу List
. Принцип его работы можно описать How LIFO, что расшифровывается How Last In First Out(Последний пришел, первый ушел). А именно это такой список похожий на стопку книг, чтобы взять элемент который мы положor в Stack
первым, нам необходимо сначала извлечь все элементы которые мы добавor в наш список после. Как это указано на картинке выше в отличии например от обычного списка ArrayList
где мы можем получить любой элемент из списка по индексу. Еще раз для закрепления. Получение element из Стэка
возможно только с конца! В то время How первый добавленный в него элемент находится в начале(or на дне How удобнее). Вот Howие методы имеет наш Stack
Object push()
- Добавляет элемент в верх стека. Object pop()
- returns элемент, находящийся в верхней части стэка, удаляя его в процессе. Object peek()
- returns элемент, находящийся в верхней части стэка, но не удаляет его. int search()
- Ищет элемент в стеке. Если найден, возвращается его смещение от вершины стека. В противном случае возвращается -1. boolean empty()
- Проверяет, является ли стек пустым. returns true, если стек пустой. returns false, если стек содержит элементы. Так для чего же в Java
нужен StackTrace
построеный на принципах работы Stack
? Давайте разберем пример ошибки ниже, которая возникла в процессе выполнения такой вот простой программы.
public class Test {
public static void main(String[] args) {
System.out.println(convertStringToInt(null));
}
public static int convertStringToInt(String s) {
int x = Integer.parseInt(s);
return x;
}
}
У нас есть класс Test
с двумя методами. Всем привычный main
и convertStringToInt
логика которого заключается в конвертировании и возврате полученной извне(а именно из метода main
) строки в целочисленное число типа int
. Как вы видите мы намеренно передали instead of строки с Howой-нибудь цифрой, параметр null
. Данный параметр наш метод не смог правильно обработать и вызвал ошибку NumberFormatException
. Как вы знаете программа начинает отрабатывать свою работу из метода main
и в этот момент она создает новый Стэк
с названием StackTrace
куда кладет текущее meaning ее работы под номером 1, далее мы переходим в метод convertStringToInt
и программа опять заносит параметры нашего нахождения в созданный ранее StackTrace
под номером 2, далее вызывается не видимый нашему глазу метод parseInt
находящийся в классе Integer
и это уже будет элемент под номером 3 нашего StackTrace
, в этом методе будет еще один внутренний вызов добавленный в StackTrace
под номером 4 для проверки element на null который и приведет к ошибке. Программе необходимо вывести нашу ошибку с указанием всей цепочки наших переходов до момента возникновения ошибки. Тут то ей и приходит на помощь ранее созданный StackTrace
с данными наших переходов.
Exception in thread "main" java.lang.NumberFormatException: null
at java.base/java.lang.Integer.parseInt(Integer.java:614)
at java.base/java.lang.Integer.parseInt(Integer.java:770)
at com.example.task01.Test.convertStringToInt(Solution.java:10)
at com.example.task01.Test.main(Solution.java:6)
До возникновения ошибки, программа шла вглубь методов, но How только возникла ошибка, все начинает происходить в обратном порядке. Печатается строка с описанием проблемы(№1 на примере), далее берется последнее (и находящееся на вершине) добавленное meaning в наш Стэк
оно было под номером четыре и печатается в консоль(№2 на примере) и мы видим что проблема возникла в классе Integer
на 614 строке codeа и вызвала эту строку, строка 770 метода parseInt
того же класса(№3 на примере) которая при добавлении в Стэк
была под номером три и этот метод класса Integer
все еще не видимый нам был вызван уже нашим методом convertStringToInt
располагающемся на 10 строке нашей программы(№4 на примере, а при добавлении он был вторым), а его в свою очередь вызвал main
на 6 строке(№5 на примере, а при добавлении соответственно первый). Вот так вот, складируя в Стек
шаг за шагом наши вызываемые методы мы смогли вернуться обратно в main
параллельно печатая информацию что именно привело нас к ошибке. Но StackTrace
это не только работа с ошибками, он позволяет получить нам кучу интересной информации о процессе работы нашего applications. Давайте разберем еще один популярный пример в комментариях к основной лекции 9го уровня. У нас есть code и к нему сразу прикреплю картинку визуализирующую процесс работы программы:
public class Test {
public static void main(String[] args) {
method1();
method2();
}
public static void method1() {
//не вызывает ничего
}
public static void method2() {
method3();
method4();
}
public static void method3() {
//не вызывает ничего
}
public static void method4() {
method5();
}
public static void method5() {
StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
for (StackTraceElement element:stackTraceElements) {
System.out.println(element.getMethodName());
}
}
}
Тут наша программа безошибочно выполняет свою работу и заканчивается. Вот что мы увидим в выводе консоли:
getStackTrace
method5
method4
method2
main
Process finished with exit code 0
Как у нас получился такой вывод и что же произошло в пятом методе начиная с 20й строки? Боюсь самое лучше что я смогу сделать это добавить самое популярное объяснение(в сокращении) юзера Кирилла из комментариев к лекции. Обратимся к строчке по созданию StackTrace
и разберем ее поэлементно:
StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
StackTraceElement[]
- указание на тип массива(На ранних уровнях вы уже проходor массивы типа int[], String[], вот тут тоже самое). stackTraceElements
- Name массива, может быть любым с учетом общих правил наименования на работу эту не влияет. Thread.currentThread()
- получение ссылки на текущий поток, в котором выполняются методы, которые мы хотим отследить(пока это не важно, подробнее потоки вы будете разбирать на 16 уровне в квесте Java Core) getStackTrace()
- получаем весь Стэк
вызываемых методов(Это обычный геттер для StackTrace
) Теперь посмотрим, чем нам может быть полезен созданный массив. Мы понимаем, что в массиве хранится инфа о выполненных методах.(с) И для этого в 21й строке мы запускаем модифицированный цикл for
под названием forEach
(кстати кто еще не изучил этот цикл, советую почитать о нём) и выводим данные из массива в консоль, а именно информацию Howие методы выполнялись в процессе работы посредством конструкции element.getMethodName()
. Внимание How мы видим нулевым элементом массива у нас оказался сам getStackTrace()
соответственно так How в момент получения массива данных он был последним методом что выполнился и тем самым оказавшись на верхушке Стэка
, а помня про нашу конструкцию "Последний пришел, первый ушел" сразу же первым добавляется в массив под нулевым элементом. Вот что еще мы можем получить из StackTraceElement
: String getClassName()
- returns Name класса. String getMethodName()
- returns Name метода. String getFileName()
- returns file name (в одном файле может быть много классов). String getModuleName()
- returns Name модуля (может быть null). String getModuleVersion()
- returns версию модуля (может быть null). int getLineNumber()
- returns номер строки в файле, в которой был вызов метода. Теперь, когда вы поняли общий принцип работы, советую вам самим опробовать разные методы StackTrace
в вашей Ide. Даже если вы не совсем всё усвоor, продолжайте обучение и мозаика сложится так же How сложилась у меня в данном вопросе. Желаю вам всем успехов! P.s. Если вам понравился данный материал, пожалуйста поддержите лайком. Вам не трудно, мне приятно. Спасибо и увидимся на 41 уровне ;)
GO TO FULL VERSION