제이온

[Java] Yansıma Kavramı ve Kullanım Şekli

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

Oluşturulma: 2024-04-25

Oluşturulma: 2024-04-25 22:27

Yansıma Nedir?

Yansıma, heap alanına yüklenmiş Class türündeki nesneler aracılığıyla istenen sınıfın örneğini oluşturmayı ve örneğin alanlarına ve yöntemlerine erişim belirleyicilerden bağımsız olarak erişmeyi sağlayan bir API'dir.



Burada yüklenmiş sınıf, JVM'nin sınıf yükleyicisinin sınıf dosyasını yüklemesini tamamlamasının ve ilgili sınıfın bilgilerini içeren Class türündeki nesneyioluşturup bellek heap alanında saklamasını ifade eder. new anahtar sözcüğü ile oluşturulan nesnelerden farklı olduğunu unutmayın. Eğer Class türündeki nesneler hakkında anlayışınız yetersiz ise java.lang.class nesnesinin JDK belgesini inceleyebilirsiniz.


Kullanım Şekli

Yansımayı kullanmadan önce, heap alanına yüklenmiş Class türündeki nesneyi edinmemiz gerekir. Bunun için toplamda 3 farklı yol bulunmaktadır.


  • Sınıf.class ile edinme
  • Örnek.getClass() ile edinme
  • Class.forName("SınıfAdı") ile edinme


3 farklı yolla edinilen Class türündeki nesnelerin hepsinin aynı olduğunu görebiliriz. Hash değeri aynı olduğundan, duruma göre uygun olanı kullanabiliriz.


Şimdi, edinilen Class türü aracılığıyla ilgili sınıfın örneğini oluşturabilir ve örneğin alanlarına ve yöntemlerine erişim belirleyicilerden bağımsız olarak erişebiliriz. Öncelikle ilgili sınıfın örneğini oluşturalım.


getConstructor() ile kurucuyu elde edebilir ve newInstance() ile dinamik olarak Member örneğini oluşturabiliriz.

Son olarak, örneğin alanlarına ve yöntemlerine erişim belirleyicilerden bağımsız olarak erişip kullanalım.

getDeclaredFileds() ile sınıfın örnek değişkenlerini elde edebilir, get() ile alan değerini döndürebilir ve set() ile alan değerini değiştirebileceğimizi görebiliriz. Burada dikkat edilmesi gereken nokta, private erişim belirleyicisine sahip bir alana erişirken setAccessible()'in parametresini true olarak geçirmemiz gerektiğidir.


Yöntemler için de getDeclaredMethod() ile yöntemi elde edebiliriz. Bu durumda, yöntemin adını ve parametrelerinin türünü birlikte parametre olarak geçirmemiz gerekir. Benzer şekilde, private erişim belirleyicisine sahip bir yönteme erişirken setAccessible()'in parametresini true olarak ayarlamalıyız. Son olarak, invoke() yöntemi ile yansıma API'si aracılığıyla elde edilen yöntemi çağırabiliriz.


Avantajlar ve Dezavantajlar

  • Avantajlar
    • Çalışma zamanında sınıfın örneğini oluşturup, erişim belirleyicilerden bağımsız olarak alanlara ve yöntemlere erişerek gerekli işlemleri gerçekleştirebilme esnekliğine sahiptir.
  • Dezavantajlar
    • Kapsüllenmeyi ihlal eder.
    • Çalışma zamanında örnek oluşturulduğundan, derleme zamanında ilgili türü denetleyemeyiz.
    • Çalışma zamanında örnek oluşturulduğundan, belirli işlem akışını anlamak zor olabilir.
    • Sadece alanlara ve yöntemlere erişmeye kıyasla, yansıma kullanarak erişim sağlamak performans açısından daha yavaştır. (Tüm durumlarda performans düşüklüğü yaşanmaz.)


Kullanım Nedenleri

Yansıma API'si aracılığıyla çalışma zamanında sınıf bilgilerine erişerek sınıfları istediğimiz gibi değiştirebiliriz. Hatta private erişim belirleyicisi ile tanımlanmış alanları ve yöntemleri bile değiştirebiliriz. Nesne yönelimli tasarımda önemli bir yer tutan kapsüllenme ilkesini ihlal ettiğinden, kullanılmaması gereken bir teknoloji gibi görünebilir.


Küçük ölçekli bir konsol uygulamasında, geliştirici derleme zamanında programda kullanılacak nesneleri ve bağımlılıkları kolayca anlayabilir. Ancak framework gibi büyük ölçekli bir geliştirme aşamasında, çok sayıda nesneyi ve bağımlılığı anlamak zor olabilir. Bu durumda yansıma kullanılarak dinamik olarak sınıflar oluşturularak bağımlılık ilişkileri kurulabilir.


Örneğin, Spring'in Bean Factory'sine baktığımızda, @Controller, @Service, @Repository gibi anotasyonları eklediğimizde Bean Factory'nin bu anotasyonlu sınıfları otomatik olarak oluşturup yönettiğini görebiliriz. Geliştirici Bean Factory'ye ilgili sınıfı bildirmemiştir, ancak bu durum yansıma sayesinde mümkün olur. Çalışma zamanında ilgili anotasyonlu sınıfları arayıp bulursa, yansıma aracılığıyla ilgili sınıfın örneğini oluşturur, gerekli alanları enjekte ederek Bean Factory'ye kaydeder.


Elbette, yukarıda bahsettiğimiz gibi kapsüllenmeyi ihlal ettiğinden, sadece gerçekten gerekli durumlarda kullanılması önerilir.


Kaynaklar

Yorumlar0