Bu yazıda siz Zəng Yığını İzləmə kimi də tanınan Java fenomeni StackTrace-in necə işlədiyini öyrənəcək və başa düşəcəksiniz. Bu məlumat Java Syntax Level 9-un əvvəlində bu konsepsiya ilə qarşılaşan yeni başlayanlar üçün strukturlaşdırılmışdır. Düşünürəm ki, IDE , Eclipse və ya başqa bir şey olmasından asılı olmayaraq, hamınız ən azı bir dəfə IDE-də işləyərkən oxşar səhvlərlə qarşılaşmısınız .
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)
Bu, təxmin etdiyiniz kimi, bizim izləməmizdir. Ancaq panikləməyə tələsməyin, indi bu nümunəni sizin üçün parçalayacağıq. StackTrace
Əvvəlcə onun adından da göründüyü kimi işlədiyini başa düşməlisiniz Стэк
. Bu nöqtədə bir az daha ətraflı dayanacağıq. Səkkizinci səviyyədə siz artıq kolleksiyalarla tanış olmusunuz və bilirsiniz ki, onlar üç qrupa bölünür Set
- toplu, List
- siyahı, Map
- lüğət (və ya xəritə). JavaRush-a (c) görə . Bizimkilər Stack
qrupun bir hissəsidir List
. Onun iş prinsipini LIFO kimi təsvir etmək olar, hansı ki, Last In First Out deməkdir . Məhz bu, kitab yığınına bənzər bir siyahıdır; ilk daxil etdiyimiz elementi götürmək üçün Stack
əvvəlcə siyahımıza sonra əlavə etdiyimiz bütün elementləri çıxarmalıyıq. Yuxarıdakı şəkildə göstərildiyi kimi, məsələn, ArrayList
siyahıdan istənilən elementi indekslə əldə edə biləcəyimiz adi siyahıdan fərqli olaraq. Bir daha gücləndirmək üçün. Bir elementi əldə etmək Стэка
yalnız sondan mümkündür! Ona əlavə edilən ilk element başlanğıcda (yaxud daha rahat olduğu kimi aşağıda) olsa da. Stack
Obyektimizdə olan üsullar bunlardır push()
- yığının yuxarı hissəsinə element əlavə edir. Obyekt pop()
- yığının yuxarısındakı elementi qaytarır, prosesdə onu çıxarır. Obyekt peek()
- yığının yuxarısındakı elementi qaytarır, lakin onu çıxarmır. int search()
- Stackdə elementi axtarır. Əgər tapılarsa, onun yığının yuxarı hissəsindən ofseti qaytarılır. Əks halda -1 qaytarılır. boolean empty()
- yığının boş olub olmadığını yoxlayır. Yığın boş olduqda doğru qaytarır. Yığında elementlər varsa, false qaytarır. Bəs niyə sizə iş prinsipləri əsasında qurulmuş birinə Java
ehtiyacınız var ? Belə bir sadə proqramın icrası zamanı baş verən aşağıdakı xətanın nümunəsinə baxaq. 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
İki metoddan ibarət bir sinifimiz var . Hamıya tanışdır main
və convertStringToInt
məntiqi xaricdən (yəni metoddan main
) alınan sətri tam ədəd tipli növə çevirmək və qaytarmaqdır int
. Gördüyünüz kimi, biz qəsdən hansısa nömrə ilə sətir əvəzinə parametri keçdik null
. Metodumuz bu parametri düzgün emal edə bilmədi və xətaya səbəb oldu NumberFormatException
. Bildiyiniz kimi, proqram öz işini metoddan işləməyə başlayır və bu anda o , öz işinin cari dəyərini 1 nömrəsinin altına qoyduğu adla main
yenisini yaradır , sonra yenidən metoda və proqrama keçirik. yerimizin parametrlərini 2 nömrə altında daha əvvəl yaradılmış birinə daxil edir, sonra bu, sinifdə yerləşən gözümüzə görünməyən bir üsul adlanır və bu, artıq bizim 3 nömrəli elementimiz olacaq , bu üsulda başqa bir daxili zəng əlavə olunacaq Elementi sıfıra yoxlamaq üçün 4- ə qədər səhvə səbəb olacaq. Proqram səhv baş verənə qədər bütün keçid zəncirini göstərən səhvimizi göstərməlidir. Burada əvvəllər keçidlərimizin məlumatları ilə yaradılan onun köməyinə gəlir . Стэк
StackTrace
convertStringToInt
StackTrace
parseInt
Integer
StackTrace
StackTrace
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)
Səhv baş verməmişdən əvvəl proqram metodlara dərindən keçdi, lakin səhv baş verən kimi hər şey tərs qaydada baş verməyə başlayır. Problemi təsvir edən sətir çap olunur (nümunədə №1), sonra bizimkinə əlavə olunan sonuncu (və yuxarıda) dəyər götürülür, Стэк
dördüncü nömrə idi və konsola çap olunur (nümunədə №2) və görürük ki, problem Integer
614 kod sətirində sinifdə yaranıb və bu sətir, parseInt
eyni sinif metodunun (nümunədə 3 nömrəli) 770-ci sətri adlanır və bu sətir əlavə edildikdə Стэк
üç nömrəli idi və bu sinif metodu, hələ də bizə görünməyən, proqramımızın 10-cu sətirində yerləşən Integer
metodumuzla çağırıldı (nümunədə 4-cü, əlavə edərkən ikinci idi) və o da öz növbəsində 6-cı sətirdə (№ 5-də) çağırıldı. nümunə və əlavə edərkən, müvafiq olaraq, birinci). Beləliklə, çağırılan metodlarımızı addım-addım saxlayaraq , bizi səhvə aparan məlumatların paralel çapına qayıda bildik . Ancaq bu, yalnız səhvlərlə işləmək deyil, bizə müraciətimizin prosesi haqqında çoxlu maraqlı məlumatlar əldə etməyə imkan verir. 9-cu səviyyənin əsas mühazirəsinin şərhlərində başqa bir məşhur nümunəyə baxaq. Bizdə kod var və mən dərhal ona proqramın prosesini göstərən bir şəkil əlavə edəcəyəm: convertStringToInt
main
Стек
main
StackTrace
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());
}
}
}
Burada proqramımız öz işini qüsursuz yerinə yetirir və bitir. Konsol çıxışında görəcəyimiz budur:
getStackTrace
method5
method4
method2
main
Process finished with exit code 0
Bu nəticəni necə əldə etdik və 20-ci sətirdən başlayaraq beşinci üsulda nə baş verdi? Qorxuram ki, əlimdən gələnin ən yaxşısı mühazirəyə şərhlərdən Kirill istifadəçisinin ən məşhur izahını (qısaldılmış) əlavə etməkdir. Gəlin yaradılış xəttinə keçək StackTrace
və onu element-element təhlil edək:
StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
StackTraceElement[]
- massivin növünün göstəricisi (İlk səviyyələrdə siz artıq int[], String[] kimi massivlər haqqında öyrənmisiniz, burada da eynidir). stackTraceElements
- massivin adı hər hansı ola bilər, ümumi adlandırma qaydalarını nəzərə alsaq, bu işə təsir etmir. Thread.currentThread()
- izləmək istədiyimiz metodların icra olunduğu cari mövzuya keçid əldə etmək (hazırda bu vacib deyil, siz Java Core axtarışında 16-cı səviyyədə mövzuları daha ətraflı təhlil edəcəksiniz) - bütün çağırılan metodları getStackTrace()
alırıq Стэк
(Bu, üçün müntəzəm alıcıdır StackTrace
) İndi görək yaradılmış massiv bizim üçün nə faydalı ola bilər. Biz başa düşürük ki, massiv icra edilən metodlar haqqında məlumat saxlayır. (c) Bunun üçün 21-ci sətirdə dəyişdirilmiş bir dövrü işə salırıq for
( forEach
yeri gəlmişkən, bu dövrü hələ öyrənməmişlər üçün bu barədə oxumağı məsləhət görürəm) və massivdən konsola məlumat çıxarırıq. , konstruksiyadan istifadə etməklə iş zamanı hansı üsulların yerinə yetirildiyi barədə məlumat element.getMethodName()
. Diqqət, gördüyümüz kimi, serialın sıfır elementi müvafiq olaraq özü oldu getStackTrace()
, çünki məlumat massivinin qəbulu anında bu, icra olunan və bununla da yuxarıda bitən son üsul idi Стэка
və tikintimizi xatırlayırıq " Son girən, ilk çıxan ” dərhal sıfır elementin altındakı massivə əlavə ediləcək ilkdir. Buradan başqa nə əldə edə bilərik StackTraceElement
: String getClassName()
- Sinfin adını qaytarır. String getMethodName()
- metodun adını qaytarır. String getFileName()
- Fayl adını qaytarır (bir faylda çoxlu siniflər ola bilər). String getModuleName()
- Modul adını qaytarır (null ola bilər). String getModuleVersion()
- Modul versiyasını qaytarır (null ola bilər). int getLineNumber()
- Metodun çağırıldığı faylda sətir nömrəsini qaytarır. İndi ümumi iş prinsipini başa düşdüyünüz üçün sizə İdeStackTrace
-də özünüz müxtəlif üsulları sınamağı məsləhət görürəm . Hər şeyi tam mənimsəməmisinizsə belə, öyrənməyə davam edin və tapmaca bu məsələdə mənim üçün olduğu kimi olacaq. Hamınıza uğurlar arzulayıram! Ps Bu materialı bəyəndinizsə like ataraq dəstək olun. Sizin üçün çətin deyil, məmnunam. Təşəkkür edirəm və 41-ci səviyyədə görüşənədək ;)
GO TO FULL VERSION