[java] 🚀 Yansıma nedir ve neden faydalıdır?
Java ile özellikle ilgileniyorum, ancak ilkelerin herhangi bir dilde aynı olduğunu kabul ediyorum.
Ad yansıması, aynı sistemdeki (veya kendisi) diğer kodları kontrol edebilecek kodu tanımlamak için kullanılır.
Örneğin, Java’da bilinmeyen türde bir nesneye sahip olduğunuzu ve varsa bir “doSomething” yöntemini çağırmak istediğinizi varsayalım. Java'nın statik yazma sistemi, nesne bilinen bir arayüze uymadığı sürece bunu destekleyecek şekilde tasarlanmamıştır, ancak yansıma kullanarak kodunuz nesneye bakabilir ve 'doSomething' adında bir yöntem olup olmadığını öğrenebilir ve ardından istemek.
Bu yüzden, Java'da size bunun bir kod örneğini vermek için (söz konusu nesnenin foo olduğunu hayal edin):
Java'da çok yaygın bir kullanım örneği, ek açıklama içeren kullanımdır. Örneğin JUnit 4, @Test ek açıklamasıyla etiketlenmiş yöntemler için sınıflarınıza bakmak için yansıma kullanacak ve daha sonra ünite testini çalıştırırken bunları arayacaktır.
Http://docs.oracle.com/javase/tutorial/reflect/index.html adresinde başlamanız için bazı iyi yansıma örnekleri vardır.http://docs.oracle.com/javase/tutorial/reflect/index.html
Ve son olarak, evet, kavramlar yansımayı destekleyen diğer statik tip dillerde oldukça benzerdir (C # gibi). Dinamik olarak yazılmış dillerde, yukarıda açıklanan kullanım durumu daha az gereklidir (derleyici herhangi bir nesnenin çağrılmasına izin verir, çünkü çalışma zamanında mevcut değilse başarısız olur), ancak işaretli yöntemleri aramanın ikinci durumu Belli bir şekilde çalışmak hala yaygındır.
Bir yorumdan güncelleme:
Sistemdeki kodu inceleme ve nesne türlerini görme yeteneği yansıma değil, Yazım Denetimi'dir. Daha sonra yansıma, iç denetimden faydalanarak çalışma zamanında değişiklik yapma yeteneğidir. Buradaki ayrım, bazı dillerin iç gözlemi desteklediği, ancak yansımayı desteklemediği için gereklidir. Böyle bir örnek C ++
Matt Sheppard2008-09-012008-09-01 08:44:58Z
Yansıma , bir dilin çalışma zamanında sınıfları, yöntemleri, nitelikleri vb. Denetleme ve dinamik olarak arama yeteneğidir.
Örneğin, Java'daki tüm nesneler getClass() , derleme zamanında bilmiyor olsanız bile (örneğin, bunu bir olarak ilan ettiyseniz Object ) nesnenin sınıfını belirlemenizi sağlayan bir yönteme sahiptir - bu önemsiz görünebilir, ancak bu tür bir yansıma mümkün olmayabilir gibi daha az dinamik dillerde C++ . Daha gelişmiş kullanımlar, yöntemleri, yapıcıları vb. Listeleyip çağırmanızı sağlar.
Yansıma önemlidir, çünkü derleme zamanında her şeyi "bilmek" zorunda olmayan programları daha fazla dinamik hale getirir, çünkü çalışma zamanında birbirine bağlanabilirler. Kod bilinen arayüzlere karşı yazılabilir, ancak kullanılacak gerçek sınıflar, yapılandırma dosyalarından yansıma kullanılarak başlatılabilir.
Modern çerçevelerin çoğu bu sebepten dolayı yansımayı yoğun olarak kullanıyor. Diğer birçok modern dil de yansıma kullanır ve betik dillerinde (Python gibi), bu dillerin genel programlama modelinde daha doğal hissettiğinden daha sıkı bir şekilde bütünleşir.
En sevdiğim yansıma kullanımlarından biri, aşağıdaki Java boşaltma yöntemidir. Herhangi bir nesneyi parametre olarak alır ve her alan adını ve değerini yazdırmak için Java yansıma API'sini kullanır.
Ben Williams2008-09-022008-09-02 16:15:28Z
Yansıma, Java sanal makinesinde çalışan uygulamaların çalışma zamanı davranışını inceleme veya değiştirme becerisi gerektiren programlar tarafından yaygın olarak kullanılır. Bu nispeten gelişmiş bir özelliktir ve yalnızca dilin temellerini anlayabilen geliştiriciler tarafından kullanılmalıdır. Bu uyarı göz önüne alındığında, yansıma güçlü bir tekniktir ve uygulamaların aksi takdirde imkansız olacak işlemleri gerçekleştirmelerini sağlayabilir.
Bir uygulama, tam nitelikli adlarını kullanarak genişletilebilirlik nesnelerinin örnekleri oluşturarak, kullanıcı tarafından tanımlanan harici sınıfları kullanabilir. Sınıf Tarayıcıları ve Görsel Geliştirme Ortamları Bir sınıf tarayıcısının, sınıf üyelerini sıralayabilmesi gerekir. Görsel geliştirme ortamları, geliştiricinin doğru kodu yazmasına yardımcı olmak için yansıma türündeki bilgileri kullanmanın yararlarından yararlanabilir. Hata Ayıklayıcılar ve Test Araçları Hata ayıklayıcıların sınıftaki özel üyeleri inceleyebilmesi gerekir. Test donanımları, bir test takımında yüksek düzeyde kod kapsamı sağlamak için bir sınıfta tanımlanmış keşfedilebilir ayarlanmış API'leri sistematik olarak çağırmak için yansımadan yararlanabilir.
Yansıma güçlüdür, ancak ayrım gözetmeden kullanılmamalıdır. Yansıma kullanmadan bir işlem yapmak mümkün ise, kullanmaktan kaçınmak tercih edilir. Yansıma yoluyla koda erişirken aşağıdaki endişeler akılda tutulmalıdır.
Yansıma, dinamik olarak çözümlenmiş türleri içerdiğinden, belirli Java sanal makinesi optimizasyonları gerçekleştirilemez. Sonuç olarak, yansıtıcı işlemler yansıtıcı olmayan emsallerinden daha yavaş performans gösterir ve performansa duyarlı uygulamalarda sık olarak adlandırılan kod bölümlerinden kaçınılmalıdır.
Yansıtma, bir güvenlik yöneticisi altında çalışırken bulunmayabilecek bir çalışma zamanı izni gerektirir. Bu, Applet gibi sınırlı bir güvenlik bağlamında çalışması gereken kod için önemli bir husustur.
İnternalların Maruz Kalması
Yansıma, kodun, özel alanlara ve yöntemlere erişmek gibi yansıtıcı olmayan kodda yasadışı olabilecek işlemleri gerçekleştirmesine izin verdiğinden, yansıma kullanımı, kodu işlevsiz hale getirebilecek ve taşınabilirliği bozabilecek beklenmeyen yan etkilere neden olabilir. Yansıtıcı kod soyutlamaları bozar ve bu nedenle platformun yükseltilmesiyle davranışını değiştirebilir.
kaynak: Yansıma API'si
Desmond Smith2014-10-172014-10-17 11:59:33Z
Yansıma, bir uygulamanın veya çerçevenin henüz yazılmamış bile olsa kodla çalışmasına izin veren önemli bir mekanizmadır!
Örneğin, tipik web.xml dosyanızı alın. Bu, yuvalanmış bir sunucu uygulaması sınıfı öğeleri içeren bir sunucu uygulaması öğeleri listesi içerir. Sunucu uygulaması kabı, web.xml dosyasını işleyecek ve yansıma yoluyla her bir sunucu uygulaması sınıfının yeni bir örneğini oluşturacaktır.
Başka bir örnek, XML Ayrıştırma için Java API (JAXP) olacaktır . Bir XML ayrıştırıcı sağlayıcısının, yansıma yoluyla yeni örnekler oluşturmak için kullanılan, iyi bilinen sistem özellikleriyle 'takılı' olduğu durumlarda.
Ve son olarak, en kapsamlı örnek, fasulyelerini oluşturmak için yansıma kullanan ve ağır proxy kullanımı için Bahar .
Her dil yansıtmayı desteklemez, ancak ilkeler genellikle onu destekleyen dillerde aynıdır.
Yansıtma, programınızın yapısını "yansıtma" yeteneğidir. Veya daha somut. Sahip olduğunuz nesnelere ve sınıflara bakmak ve programlı olarak uyguladıkları yöntemler, alanlar ve arayüzler hakkında bilgi almak için. Ek açıklamalar gibi şeylere de bakabilirsiniz.
Birçok durumda faydalıdır. Dinamik olarak sınıfları kodunuza eklemek istediğiniz her yerde. Çok sayıda nesne ilişkisel eşleştiricisi, hangi nesneleri kullanacaklarını önceden bilmeden, veritabanlarından nesneleri başlatabilmek için yansıma kullanır. Eklenti mimarileri, yansımanın kullanışlı olduğu başka bir yerdir. Kodu dinamik olarak yükleyebilmek ve orada eklenti olarak kullanmak için doğru arayüzü kullanan türler olup olmadığını belirlemek bu durumlarda önemlidir.
Yansıma, uygulama hakkında önceden bilgi sahibi olmadan çalışma sırasında dinamik olarak çalışma sırasında yeni nesnelerin somutlaştırılmasına, yöntemlerin çağrılmasına ve sınıf değişkenlerinde get / set işlemlerine izin verir.
Yukarıdaki örnekte, null parametresi, yöntemi çağırmak istediğiniz nesnedir. Metot statik ise null sağlayın. Eğer yöntem statik değilse, çağırırken null yerine geçerli bir MyObject örneği vermeniz gerekir.
Yansıtma ayrıca, bir sınıfın özel üyesine / yöntemlerine erişmenizi sağlar:
Sınıfların incelenmesi için (ayrıca inceleme olarak da bilinir) yansıma paketini ( java.lang.reflect ) içe aktarmanız gerekmez . Sınıf meta verilerine erişilebilir java.lang.Class .
Yansıtma çok güçlü bir API'dir, ancak çalışma zamanındaki tüm türleri çözdüğü için aşırı kullanılırsa uygulamayı yavaşlatabilir.
Nikhil Shekhar2013-07-082013-07-08 16:12:04Z
Java Reflection oldukça güçlü ve çok faydalı olabilir. Java Reflection , derleme zamanında sınıfların adlarını, yöntemlerini vb. Bilmeden çalışma zamanındaki sınıfları, arayüzleri, alanları ve yöntemleri incelemeyi mümkün kılar . Yansıma kullanarak yeni nesneleri başlatmak, yöntemleri çağırmak ve alan değerlerini almak / ayarlamak da mümkündür .
Yansıma kullanmanın size neye benzediğini gösteren hızlı bir Java Yansıması örneği:
Bu örnek, Class nesnesini MyObject adlı sınıftan alır. Sınıf nesnesini kullanarak, örnek o sınıftaki yöntemlerin bir listesini alır, yöntemleri yineler ve adlarını yazdırır.
Tam olarak tüm bu işler burada nasıl açıklanmaktadır?
Düzenleme : Neredeyse 1 yıl sonra bu cevabı değiştiriyorum, yansıma hakkında okurken Reflection'dan daha az faydalandım.
Yay, aşağıdaki gibi fasülye konfigürasyonunu kullanır:
Spring bağlamı bu <bean> öğesini işlediğinde, bu sınıfı başlatmak için Class.forName (String) "com.example.Foo" argümanıyla kullanır.
Daha sonra <özellik> elemanı için uygun ayarlayıcıyı elde etmek için yansıma kullanacak ve değerini belirtilen değere ayarlayacaktır.
Junit, özellikle Özel / Korumalı yöntemleri test etmek için Yansıma'yı kullanır.
Örneğin, uygulamanıza API Yöntemlerini kullanarak edindiğiniz bir nesneyi veren uzak bir uygulamayı ele alalım. Şimdi nesneyi temel alarak bir çeşit hesaplama yapmanız gerekebilir.
Sağlayıcı, bu nesnenin 3 tip olabileceğini garanti eder ve ne tür bir nesne temelinde hesaplama yapmamız gerekir.
Bu yüzden, her biri farklı bir mantık içeren 3 sınıfa uygulayabiliriz. Açıkçası, nesne bilgisi çalışma zamanında mevcuttur, bu nedenle hesaplama yapmak için statik olarak kodlama yapamazsınız, bu nedenle yansıma, hesaplamayı gerçekleştirmek için ihtiyaç duyduğunuz sınıfın nesnesini başlatmak için kullanılır. sağlayıcıdan alınan nesne.
Yansıma , çalışma zamanında yöntemlerin, sınıfların, arabirimlerin davranışlarını incelemek veya değiştirmek için kullanılan bir API'dir .
Yansıma için gerekli sınıflar altında verilmiştir java.lang.reflect package .
Yansıma bize bir nesnenin ait olduğu sınıf ve aynı zamanda nesneyi kullanarak gerçekleştirilebilecek sınıflar hakkında bilgi verir.
Yansıma yoluyla, çalışma zamanında, bunlarla kullanılan erişim belirtecinden bağımsız olarak yöntemleri çağırabiliriz.
java.lang Ve java.lang.reflect paketler java yansıması için sınıfları sağlar.
Yansıma hakkında bilgi almak için kullanılabilir -
Sınıf getClass() Bir nesnenin ait olduğu sınıfın adını almak için bu yöntem kullanılır.
Yapıcılar getConstructors() yöntem nesnesinin ait olduğu sınıfın genel kurucular elde etmek için kullanılır.
Yöntem getMethods() yöntem, nesnelerin ait olduğu sınıfın genel yöntemleri elde etmek için kullanılır.
Reflection API esas olarak kullanılır:
IDE (Tümleşik Geliştirme Ortamı) örneğin Eclipse, MyEclipse, NetBeans vb.
Hata Ayıklayıcı ve Test Araçları vb.
Yansıma Kullanmanın Avantajları:
Genişletilebilirlik Özellikleri: Bir uygulama, tam nitelikli adlarını kullanarak genişletilebilirlik nesnelerinin örnekleri oluşturarak, kullanıcı tarafından tanımlanan harici sınıfları kullanabilir.
Hata ayıklama ve test araçları: Hata ayıklayıcılar, sınıflardaki özel üyeleri incelemek için yansıma özelliğini kullanır.
Performans Tepegözü: Yansıtıcı işlemler, yansıtıcı olmayan emsallerinden daha yavaş performans gösterir ve performansa duyarlı uygulamalarda sık olarak adlandırılan kod bölümlerinden kaçınılmalıdır.
İçsellerin Maruz Kalması: Yansıtıcı kod soyutlamaları bozar ve bu nedenle platformun yükseltilmesiyle davranışını değiştirebilir.
Ref: Java Yansıma javarevisited.blogspot.in
Yansıma için basit bir örnek. Bir satranç oyununda, kullanıcı tarafından çalışma zamanında ne taşınacağını bilmiyorsunuz. Yansıma, çalışma zamanında zaten uygulanan yöntemleri çağırmak için kullanılabilir:
Isuru Jayakantha2014-11-062014-11-06 04:42:31Z
Yansıtma, programcının programdaki varlıklara dinamik olarak erişmesini sağlar. yani eğer programcı bir sınıftan veya onun yöntemlerinden habersizse, bir uygulamayı kodlarken, bu sınıftan yansıma kullanarak dinamik olarak (çalışma zamanında) faydalanabilir.
Bir sınıf adının sık sık değiştiği senaryolarda sıklıkla kullanılır. Böyle bir durum ortaya çıkarsa, programcının uygulamayı yeniden yazması ve sınıfın adını tekrar tekrar değiştirmesi karmaşıktır.
Bunun yerine, yansıma kullanarak, muhtemelen değişen bir sınıf adı için endişelenmeniz gerekir.
Yansıma, programınızın çalışma zamanı bilgisine erişmenizi ve davranışını değiştirmenizi sağlayan bir takım işlevdir (bazı sınırlamalarla).
Bu, programınızın meta bilgisine bağlı olarak çalışma zamanını değiştirmenize izin verdiği için yararlıdır, yani, bir işlevin dönüş türünü kontrol edebilir ve durumu işleme şeklinizi değiştirebilirsiniz.
Örneğin, C # 'da bir derleme (a .dll) çalışma zamanında yükleyebilir, inceleyebilir, sınıflar arasında gezinebilir ve bulduklarınıza göre işlem yapabilirsiniz. Ayrıca, çalışma zamanında bir sınıf örneği oluşturmanızı, yöntemini çağırmanızı vb. Sağlar.
Nerede yararlı olabilir? Her zaman işe yaramaz, ancak somut durumlar için faydalıdır. Örneğin, oturum açma amaçları için sınıfın adını almak, bir yapılandırma dosyasında belirtilenlere göre olaylar için dinamik olarak işleyiciler oluşturmak için kullanabilirsiniz.
Jorge Córdoba2008-09-012008-09-01 08:50:52Z
Yansıma nesnenin görünüşünü görmesine izin vermektir. Bu argüman yansıma ile ilgisi yok gibi görünüyor. Aslında, bu "kendini tanımlama" yeteneğidir.
Yansımanın kendisi, Java ve C # olarak kendi kendini tanıma ve kendini algılama yeteneğine sahip olmayan diller için bir kelimedir. Öz-bilgi kabiliyetine sahip olmadıkları için, nasıl göründüğünü gözlemlemek istediğimizde, nasıl göründüğünü yansıtacak başka bir şeyimiz olmalı. Ruby ve Python gibi mükemmel dinamik diller, diğer kişilerin yardımı olmadan kendi yansımasını algılayabilir. Java nesnesinin, yansıma sınıfının bir nesnesi olan bir ayna olmadan nasıl göründüğünü anlayamadığını söyleyebiliriz, ancak Python'daki bir nesne onu ayna olmadan algılayabilir. Bu yüzden Java'da yansımaya ihtiyacımız var.
Marcus Thornton2015-12-082015-12-08 07:02:19Z
Sadece listelenenlerin tümüne bir nokta eklemek istiyorum.
Reflection API ile toString() herhangi bir nesne için evrensel yöntem yazabilirsiniz .
Hata ayıklamada kullanışlıdır.
İşte bazı örnek:
Java dokümantasyon sayfasından
java.lang.reflect paket, sınıflar ve nesneler hakkında yansıtıcı bilgiler elde etmek için sınıflar ve arayüzler sağlar. Yansıtma, yüklenen sınıfların alanları, yöntemleri ve yapıcıları ve yansıtılan alanların, yöntemlerin ve yapıcıların, güvenlik kısıtlamaları dahilindeki temel meslektaşları üzerinde çalışmak için kullanılması hakkında bilgilere programatik erişim sağlar.
AccessibleObject gerekli ReflectPermission olması halinde erişim kontrollerinin engellenmesine izin verir .
İle birlikte bu pakette Sınıflar, java.lang.Class böyle debugger'lar, tercümanlar, nesne müfettişleri, sınıf tarayıcılar ve gibi hizmetleri gibi uygulamalar barındırmak Object Serialization ve JavaBeans bir hedef nesnenin kamu üyelerine ya o ihtiyacı erişimi (kendi çalışma zamanı sınıfına göre) veya üyeleri tarafından ilan verilen bir sınıf
Aşağıdaki işlevselliği içerir.
Sınıf nesnelerinin elde edilmesi,
Bir sınıfın özelliklerinin incelenmesi (alanlar, yöntemler, yapıcılar),
Alan değerlerini belirlemek ve almak,
Yeni nesne örnekleri oluşturma.
Sınıf tarafından maruz bırakılan yöntemler için bu dokümantasyon bağlantısına bir göz atın Class .
Bu makaleden (Dennis Sosnoski, Sosnoski Yazılım Çözümleri, Inc Başkanı) ve bu makaleden (güvenlik araştırmaları pdf):
Reflection kullanımından çok dezavantajlar görebiliyorum
Program bileşenlerini dinamik olarak bağlamak için çok yönlü bir yol sağlar
Nesnelerle çok genel yollarla çalışan kütüphaneler oluşturmak için kullanışlıdır.
Alan ve yöntem erişimi için kullanıldığında yansıma doğrudan koddan daha yavaştır.
Kodunuzda gerçekte neler olup bittiğini gizleyebilir
Kaynak kodunu atlar bakım sorunları yaratabilir
Yansıtma kodu aynı zamanda ilgili doğrudan koddan daha karmaşıktır.
Veri erişim koruması ve tür güvenliği gibi temel Java güvenlik kısıtlamalarının ihlal edilmesini sağlar
Sınırlı sınıfların yüklenmesi,
Kısıtlı bir sınıfın yapıcılarına, yöntemlerine veya alanlarına referans alma,
Yeni nesne örnekleri oluşturma, yöntemleri başlatma, kısıtlanmış bir sınıfın alan değerlerini alma veya ayarlama.
Yansıma özelliğinin kötüye kullanılmasıyla ilgili bu SE soruya bir göz atın:
Java'da özel bir alanı nasıl okurum?
Bir sistem kodundan yürütülen işlevlerinin güvensiz kullanımı da kolayca bir Java güvenlik modunun uzlaşmasına yol açabilir . Yani bu özelliği az miktarda kullanın
Ravindra babu2016-02-132016-02-13 12:33:45Z
Adından da anlaşılacağı gibi, çalışma zamanında dinamik olarak örnek oluşturma yöntemini çağırmak için özellik sağlama dışında, sınıf yöntemi vb.
Ahşabın altındaki birçok çerçeve ve uygulama tarafından, gerçekte kodu bilmeden hizmet çağırmak için kullanılır.
Mohammed Sarfaraz2017-04-092017-04-09 02:29:34Z
Yansıma size daha genel kod yazma yeteneği verir. Çalışma zamanında bir nesne oluşturmanıza ve çalışma zamanında onun yöntemini çağırmanıza olanak tanır. Dolayısıyla program oldukça parametreli hale getirilebilir. Ayrıca, nesnenin ve sınıfın dış dünyaya maruz kalan değişkenlerini ve yöntemini tespit etmesine izin verir.
saumik gupta2016-04-262016-04-26 22:54:49Z
Reflection birçok kullanım alanı vardır . Daha aşina olduğum, anında kod oluşturabilmek.
IE: dinamik sınıflar, fonksiyonlar, yapıcılar - herhangi bir verilere dayanarak (xml / array / sql results / hardcoded / etc ..)
Ess Kay2013-05-062013-05-06 20:16:28Z
Bu soruya örnek olarak cevap vermek istiyorum. Her şeyden önce Hibernate proje , çalışan uygulama ile kalıcılık deposu arasındaki uçurumun köprülenmesi için ifadeler Reflection API üretmek CRUD için kullanır . Etki alanında bir şeyler değiştiğinde, Hibernate onları veri deposuna sürdürebilmeleri ve bunun tersi de bilmek zorundadır.
Alternatif olarak çalışır Lombok Project . Derleme zamanında yalnızca kodu enjekte eder, kodun etki alanı sınıflarınıza eklenmesiyle sonuçlanır. (Ben alıcılar ve ayarlayıcılar için tamam olduğunu düşünüyorum)
Hibernate reflection bir uygulama için oluşturma işlemi üzerinde çok az etkisi olduğu için seçti .
Ve Java 7'den bizde olduğu MethodHandles gibi çalışıyoruz Reflection API . Projelerde, loggerlerle çalışmak için bir sonraki kodu kopyalayıp yapıştırıyoruz:
Çünkü bu durumda yazım hatası yapmak zor.
Örnek olarak açıklamayı en iyi bulduğum gibi, cevapların hiçbiri de öyle görünmüyor ...
Yansımaları kullanmanın pratik bir örneği, Java'da yazılmış bir Java Dil Sunucusu veya PHP'de yazılmış bir PHP Dil Sunucusu olabilir. Yazarken olası tüm eşleşmeleri göstermek için tüm etiket adlarının (otomatik olarak tamamlanabilen kelimeler) sahip olması için, Dil Sunucusu'nun, doc blokları ve özel üyeler dahil olmak üzere sınıfla ilgili her şeyi incelemesi gerekir. Bunun için söz konusu sınıfın bir yansımasına ihtiyacı var.
Farklı bir örnek, özel bir yöntemin birim testi olabilir. Bunu yapmanın bir yolu, bir yansıma oluşturmak ve testin kurulum aşamasında yöntemin kapsamını halka açıklamaktır. Tabii ki kişi özel yöntemlerin doğrudan test edilmemesi gerektiğini, ancak mesele bu olmadığını iddia edebilir.
WebKit nedir ve CSS ile ilişkisi nedir?
SQL OVER () yan tümcesi - ne zaman ve neden yararlıdır?
Modern Python'da özel istisnaları ilan etmenin doğru yolu?
Değiştirilmemiş olarak işaretlenmiş dosyaların bir listesini alabilir miyim?