Muhabir: Birkaç röportaj sorusunu ezberledikten sonra, Java kaynak koduna aşina olduğunuzu söylemeye cesaret edebilir misiniz? Kaynak kodunu bile bilmeyen kişileri işe almıyoruz Güç Projesi

Yazar Baldwin_KeepMind

Sorumlu Editör | Wu Xingling

Üretildi CSDN Blog

Benim gerçek deneyimim

Başlık, 28 Haziran 2019'da Shenzhen'deki bir Fortune 500 şirketinde röportaj yaptığım zaman görüşmecinin bana söylediği şeydi. Şu anda düşündüğümde bile sonsuz utanıyorum. Sıkıcılığım, tembelliğim ve küstahlığım nedeniyle Shenzhen'e ilk ziyaretim Görüşme mahvoldu.

Hayatımın o sıcak sabahını asla unutmayacağıma eminim İlk gün K Company'den röportaj duyurusu aldım.Bu, Shenzhen'deki ilk görüşme davetimdi. Bilgiyi aldıktan sonra, K Şirketi'nden bir teklif aldığım için çok heyecanlandım. K şirketinin İnternet'teki deneyimini kontrol ettim ve birçok kişinin kaynak kodu okuma becerisine büyük önem verdiklerini ve hemen hemen her seferinde kaynak kodu sorduğunu öğrendim. Bu yüzden String, HashMap vb. Hakkında birkaç makale bulmak için İnternet'e gittim ve Java kaynak kodu hakkında çok şey öğrendim. Okuduktan sonra kendime çok güveniyorum, yarın tüm soruları cevaplayabileceğimi ve mutlu bir şekilde uyuyabileceğimi düşünüyorum.

Röportaj sabahı saat 9'da alt kattaki K şirketine geldim ve sonra beni yukarı çıkarması için kişiyi aradım, bekleme odasında röportajı bekledim, saat 9:30 civarında, resepsiyondaki bayan adımı çağırdı ve onu takip ettim. Birlikte küçük bir odaya girdik. İçinde iki kişi vardı. Teknik görünüyorlardı (çünkü biraz kellerdi). İlk başta iyi gittiler. Sonra bir soru sordular, "Özgeçmişiniz Java kaynak kodunu bildiğinizi söylüyor. Size bir soru sorayım, String sınıfı kalıtsal olabilir mi? "Tabii ki miras alınmaz. Makalede yazılır. String final ile değiştirilir ve miras alınamaz.Sonra bazı röportaj soruları hakkında konuştum. İçerik, görüşmeci daha sonra başka bir soru sordu:

"Lütfen bana kısaca alt dizenin uygulama sürecinden bahsedin" Evet, bu soruyu okumadım ve kullandığım zaman bu yöntemin kaynak koduna bile bakmıyorum, belli belirsiz cevap veremiyorum, kızardığımı sıcak hissedebiliyorum. Utançımı görmüş gibiydi, bu yüzden "Kaynak kodunu gerçekten okudunuz mu? Alt dize çok basit bir yöntemdir. Okudiyseniz, bilmemek imkansızdır" dedi. İtiraf etmeliyim, kaynak kodunu okumadım, evet aslında basit bir alt dizeyi nasıl uygulayacağımı bile bilmiyorum, String sınıfının kaynak kodunu bile bulamıyorum.

Görüşmeci başlıktaki cümleyi söyledi ve sonra görüşmede başarısız oldum.

Benim için yeni bir dünya açan bu başarısız deneyime teşekkür etmek istiyorum.Jdk kaynak kodundan Spring'e, SpringBoot kaynak koduna kadar kaynak koduna bakmaya başladım.Ona baktıkça bu mükemmel çerçeveyi yazan büyük adamlara daha çok hayran oluyorum. Fikirleri, kod mantığı ve tasarım modelleri çok mükemmel ve uygun. Sadece bu değil, aynı zamanda yavaş yavaş kendi kendime bazı çerçeveler yazmaya başladım. İlk uygulama çerçevesi "El Yazısı Kısa Versiyon Bahar Çerçevesi - YzSpring" idi. Bir haftamı aldı. Her gece işten sonra evde bir veya iki saat çalışmak zorunda kaldım. , YzSpring'i yazdıktan sonra Bahar'ı gerçekten anladığımı hissediyorum İnternetteki bilgileri okuduğumda her zaman kaşıntı hissettim, Bahar'ın çalışma prensibini ancak kendi başıma yazarak anlayabiliyorum.

