Tam metin 2361 kelime ve beklenen öğrenme süresi 9 dakikadır
Kaynak: unsplash
Sık sık nehir kenarında yürürüm ve ıslak ayakkabı kalmaz.Bazı hataları önlemek gerçekten zordur. Bununla birlikte, yazarın çaylaklardan kıdemli teknik liderlere kadar düzinelerce yazılım mühendisi ile yaptığı röportaja dayanarak, daha fazla durumda, adayların temel kavramları kavrayışlarında boşluklar olduğu görülüyor.
Bu makalede, bir teknik direktör ve röportajcı olarak deneyimime dayanarak, yazar Java geliştiricileri tarafından yapılan en yaygın hataları listeliyor ve vurulup vurulmadığımı görüyor.
Biraz anlaşılmaz olsa da, adaylar Java'daki korumalı erişim değiştiricilerin kapsamını gerçekten unuturlar. Belki de görüşme sırasındaki endişe ve gerginlik nedeniyle, genellikle bunlardan sadece birine cevap verebilirler:
· Korumalı alanlara, yöntemlere ve kuruculara alt sınıflardan erişilebilir.
· Korumalı alanlara, yöntemlere ve kuruculara aynı paketten erişilebilir.
Ek olarak, paketin kapsamı birçok geliştiricinin kendi testlerini yazmasına yardımcı olabilir: korunan yöntemlere test yolundan erişilebilir. Yani bu niteliği unutmak, röportajda hiç test yazmadığınızı göstermeye eşdeğerdir!
Kaynak: unsplash
Çok sayıda dizi veya büyük dizi kullanırsanız, bağlantı işlemi sırasında çok fazla bellek harcayabilirsiniz.
Yukarıdaki örnek, bazı StringBuilder ve String nesneleri oluşturmaktır: kesin olmak gerekirse, 10.000.000 StringBuilder ve 10.000.001 String.
Açıklama
Bir adım geri atın ve ne olduğunu görün.
Dize birleştirme için + operatörü kullanıldığında, birleştirme sonucunu saklayan ve sonucu hedef nesneye atayan bir ara nesne oluşturulur.
Yukarıdaki örnekte, toplam 3 nesne oluşturulmuştur: metin için 2 ve bağlantı için 1, yani, ilk dize sonucunun bir kopyası artı ikinci dize "dünya!". String değişmez olduğundan, bu string birleştirme mümkündür.
Ancak derleyici, kodu aşağıdakine dönüştürmek için yeterince akıllıdır (Java9 +, StringContactFacotry'yi kullandığı için geçerli değildir, ancak sonuçlar çok benzerdir):
Bu optimizasyon ara bağlantı nesnesini siler ve bellek 2 string metin ve 1 StringBuilder tarafından işgal edilir. Genel olarak, dizi nesnelerinin sayısı O (n²) 'den O (n)' ye düşmüştür.
İlk örneğe geri dönersek, derleyici kodu aşağıdaki gibi optimize eder:
Derleyici yalnızca dahili bağlantıyı optimize eder, ancak bu çok sayıda StringBuilder ve String nesnesi oluşturur! Dizeleri bağlamanın doğru yolu aşağıdaki gibidir, yalnızca bir StringBuilder ve bir String gereklidir.
Eşittir () yerine == (karşılaştırma operatörü) kullanıyorsanız, bu alışkanlığı değiştirmeniz gerekir ve sonuçlar şaşırtıcı olabilir.
Açıklama
İki Dizeyi ve diğer nesneleri karşılaştırmak istediğinizde, == kullanmayın. == İçerik yerine yalnızca iki işlenenin nesne referansını (bellek adresi karşılaştırması) karşılaştırır.
Yukarıdaki örnekte, dizge yerleşik dizgi mekanizmasını etkinleştiremez: bellek adresi x'ten farklıdır.
Yazar bu yöntemi defalarca keşfetmiştir:
Boş değer döndürme ile ilgili sorun, arayan kişiyi sonuç üzerinde boş bir kontrol yapmaya zorlamaktır; bu durumda, öğe yoksa, arayan kişi boş bir liste döndürecektir.
Geliştiriciler her zaman bir istisna veya özel nesne (boş bir liste gibi) döndürmek isterler, aksi halde kodu kullanan uygulama NullPointerException tarafından etkilenecektir.
Kullanıcı tarafından sağlanan parolanın dize nesnesinde saklanması bir güvenlik sorunudur ve dizi, bellek saldırılarına karşı savunmasızdır.
JPasswordField ve Password4j'de olduğu gibi karakter kullanılmalıdır. Ancak web uygulamalarından bahsediyorsanız, çoğu web kapsayıcısı HttpServletRequest nesnesinde düz metin parolasını bir String olarak geçirir, böylece geliştiriciler bu konuda neredeyse hiçbir şey yapamazlar.
Kaynak: unsplash
Açıklama
Dizeler Java Sanal Makinesi (JVM) (yerleşik) tarafından önbelleğe alınır ve PermGen alanında (Java 8'den önce) veya yığın alanında depolanır. Her iki durumda da, önbelleğe alınan değer yalnızca çöp toplama gerçekleştikten sonra silinir: bu, belirli bir değerin dize havuzundan ne zaman silineceğini bilmenin imkansız olduğu anlamına gelir, çünkü çöp toplayıcının davranışı belirsizdir.
Diğer bir sorun da Dizelerin değişmez olması, dolayısıyla temizlenememesidir. Ancak, char değişkendir ve işlendikten sonra silinebilir (örneğin, her bir öğeyi 0 ile değiştirin). Bu basit teknik sayesinde bir saldırgan, düz metin parolası yerine yalnızca bellekteki tüm sıfırlardan oluşan bir dizi bulabilir.
Null geçmek, çağıran kodun null değerini yönetebileceğinin kabul edildiği anlamına gelir. Bunu yapamazsa, uygulama kesinlikle bir NullPointerException oluşturur.
Ek olarak, açık bir şekilde null iletmek kodu gittikçe daha kafa karıştırıcı hale getirecektir. Aşağıdaki tipik bir örnektir:
İnit () çağrıldığında, kullanılabilir Kullanıcı nesnesi yoktur. Öyleyse, Kullanıcı yoksa, Kullanıcı üzerinde çalışan bir işlevi neden çağıralım? GrantAccessToUser () içindeki mantık gerekliyse, diğer işlevlerden çıkarılmalı ve null geçirmek yerine kullanılmalıdır.
Aşağıdaki örnekler sistem performansı kaybına neden olabilir:
Pattern.compile () çok yoğun kaynak gerektiren bir işlevdir ve bir dizge aynı kalıpla her eşleştiğinde çağrılmamalıdır.
Açıklama
Pattern.compile (), daha hızlı bellek gösterimi kullanmak için modeli önceden derler. Tek bir eşleşmeyle karşılaştırıldığında, bu işlem son derece güçlü bilgi işlem gücü gerektirir.
Performansı artırmanın klasik yolu, aşağıda gösterildiği gibi Desen nesnelerini statik alanlarda önbelleğe almaktır:
Bu çözüm, aynı kaynak yoğun durum bilgisiz nesne her kullanıldığında kullanılmalıdır.
Bu kod ConcurrentModificationException oluşturacaktır.
Açıklama
Yineleme sırasında listeden bir öğe silindiğinde, liste yineleyici öğeleri atlamak, öğeleri yinelemek, dizinin sonunu indekslemek gibi iyi çalışmayacaktır. Bu nedenle, birçok koleksiyonun oncurrentModificationException'ı atmak daha kolaydır.
Temel dizi yineleyiciyi kullanın:
Bir anlamda, geliştiriciler istisnaların uğursuz olduğunu düşünürler, bu nedenle -1 veya "C_ERR" gibi garip değerler döndüren işlevler yazma eğilimindedirler.
Bu, özel bir İstisna oluşturmaya değer tipik bir durumdur. Örnek aşağıdaki gibi yeniden yazılabilir:
Gördüğünüz gibi, kodun okunabilirliği ve sürdürülebilirliği büyük ölçüde geliştirildi. Arayanın, her dönüş koduyla uğraşmak zorunda kalmadan yalnızca DeviceStartException içeriğini okuması gerekir.
StringBuffer'ın senkronizasyon özelliklerinden dolayı, bu örnek çok fazla bellek kullanımı oluşturacaktır. Daha karmaşık ortamlarda, okuyucu yanlışlıkla bazı gereksiz senkronizasyonların gerekli olduğuna inanabilir.
Projeye bir StringBuffer dahil edilmişse, bunun nedeni bazı eski API'lerin (yani Java5'ten önce) bunu gerektirmesi olabilir, ancak nadiren kodun eşzamanlı bir ortamda Dizeleri eklemeye çalışması olabilir. Bunun yerine StringBuilder'ı kullanın: Java5'te sunulan tüm işlemler eşzamansızdır.
Bu, röportajlarda ve aktif projelerde gördüğüm hataların sadece bir kısmı.Nesne yönelimli programlamanın (OOP) tuzaklarından, tasarım modellerinden, aşırı tasarımından, bellek sızıntılarından ve diğer kusurlarından bahsetmedim ...
Resim kaynağı: xkcd
Bu sorunları yaşıyorsanız, kodlama stilini değiştirme zamanı gelmiştir. Zor değil. Bu tuzaklardan kaçınmak, geliştiricinin deneyimini geliştirebilir ve insanları proaktif olarak bir sonraki görüşmeye hazırlayabilir.
Gerçek hataları gösterebilen ve olası hataları vurgulayabilen SonarQube gibi statik bir kod analizörü kullanın.
Kaynak: unsplash
Öğrenmeye devam etmek daha önemlidir, sadece dilbilgisi değil, aynı zamanda herhangi bir programlama dilinin arkasındaki teori. Küçük hataları sizden uzak tutmak için daha fazla kod yazın ve daha fazla pratik yapın ~
Yorum Beğen Takip Et
Yapay zeka öğrenme ve geliştirmenin kuru mallarını paylaşalım
Yeniden yazdırıyorsanız, lütfen arka planda bir mesaj bırakın ve yeniden yazdırma şartnamelerine uyun