JavaRush /Java Blogu /Random-AZ /Stack Trace və onun nə ilə yeyildiyi
Alukard
Səviyyə
London

Stack Trace və onun nə ilə yeyildiyi

Qrupda dərc edilmişdir
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. Stack kolleksiyası necə işləyir 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 Stackqrupun 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, ArrayListsiyahı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ə Javaehtiyacınız var ? Belə bir sadə proqramın icrası zamanı baş verən aşağıdakı xətanın nümunəsinə baxaq. StackTraceStack
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 mainconvertStringToIntmə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 mainyenisini 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 . СтэкStackTraceconvertStringToIntStackTraceparseIntIntegerStackTraceStackTraceStackTrace
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 Integer614 kod sətirində sinifdə yaranıb və bu sətir, parseInteyni 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 Integermetodumuzla ç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: convertStringToIntmainСтекmainStackTrace
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());
        }
    }
}
Stack Trace və nə ilə yeyilir - 2 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 StackTracevə 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( forEachyeri 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 ;)
Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION