제이온

[Etkin Java] Madde 6. Gereksiz Nesne Oluşturmayı Önleyin

  • Yazım Dili: Korece
  • Baz Ülke: Tüm Ülkelercountry-flag
  • BT

Oluşturulma: 2024-04-28

Oluşturulma: 2024-04-28 13:40

Gereksiz Nesne Oluşturma Durumları

new String() Kullanımı


a, b ve c dizeleri hepsi "hi" metnini içerir. Ancak, bu üç dizenin referans verdiği adresler farklı olduğundan, aynı veri için farklı bellek alanları ayrılması gibi bir israf meydana gelir.


<span class="image-inline ck-widget" contenteditable="false"><img src="https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2Fa53d14aa-6abf-40f0-8441-435647d172fa%2FUntitled.png?table=block&id=f168859c-367c-4924-a4c6-5e04788fab67&spaceId=b453bd85-cb15-44b5-bf2e-580aeda8074e&width=2000&userId=80352c12-65a4-4562-9a36-2179ed0dfffb&cache=v2" alt="Untitled" style="aspect-ratio:2000/1146;" width="2000" height="1146"></span>


Bu nedenle, bir dize bildirdiğinizde new anahtar sözcüğünü kullanmak yerine doğrudan sabit değerle bildirmelisiniz.



Yukarıdaki kod parçası yalnızca bir örnek kullanır. Dahası, bu yöntemi kullanırsanız, aynı JVM içinde "hi" dize sabit değerini kullanan tüm kodların aynı nesneyi yeniden kullanmasını sağlar. Bu, Java sabit havuzunun özelliğinden kaynaklanır.


new Boolean() Kullanımı

Yukarıdaki kod, dizeyi parametre olarak alan bir oluşturucu aracılığıyla Boolean örneği oluşturur. Boolean yalnızca true veya false değerlerine sahip olabilir ve her seferinde bir örnek oluşturmak bellek israfına yol açar. Bu nedenle, Boolean.valueOf() gibi 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 nesnelerin maliyetini her zaman bilemeyiz. Örneğin, verilen bir dizenin geçerli bir Roma rakamı olup olmadığını kontrol eden bir yöntem yazmak istiyorsak, aşağıdaki gibi düzenli ifadeleri kullanmak en kolay yoldur.



Ancak String.matches() performans açısından sorunlu bir yöntemdir. Bu yöntemin içinde oluşturduğu düzenli ifade için Pattern örneği, bir kez kullanılıp atıldığından hemen çöp toplama hedefi haline gelir. Düzenli ifade tekrar tekrar kullanıldıkça, aynı Pattern örneğinin oluşturulup atılmasının maliyeti artar. Bu nedenle, Pattern örneğini önceden önbelleğe alıp, daha sonra isRomanNumeral() yöntemi çağrıldığında bu örneği yeniden kullanmak daha iyidir.



Dikkat Edilmesi Gerekenler

Yukarıdaki tüm örneklerde, gereksiz nesneleri önbelleğe alırken hepsi değişmez nesneler olarak oluşturuldu. Bu, yeniden kullanıldığında güvenli olmaları içindir. Ancak, değişmez nesne olarak yeniden kullanmanın sezgisel olarak tersine düştüğü durumlar vardır.


Uyarlayıcı (görünüm), gerçek işlemi arka uç nesnesine devreder ve kendisi ikinci bir arayüz görevi görür. Uyarlayıcı yalnızca arka uç nesnesini yönetmelidir, bu nedenle her arka uç nesnesi için yalnızca bir uyarlayıcı oluşturulmalıdır.


Örneğin, Map arayüzünün keySet() yöntemi, Map nesnesinin içindeki tüm anahtarları içeren Set görünümünü döndürür. Kullanıcı, keySet() yöntemini her çağırdığında yeni bir Set örneğinin oluşturulacağını düşünebilir, ancak gerçek JDK uygulamasını incelersek, her seferinde aynı değişken Set örneğini döndürdüğünü görürüz.


Bunun nedeni, döndürülen Set örneği değişken olsa bile, gerçekleştirdiği tüm işlevlerin aynı olması ve tüm Set örneklerinin Map örneğini temsil etmesidir. Bu nedenle, keySet() görünüm nesnesini birden çok kez oluştursa bile sorun olmaz, ancak bunu yapmanın da hiçbir faydası yoktur.



Bu nedenle, yukarıdaki gibi names1 örneğini değiştirdiğimizde, names2 örneği de etkilenir.


Ancak şahsi olarak, keySet() yönteminin dönüş değerinin, her seferinde yeni bir nesne döndürmek için savunmacı kopyalama kullanması gerektiğini düşünüyorum. Eğer keySet() yöntemi ile alınan Set örneği başka bir yerde de kullanılıyorsa ve bu örneğin durumunu değiştiren bir kod varsa, şu anda kullanılan Set örneği ile Map örneğinin değerleri hakkında emin olamayız.


Ayrıca, keySet() yöntemini aşırı derecede çok kullanan bir ortam olmadığı sürece, Set arayüzünün her seferinde oluşturulmasının performansa ölümcül bir etkisi olmaz. Aksine, Set arayüzünü değişmez bir nesne yaparak güvenli bir şekilde bakımını yapmak daha iyidir diye düşünüyorum.


Otomatik Kutuya Koyma

Otomatik kutuya koyma, programcıların temel türleri ve sarmalayıcı türleri karıştırarak kullanmaları durumunda otomatik olarak karşılıklı dönüşüm sağlayan bir tekniktir. Ancak otomatik kutuya koyma, temel türler ile sarmalayıcı türler arasındaki ayrımı bulanıklaştırır, tamamen ortadan kaldırmaz.



Mantıksal olarak sorun yok, ancak performans açısından çok verimsiz bir kod. Bunun nedeni, sum'ın türü ile for döngüsü içindeki i'nin türünden kaynaklanır.


sum'ın türü Long'dur ve i'nin türü long'dur. Yani, long türündeki i, döngüde sum'a eklenirken her seferinde yeni bir Long örneği oluşturur. Sonuç olarak, sarmalayıcı türlerden ziyade temel türleri kullanmalı ve istenmeyen otomatik kutuya koyma işleminin kullanılmamasına dikkat etmeliyiz.


Yanlış Anlaşılmaması Gereken Noktalar

Gereksiz nesne oluşturulmasını önlemenin, nesne oluşturma maliyeti yüksek olduğu için 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 nesneleri oluşturmak ve toplamak çok fazla yük getirmiyor. Bu nedenle, veritabanı bağlantısı gibi maliyeti çok yüksek nesneler değilse, özel nesne havuzu oluşturmayın.


Dahası, savunmacı kopyalamanın gerekli olduğu durumlarda nesneleri yeniden kullanmanın sonuçlarının, gereksiz nesneleri tekrar tekrar oluşturmanın sonuçlarından çok daha büyük olduğunu unutmayın. Tekrar tekrar oluşturmanın olumsuz etkileri yalnızca kod biçimini ve performansı etkiler, ancak savunmacı kopyalama başarısız olursa hatalara ve güvenlik sorunlarına yol açar.


Kaynaklar

Yorumlar0