Daha sonra, "IPayment" projesindeki ortaklarım arayüzümüzün yavaş geribildirim hızından şikayet etmeye devam ettiler. Kodu optimize etmeye ve Redis'te bazı verileri önbelleğe almaya başladım. Hız gerçekten hızlıydı, ancak her önbelleğe alınmış bir veri eklediğimde, Eşleştirme için iki veya üç satır kod kullanılır Önbelleğe alınan verilerin daha az olması önemli değildir, ancak önbelleğe daha fazla veri yazılması gerektiği için kod aşırı derecede şişirilir. Bir gün @Autowired'ın enjeksiyon işlevini gördüm, birden düşündüm, neden önbelleğe alınması gereken verilere açıklama eklemek için pratik bir çerçeve yazamıyorum ve sonra bunu işlemek için çerçeveyi kullanamıyorum? Sadece yapın ve bir hafta fazla mesai yapın. "Redis tabanlı hızlı veri önbelleğe alma bileşenini" tamamladım. Projeyi tanıttıktan sonra, önbelleğe alınması gereken verilerin yalnızca @BFastCache ile dekore edilmesi gerekiyor. İsteğe bağlı işlemler var: veriler üzerinde işlem , Veri kaynağını seçin, veri kaynağını güncelleyin, Anahtarı ayarlayın / değiştirin, bu da iş verimliliğini büyük ölçüde artırır. İlk defa tekerleği kendim yazıyorum ve etkisi o kadar iyi ki, ağabey tarafından onaylandığım için çok mutluyum.

