![translation](https://cdn.durumis.com/common/trans.png)
Bu, AI tarafından çevrilen bir gönderidir.
Dil Seç
Text summarized by durumis AI
- new anahtar sözcüğünü kullanarak bir dize veya Boolean örneği oluşturmak, bellek israfıdır, bu nedenle literallerle bildirilmesi veya Boolean.valueOf() yönteminin kullanılması daha iyidir.
- String.matches() yöntemi düzenli ifadeler kullandığı için performans sorunlarına neden olabilir ve bir Pattern örneğini önbelleğe alıp yeniden kullanmak daha iyidir.
- keySet() yöntemi gibi bir görünüm nesnesi döndüren durumlarda, yeni bir nesne döndürerek savunmacı kopyalama kullanmak daha güvenlidir.
Gereksiz nesne oluşturma durumları
new String() kullanımı
String a = new String("hi");
String b = new String("hi");
a, b ve c dizeleri hepsi "hi" dizisini içerir. Ancak, bu üç dizenin başvurduğu adresler farklı olduğundan, aynı veri için farklı bellek ayırma yapılması gereksiz bir israf yaratır.
Bu yüzden, bir dizeyi bildirmek için new anahtar sözcüğünü kullanmamak, literal olarak bildirmek gerekir.
String a = "hi";
String b = "hi";
Yukarıdaki kaynak kodu yalnızca bir örnek kullanır. Dahası, bu yöntemi kullanırsanız, aynı JVM içinde "hi" dize literalini kullanacak tüm kodların aynı nesneyi yeniden kullanmasını garanti eder. Bunun nedeni, Java sabit havuzunun özelliğinden kaynaklanmaktadır.
new Boolean() kullanımı
Yukarıdaki kod, bir dizeyi parametre olarak alan oluşturucu aracılığıyla Boolean örneği oluşturmaktadır. Boolean, yalnızca true veya false değerine sahip olabilir, ancak her seferinde örnek oluşturmak bellek israfıdır. Bu nedenle, Boolean.valueOf() statik fabrika yöntemini kullanmak daha iyidir.
String.matches() kullanımı
Oluşturma maliyeti yüksekse, önbelleğe alıp yeniden kullanmak iyidir, ancak oluşturduğumuz nesnenin maliyetini her zaman bilemeyiz. Örneğin, belirtilen dizenin geçerli bir Roma rakamı olup olmadığını kontrol eden bir yöntem yazmak istiyorsanız, aşağıdaki gibi düzenli ifadeleri kullanmak en kolay yoldur.
public static boolean isRomanNumeral(String s) {
return s.matches("^(?=.)M*(C[MD]|D?C{0,3})(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})$");
Ancak String.matches(), performans açısından sorunlu bir yöntemdir. Bu yöntemin içeride oluşturduğu düzenli ifade için Pattern örneği, bir kez kullanıldıktan sonra atılır ve hemen çöp toplama hedefi olur; bu düzenli ifadenin tekrar tekrar kullanım sıklığı ne kadar artarsa, aynı Pattern örneğinin oluşturulması ve atılması maliyeti o kadar artar. Bu nedenle, Pattern örneğini önceden önbelleğe alıp, isRomanNumeral() yöntemi daha sonra çağrıldığında bu örneği yeniden kullanmak daha iyidir.
public class RomanNumerals {
private static final Pattern ROMAN = Pattern.compile(
"^(?=.)M*(C[MD]|D?C{0,3})(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})$");
public static boolean isRomanNumeral(String s) {
return ROMAN.matcher(s).matches();
}
Dikkat edilmesi gerekenler
Yukarıdaki tüm örneklerde gereksiz nesnelerin önbelleğe alınması sırasında, hepsi değişmez nesne olarak oluşturulmuştur. Bunun nedeni, yeniden kullanıldığında güvenli olmasını sağlamaktır. Ancak, değişmez nesne olarak yeniden kullanmanın sezgiye aykırı olduğu durumlar vardır.
Adaptör (görünüm), gerçek işlemi arka uç nesnesine devreder ve kendisi ikinci bir arayüz görevi görür. Adaptör, yalnızca arka uç nesnesini yönetmesi gerektiğinden, arka uç nesnesi başına yalnızca bir adaptör oluşturulması yeterlidir.
Örneğin, Map arayüzünün keySet() yöntemi, Map nesnesinin içindeki tüm anahtarları içeren bir Set görünümünü döndürür. Kullanıcı, keySet() yöntemini her çağırdığında yeni bir Set örneği oluşturulacağını düşünebilir, ancak gerçek JDK uygulamasında, her seferinde aynı değişken Set örneği döndürülür.
Bunun nedeni, döndürülen Set örneğinin değişken olmasına rağmen, yaptığı işlevlerin hepsinin aynı olması ve tüm Set örneklerinin Map örneğini temsil etmesidir. Bu nedenle, keySet() birden çok görünüm nesnesi oluştursa bile, bunun bir sakıncası yoktur; ancak bunun bir gereği de, faydası da yoktur.
public class UsingKeySet {
public static void main(String[] args) {
Map menu = new HashMap<>();
menu.put("Burger", 8);
menu.put("Pizza", 9);
Set names1 = menu.keySet();
Set names2 = menu.keySet();
names1.remove("Burger");
System.out.println(names1.size()); // 1
System.out.println(names2.size()); // 1
}
Bu nedenle, yukarıdaki gibi names1 örneğini değiştirdiğinizde, names2 örneği de aynı şekilde etkilenecektir.
Ancak kişisel olarak, keySet() yönteminin döndürdüğü değer, her seferinde savunmacı bir kopyalama kullanarak yeni bir nesne döndürmesi gerektiğini düşünüyorum. keySet() yöntemiyle alınan Set örneği başka yerlerde de kullanılıyorsa ve bu örneğin durumunu değiştiren bir kod varsa, şu anda kullanılan Set örneği ve Map örneğinin değerlerinden emin olamayız.
Ayrıca, keySet() çok fazla kullanılan bir ortam değilse, Set arayüzü her seferinde oluşturulsa bile performansı ciddi şekilde etkilemez. Set arayüzünü değişmez bir nesne olarak oluşturup kararlı bir şekilde bakım yapmak daha iyi olduğunu düşünüyorum.
Otomatik kutulama
Otomatik kutulama, programcının temel türleri ve sarmalayıcı türleri karıştırarak kullanması durumunda, bunların otomatik olarak birbirine dönüştürülmesini sağlayan bir tekniktir. Ancak, otomatik kutulama temel türleri ve sarmalayıcı türleri arasındaki farkı tamamen ortadan kaldırmaz, yalnızca bulanıklaştırır.
public static long sum() {
Long sum = 0L;
for (long i = 0; i <= Integer.MAX_VALUE; i++) {
sum += i;
}
return sum;
Mantıksal olarak sorun yoktur, ancak performans açısından çok verimsiz bir kod parçacığıdır. Bunun nedeni, sum türü ve for döngüsünün içinde bulunan i türünden kaynaklanmaktadır.
sum türü Long türü, i ise long türüdür. Yani long türündeki i, döngüde dönerken sum'a eklendiğinde, her seferinde yeni bir Long örneği oluşturur. Sonuç olarak, sarmalayıcı türlerden ziyade temel türler kullanılmalı ve istenmeyen otomatik kutulamanın kullanılmamasına dikkat edilmelidir.
Yanlış anlamamak gereken noktalar
Gereksiz nesne oluşturulmasından kaçınılması gerektiği, nesne oluşturma maliyetinin yüksek olması nedeniyle, kaçınılması gerektiği şeklinde basit bir şekilde yanlış anlaşılmamalıdır.
Özellikle günümüz JVM'lerinde, gereksiz yere oluşturulan küçük nesnelerin oluşturulması ve geri alınması, çok yükleyici bir iş değildir. Bu nedenle, veri tabanı bağlantısı gibi maliyeti çok yüksek nesneler değilse, özel bir nesne havuzu oluşturmaktan kaçının.
Dahası, savunmacı bir kopyalamaya ihtiyaç duyulan bir durumda, nesnenin yeniden kullanılması durumunda meydana gelen zarar, gereksiz nesnelerin tekrar tekrar oluşturulması durumunda meydana gelen zarardan çok daha büyüktür. Tekrar tekrar oluşturmanın olumsuz etkisi yalnızca kod biçimini ve performansı etkilerken, savunmacı bir kopyalamanın başarısız olması, hata ve güvenlik sorunlarına yol açar.