Şimdi size üç soru sormak istiyorum:

  • Kaynak kodunu görüyor musunuz?

  • Kaynak kodunu biliyor musunuz?

  • Kaynak koddan kazandınız mı?

  • Kaynak koduna bakın

    1. Hataları hızla kontrol edin ve hataları azaltın

    Kodlama yaparken, genellikle String'in alt dize yöntemi gibi RuntimeException'ı bulamayız. Bazen ilettiğimiz endIndex, dizenin uzunluğundan daha büyük olabilir, bu nedenle çalışma zamanında bir hata olacaktır:

    Dize dizini aralık dışı: 100

    Bazen kafam karışıyor ve kodu doğru değiştiriyorum, ancak bu istisnanın neden oluştuğunu bilmiyorum.Aynı sorun bir dahaki sefere yazdığımda ortaya çıkıyor. Kaynak koduna bakarsak, bu istisnanın neden oluştuğunu öğrenebiliriz:

    public String substring (int beginIndex, int endIndex) { eğer (beginIndex < 0) {// Başlangıç koordinatı 0'dan küçük yeni StringIndexOutOfBoundsException (beginIndex) atmak; } eğer (endIndex > value.length) {// Bitiş koordinatı, dizenin uzunluğundan daha büyük yeni StringIndexOutOfBoundsException (endIndex); } int subLen = endIndex-beginIndex; if (subLen < 0) {// Başlangıç koordinatı bitiş koordinatından büyük yeni StringIndexOutOfBoundsException (subLen); } return ((beginIndex == 0) (endIndex == value.length))? bu : new String (değer, beginIndex, subLen); }

    Kaynak kod, yukarıdaki istisnaları atabilecek üç senaryo verir.Sonra bu üç senaryoya göre kodumuzu kontrol edebilir ve ileride kodlama yaparken bu sorunlara dikkat edebiliriz.

    2. Programlama alışkanlıklarını öğrenin

    Veya yukarıdaki alt dize kaynak kodu. Lütfen geri dönüşüne dikkat edin, yerinde olsaydınız nasıl yazardınız? Kaynak kodunu okumadıysanız, kesinlikle şunları yazacağım:

    eğer ((beginIndex == 0) (endIndex == value.length)) bunu döndür; yeni String (değer, beginIndex, subLen) döndür;

    Fonksiyonlar aynı olmasına rağmen, üçlü işlemlerin kullanılması sorunu bir satır kodla çözebilir ve if ifadeleri yazmaya gerek yoktur.Şimdi üç terimli operatörlere takıntılı hale geldim, ki bu gerçekten çok kolay.

    3. Tasarım modellerini öğrenmek (yeni başlayanlar için)

    Tamam! Karşılaşmam var Yapmak Yarı yolda bir programcı olarak, tümü kendi kendine çalışma olan sistematik bir öğretim almadım. Daha önce tasarım desenlerini hiç anlamıyordum, sadece 23 tasarım deseni olduğunu biliyordum ve en fazla tek ton desenini biliyordum.

    Tasarım modunu anlamamamızın ana sebebi o zamanlar gerçek bir savaş tecrübem olmamış olmasıydı.Yazdığım projelerin tamamı yarışma projeleriydi. Tasarım modunu hiç kullanmam gerekmiyordu. Temel olarak koşabilirdim. Tasarım kalıbı ile ilk karşılaştığımda log4j fabrika kalıbı içindeydim. O zamanlar fabrika kalıbını nasıl kullanacağımı hiç anlamıyordum. Bunu sadece log4j'nin kaynak koduna bakarak adım adım öğrendim ve daha sonra bir projeye başladığımda tasarımı bilinçli veya istemeden kullanmaya başladım. Mod, aşağıdaki projemdeki yapılandırma sınıfını elde etmek için tekli modu kullanan koddur:

    import java.util.ResourceBundle; public class Configration { özel statik Nesne kilidi = yeni Nesne; private static Configration config =; özel statik ResourceBundle rb =; özel Yapılandırma (Dize dosya adı) { rb = ResourceBundle.getBundle (dosya adı); } public static Configration getInstance (Dize dosya adı) { senkronize edildi (kilitle) { if (== config) { config = new Configration (dosya adı); } } dönüş (yapılandırma); } public String getValue (Dize anahtarı) { Dize ret = ""; eğer (rb.containsKey (anahtar)) { ret = rb.getString (anahtar); } dönüş ret; } }

    3. Küçük özet

    Birçoğunuz yukarıdaki şeylerin çok basit olduğunu düşünebilir, lütfen beni yanıltmayın, çünkü yukarıdakiler en basit örneklerdir, kaynak kodda öğrenmeye değer birçok yer vardır ve bunu sadece kendiniz okuyarak anlayabilirsiniz.

    Kaynak kodunu okumak için doğru duruş

    Burada örnek olarak çok sıcak bir HashMap sınıfı alıyoruz.Aynı zamanda kodu okumak için IDEA kullanmanızı şiddetle tavsiye ediyorum.Dahili decompiler, kaynak kodunu hızlı ve kolay bir şekilde görmemizi sağlar.Ayrıca birçok kısayol tuşu işlemi vardır. Operasyon çok havalı.

    1. Kaynak kodunu bulun

    Aslında, konumlandırırken birçok durum vardır:

    Ctrl + Sol düğme

    Bu durumda sadece HashMap sınıfına ait olan metodu girmemiz gerekiyor, Ctrl + Sol tuşuyla direkt olarak kaynak kodunu bulabiliriz.

    Ctrl + Alt + B

    HashMap'in put metodu, Map metodunun yeniden yazılmasıdır.Ctrl + Left butonunu kullanırsak, doğrudan Map arayüzünün put metoduna atlayacağız.Bu istediğimiz sonuç değil.Şu anda, fare imlecini koymanın üzerine koymalıyız. Sonra Ctrl + Alt + B tuşlarına basın ve ardından put yöntemini geçersiz kılan birçok sınıf vardır.

    Görmemiz gereken sınıfı bulun ve koyma yöntemini bulmak için sol tıklayın.

    2. Miras ilişkisini görüntüleyin

    Bir sınıfın kalıtım ilişkisi, özellikle miras alınan soyut sınıf çok önemlidir, çünkü soyut sınıftaki yöntemler alt sınıfta kullanılabilir.

    Önceki adımda HashMap kaynak kodunu bulduk ve şimdi en üste çekiyoruz, sınıf tanımlandığında aşağıdaki miras ilişkisinin olduğunu görebiliyoruz:

    genel sınıf HashMap < K, V > AbstractMap'i genişletir < K, V > Harita uygular < K, V > , Klonlanabilir, Seri hale getirilebilir

    Elbette, daha sezgisel ve ayrıntılı olmak istiyorsanız, IDEA'da kalıtımı gösteren bir işlev vardır. Fareyi görüntülenecek sınıfa yerleştirebilir ve ardından Ctrl + Alt + Shift + U veya sağ tıklama = Diyagramlar = Göster Diyagram ve sonra kalıtım ilişkisini görebiliriz:

    Ardından AbstractMap soyut sınıfına bakın, çünkü daha sonra kullanılabilir.

    3. Sınıf sabitlerini görüntüleyin

    HashMap yapıcısına girdiğimizde aşağıdaki kodu bulduk:

    public HashMap (int initialCapacity) { this (initialCapacity, DEFAULT_LOAD_FACTOR); }

    Yalnızca initialCapacity'nin aktardığımız ilk kapasite olduğunu biliyoruz, ancak bu DEFAULT_LOAD_FACTOR'un ne olduğunu ve ne kadar olduğunu bilmiyoruz. Önce bu sınıfa ait sabitlere kabaca bir göz atabilir ve daha sonra kaynak kodunu okumak için iyi bir izlenim bırakabiliriz. Bu miktarın konumunu bulmak için Ctrl + sol tıklama ve sonra birkaç sabit olduğunu gördük, sabitler hakkında yorumlar var, bir göz atalım, bu sabitleri anlamamıza yardımcı olur:

    //seri numarası

    özel statik son uzun serialVersionUID = 362498820763181265L;

    / **

    * Başlangıç kapasitesi 2'nin gücü olmalıdır

    * 1 < < 4 = 10000 = 16

    * /

    statik final int DEFAULT_INITIAL_CAPACITY = 1 < < 4; // İlk varsayılan değer, dört bit ile sola kaydırılmış ikili 1'dir = 16

    / **

    * Maksimum kapasite

    * 2'nin üssü olmalıdır < = 1 < < 30.

    * /

    statik final int MAXIMUM_CAPACITY = 1 < < 30;

    / **

    * Yük faktörü, kurucuda belirtilmediğinde kullanılacak

    * /

    statik son kayan nokta DEFAULT_LOAD_FACTOR = 0.75f;

    / **

    * Bağlı bir listeden ağaca ne zaman geçilir?

    * /

    statik final int TREEIFY_THRESHOLD = 8;

    / **

    * Bir ağaçtan bağlantılı listeye ne zaman geçilir?

    * /

    statik final int UNTREEIFY_THRESHOLD = 6;

    / **

    * Bölmelerin ağaçlandırılabileceği en küçük masa kapasitesi.

    * (Aksi takdirde, bir bölmede çok fazla düğüm varsa tablo yeniden boyutlandırılır.)

    * Çatışmaları önlemek için en az 4 * TREEIFY_THRESHOLD olmalıdır

    * yeniden boyutlandırma ve ağaçlandırma eşikleri arasında.

    * /

    statik final int MIN_TREEIFY_CAPACITY = 64;

    Bu şekilde, HashMap'teki sabitlerin rolü ve anlamı hakkında bir anlayışa sahibiz.

    4. Yapıcıyı görüntüleyin

    Genel olarak bir sınıfa bakıyoruz, önce sınıfın nasıl inşa edildiğine, yani inşa yönteminin gerçekleştirilmesine bakmalıyız:

    / ** * Başlangıç değeri ve ilk yükleme faktörüyle boş bir HashMap oluşturun * @param initialCapacity başlangıç kapasitesi. * @ İlk kapasite negatifse IllegalArgumentException'ı atar. * / public HashMap (int initialCapacity) { this (initialCapacity, DEFAULT_LOAD_FACTOR); }

    Açıkçası, yukarıdaki kurucu başka bir kurucuya işaret ediyor, öyleyse tıklayalım ve bir göz atalım

    / ** * * @param initialCapacity başlangıç kapasitesi * @param loadFactor yük faktörü * @ İlk kapasite negatifse IllegalArgumentException'ı atar * veya yük faktörü pozitif değil * / public HashMap (int initialCapacity, float loadFactor) { if (initialCapacity < 0) yeni IllegalArgumentException ("Geçersiz ilk kapasite:" + initialCapacity); if (initialCapacity > MAKSİMUM KAPASİTE) initialCapacity = MAXIMUM_CAPACITY; eğer (loadFactor < = 0 || Float.isNaN (yükFaktörü)) yeni IllegalArgumentException ("Geçersiz yük faktörü:" + Yük faktörü); this.loadFactor = loadFactor; this.threshold = tableSizeFor (initialCapacity); }

    İşte kurucumuzun uygulandığı yer. Şimdi satır satır analiz edelim:

    1. initialCapacity parametremiz başlangıçta geçtiğimiz 16'dır ve loadFactor, önceki adımda kullanılan varsayılan 0.75f parametresidir.

    2. Başlangıç kapasitesinin 0'dan küçük olup olmadığını belirleyin, 0'dan küçükse bir istisna atın ve 0'dan az değilse sonraki adıma geçin.

    3. Başlangıç kapasitesinin maksimum kapasiteden (1 < < 30) Eğer daha büyükse, maksimum kapasiteyi alın.

    4. Yük faktörünün 0'dan küçük veya 0'a eşit olup olmadığını ya da bir sayı olup olmadığını, bir istisna veya sonraki adımı belirleyin.

    5. Bu HashMap'in yük faktörünü başlatın.

    6. Son satır HashMap'in genişletme mekanizmasıdır.Gerçek kapasite tarafımızca verilen kapasiteye göre belirlenir.Bu yöntemin kaynak koduna bir göz atalım.

    statik final int tableSizeFor (int cap) { int n = cap-1; n | = n > > > 1; n | = n > > > 2; n | = n > > > 4; n | = n > > > 8; n | = n > > > 16; dönüş (n < 0)? 1: (n > = MAXIMUM_CAPACITY) MAXIMUM_CAPACITY: n + 1; }

    Bu adım aslında belirlediğimiz kapasiteden daha büyük olan 2 minimum gücü bulmak içindir.Bu değer, belirlediğimiz değer değil gerçek başlangıç kapasitesi olarak kullanılır.Bu sonraki bit işlemleri içindir. Şimdi yukarıdaki işlemi açıklıyoruz:

    Örnek olarak cap = 13'ü alın, sonra başlangıç n = 12, ikili sayı 00001100 ve sonra her seferinde bir bit sağa kaydırın ve n ile bir OR işlemi gerçekleştirin.Örnek olarak ilk kez, ilk | = sağ taraftaki işlem işaretsizdir 1 bit sağa kaydır, sonra sağdaki değer 00000110 ve n ile OR işlemi 00001110'dur. İşlem son adıma, n = 00001111'e tekrarlandığında ve sonra geri dönüşte, 16 olan n + 1'i döndürür.

    Bu noktada, boş bir HashMap'in başlatılmasını tamamladık ve şimdi bu HashMap çalışmaya hazır.

    5. Yöntem mantığını görüntüleyin

    Genel olarak HashMap kullandığımızda put yöntemi daha çok kullanılır ve daha fazla içerik içerir.Şimdi HashMap'in put metodunu bulalım.

    public V put (K anahtarı, V değeri) { return putVal (hash (anahtar), anahtar, değer, yanlış, doğru); }

    Put yöntemi putVal yöntemini çağırır ve parametreleri ayrıştırır Anahtar ve değer hakkında söylenecek bir şey yoktur. Hash (key) yönteminin ne yaptığına bir göz atalım.

    statik nihai int hash (Nesne anahtarı) { int h; return (anahtar ==)? 0: (h = key.hashCode) ^ (h > > > 16); }

    Mevcut anahtar ise, o zaman doğrudan 0 hash değerini döndürür, değilse, o zaman mevcut anahtarın hash değerini alın ve bunu h'ye atayın ve yüksek 16 bitin bitsel XOR değerini ve mevcut anahtar hash değerinin düşük 16 bitini döndürün Bu şekilde, hem yüksek hem de düşük bitlerin operasyona katılmasına izin verme yöntemi, hash çarpışmaları olasılığını büyük ölçüde azaltabilir.

    TAMAM! Üç ekstra parametre için, hash değerinin içeriğini zaten biliyoruz, ancak üç değerin ne olduğunu bilmiyoruz Endişelenmeyin, putVal yöntemine giriyoruz.

    / ** * Map.put ve ilgili yöntemleri uygular. * * anahtar için @param hash hash'i * @param anahtarı anahtarı * @param değeri koyulacak değer * @param onlyIfAbsent true ise, mevcut değeri değiştirmeyin * @param yanlışsa evict, tablo oluşturma modundadır. * @ önceki değeri geri döndürün veya yoksa * / final V putVal (int hash, K key, V value, only booleanIfAbsent, boolean tahliye) { Düğüm < K, V > sekme; Düğüm < K, V > p; int n, i; eğer ((tab = tablo) == || (n = tab.length) == 0) n = (sekme = yeniden boyutlandır). uzunluk; eğer ((p = sekme ) ==) sekme = newNode (karma, anahtar, değer); Başka { Düğüm < K, V > e; K k; eğer (p.hash == hash ((k = p.key) == anahtar || (anahtar! = anahtar.equals (k)))) e = p; else if (p TreeNode örneği) e = ((TreeNode < K, V > ) p) .putTreeVal (bu, sekme, karma, anahtar, değer); Başka { for (int binCount = 0 ;; ++ binCount) { eğer ((e = p.next) ==) { p.next = newNode (hash, key, value,); eğer (binCount > = TREEIFY_THRESHOLD-1) // -1 için -1 treeifyBin (sekme, karma); kırmak; } eğer (e.hash == hash ((k = e.key) == anahtar || (anahtar! = anahtar.equals (k)))) kırmak; p = e; } } eğer (e! =) {// anahtar için mevcut eşleme V oldValue = e.value; eğer (! onlyIfAbsent || oldValue ==) e.value = değer; afterNodeAccess (e); oldValue döndür; } } ++ modCount; eğer (++ boyut > eşik) yeniden boyutlandırma; afterNodeInsertion (evict); dönüş; }

    Yukarıdaki koda bakın, yine baş ağrısı mı çekiyor? Ondan korkmayın, satır satır ayırırız, çok kolay hale gelecektir.

    İlk adım notları okumaktır, notlar çevrilmiştir, lütfen keyfini çıkarın.

    / ** * Map.put'tan devralındı. * * @param hash key hash değeri * @param anahtar anahtarı * @param değeri Girilecek değer * @param onlyIfAbsent eğer doğruysa, mevcut değeri değiştirmeyin * @param yanlışsa evict, tablo oluşturma modundadır. * @return mevcut değeri döndürür, mevcut değer mevcut değildir dönüş * /

    Ardından içeriğe bakın

    1. HashMap'in temel veri yapısının Node olduğu birkaç değişken oluşturun ve genel özellikleri aşağıdaki gibidir:

    statik sınıf Düğüm < K, V > Map.Entry'yi uygular < K, V > { final int hash; final K anahtarı; V değeri; Düğüm < K, V > Sonraki; Düğüm (int hash, K key, V value, Node < K, V > Sonraki) { this.hash = hash; this.key = anahtar; this.value = değer; this.next = sonraki; } }

    2. Mevcut tablonun boş olup olmadığını veya tablonun uzunluğunun 0 olup olmadığını belirleyin ve aynı anda sekme ve n'ye değerler atayın.Koşullar doğruysa (mevcut HashMap boşsa), yeniden boyutlandırın ve yeniden boyutlandırma değerini sekmeye atayın. Sekme dizisinin uzunluğu n'ye atanmıştır. Boşluk nedeniyle yeniden boyutlandırma yöntemi burada ayrıntılı olarak açıklanmamaktadır.Bu yöntemin çok fazla içeriği vardır ve diğer makalelerde çokça bahsedilmiştir.Günümüzün odak noktası HashMap değil kaynak kodunun nasıl okunacağını açıklamaktır.

    3. Temel dizideki geçerli anahtar değer öğesinin karma değerine karşılık gelen konumda bir öğe olup olmadığını belirleyin, yoksa, yalnızca geçerli öğeyi yerleştirin.

    4. Önceki adımı takiben, alttaki dizinin karşılık gelen konumunda zaten bir değer varsa, verileri yazmak için diğer bazı sütun işlemlerini gerçekleştirin ve eskiDeğer'i geri getirin.

    Tüm süreci gezdikten sonra dikkat edilmesi gereken birkaç noktayı özetliyoruz.Örneğin HashMap.put metodu yeniden boyutlandırmaya, kuyruk yerleştirmeye ve ağaçlar ile listeler arasında dönüşüme dikkat etmelidir.

    Alan sorunları nedeniyle, bu yöntemin içeriğinden kısaca bahsediyorum.Kaynak kodunu görüntülemenin spesifik yolu öncekiyle aynıdır ve onu adım adım analiz edebilirsiniz.

    6. Küçük özet

    Kaynak kodunu görüntülemek için birkaç ipucu:

    1. Doğru kaynak kodu konumunu bulmak için Ctrl + Sol düğmesi veya Ctrl + Alt + B

    2. Genel bir fikir edinmek için sınıftaki bazı miktarları kontrol edin

    3. Örneğin başlatma durumunu görmek için kurucuyu görüntüleyin

    4. Kod daha karmaşıksa, kodu adım adım ayrıştırın

    5. Diğer kaynak kodunun okunması bu rutine göre analiz edilebilir

    Yazar = Mengxin, herhangi bir hata varsa lütfen belirtin.

    Kaynak kodunu okumak kesinlikle her programcının ihtiyaç duyduğu bir beceridir, ilk başta okumak zor olsa bile yavaş yavaş alışınız.

    Telif hakkı bildirimi: Bu makale, CSDN blog yazarı "Baldwin_KeepMind" in orijinal makalesidir. CC 4.0 BY-SA telif hakkı sözleşmesine uygundur. Lütfen orijinal kaynak bağlantısını ve yeniden basım için bu bildirimi ekleyin.

    Orijinal bağlantı: https://blog.csdn.net/shouchenchuan5253/article/details/105196154

    Dijital dönüşüm eş için çok mu zor? AI ve IoT sert vuruşlar yapıyor!

    Bu bir mucize! 8 günde bir ürün doğdu ve bu girişim bunu yaptı

    Döngüsel Zeka Yang Zhilin: "İnsan-makine bağlantısı" diyalog semantik uygulamalarında yeni bir trend olacak!

    Zhou Hongyi tarafından tüm ağdan yasaklanan 360 asil general: tabandan 36 yaşına kadar olan ve net değeri yüz milyonlarca olan bir karşı saldırı!

    Kubernetes'in uç bilişim alanında ayrıntılı gelişimi

    Salgından sonra, küresel kripto topluluğunun koronavirüsle savaşmak için çok şey yaptığı ortaya çıktı!

    Perakendecilikte "duygusal bilgi işlemin" uygulamasını ve gelişimini anlamak için bir makale

    10 satırlık Python kodu hangi ileri teknoloji işlemlere sahip olabilir? | Güç Projesi
    önceki
    400 satırdan fazla kod! Süper ayrıntılı Rasa Çince sohbet robotu geliştirme kılavuzu | Kuvvet Projesi
    Sonraki
    Luhan'ın AI hayranları var, AI'nın yüz değiştiren dramasının etkisi neden bu kadar aptalca?
    İyi programcıların hangi programlama alışkanlıkları vardır?
    Döngüsel Zeka Yang Zhilin: "İnsan-makine bağlantısı", semantik diyalog uygulamalarında yeni bir trend olacak
    Can sıkıcı MySQL alt veritabanı alt tablo problemini tamamen nasıl çözebilirim? Daha iyi bir veritabanı yazın
    Ne mucize! 8 günde bir ürün doğdu ve bu girişim bunu yaptı
    Programcılar için zorunlu bir kurs: Veri analizi için neden Python kullanmanız gerekiyor? Excel kötü mü?
    Ali ve Tencent gibi büyük üreticilerden yeni hasat teklifleri Size bunları anlatması gerekiyor.
    Çin'de bir ilk olan Tencent Cloud Cloud, "Aile Kovası" nı geliştirdi
    @Programmer, programlama yönteminizin modası geçmiş, bulut geliştirme çağı geliyor
    Ali Dharma Akademisi Aydınlatılıyor! P10 patronu size AIoT akıllı sesli etkileşim teknolojisinin nasıl oluşturulacağını öğretir
    IntelliJ IDEA 2020.1, 15 ana özellik ve resmi Çin desteği ile resmi olarak yayınlandı! | Güç Projesi
    Facebook mülakat sorularının tam analizi
    To Top