Java sınıfları neden uygulanan arabirimlerden ek açıklamaları devralmaz?


108

Bazı yöntem çağrılarını engellemek için Guice'nin AOP'sini kullanıyorum. Sınıfım bir arabirim uyguluyor ve arabirim yöntemlerine açıklama eklemek istiyorum, böylece Guice doğru yöntemleri seçebilir. Ek açıklama türüne Devralınan ek açıklama uygulama sınıfı ile açıklama eklense bile , Devralınan'ın java belgesinde belirtildiği gibi ek açıklamayı devralmaz:

Ayrıca, bu meta ek açıklamanın yalnızca ek açıklamaların üst sınıflardan miras alınmasına neden olduğunu unutmayın; Uygulanan arabirimlerdeki açıklamaların hiçbir etkisi yoktur.

Bunun nedeni ne olabilir? Bir nesnenin sınıfının çalışma zamanında uyguladığı tüm arabirimleri tanımak, yapılması o kadar da zor bir şey değildir, bu nedenle bu kararın arkasında iyi bir neden olmalıdır.

Yanıtlar:


130

Bunun nedeni, aksi takdirde çoklu miras probleminin ortaya çıkmasıdır.

Misal:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD) @Inherited
public @interface Baz { String value(); }

public interface Foo{
    @Baz("baz") void doStuff();
}

public interface Bar{
    @Baz("phleem") void doStuff();
}

public class Flipp{
    @Baz("flopp") public void doStuff(){}
}

public class MyClass extends Flipp implements Foo, Bar{}

Bunu yaparsam:

MyClass.class.getMethod("doStuff").getAnnotation(Baz.class).value()

sonuç ne olacak? 'baz', 'phleem' veya 'flopp'?


Bu nedenle, arabirimlerdeki ek açıklamalar nadiren faydalıdır.


9
Arabirimlerdeki açıklamalar yalnızca onları destekleyen bir çerçeveye sahipseniz yararlıdır. Bu örnekte BTW getAnnotation () null döndürür;)
Peter Lawrey

6
Bilmiyorum millet. Bu durumda (yazım hatası yoksa), The field value is ambiguous.aynı sabiti farklı değerlerle bildiren iki arayüzde olduğu gibi benzer bir derleyici hatası beklerdim . Bunun bir alan olmadığını biliyorum , ancak ek açıklama değerlerinin tümü derleme sırasında çözülür, değil mi? Burada kaçırdığımız özellik, birçok durumda çok yardımcı olacaktır. Bu arada eski bir gönderiyi canlandırdığım için üzgünüm :).
Petr Janeček

7
@Slanec, Bahar adamlarının bu sorunların etrafında nasıl çalıştığını görmek için Bahar kaynaklarının yöntemine bir göz attı. Bkz. AnnotationUtils.findAnnotation (method, annotationType)
Sean Patrick Floyd

1
Buna benzer bir şey yazmayı düşünüyordum. Bir tür basit önbelleğe alma ile, bu benim için bir yol gibi görünüyor. Teşekkürler! Yukarıdaki örnekte, Foo'ek açıklamasını bulur (bir notu MyClassyoktur, daha sonra Arayüzler aranır ve sonradan geldikleri sıraya göre alınır implements) ve bu nedenle "baz" yazdırır. Güzel.
Petr Janeček

2
@WChargin doğru, birinin bu yazım hatasını fark etmesi 2 yıl sürdü :-)
Sean Patrick Floyd

35

Gönderen Javadoc @Inherited için:

Bir ek açıklama türünün otomatik olarak miras alındığını gösterir. Ek açıklama türü bildiriminde Devralınan meta ek açıklama varsa ve kullanıcı sınıf bildiriminde ek açıklama türünü sorgularsa ve sınıf bildiriminde bu tür için ek açıklama yoksa, sınıfın üst sınıfı otomatik olarak ek açıklama türü için sorgulanır. Bu işlem, bu tür için bir açıklama bulunana veya sınıf hiyerarşisinin (Nesne) en üstüne ulaşılana kadar tekrarlanacaktır. Hiçbir üst sınıfın bu tür için bir ek açıklaması yoksa, sorgu söz konusu sınıfın böyle bir ek açıklaması olmadığını belirtir. Ek açıklamalı tür, sınıftan başka herhangi bir şeye açıklama eklemek için kullanılırsa, bu meta ek açıklama türünün hiçbir etkisi olmadığını unutmayın. Ayrıca, bu meta ek açıklamanın yalnızca ek açıklamaların üst sınıflardan miras alınmasına neden olduğunu unutmayın;

Öte yandan, JSR 305 doğrulayıcıları bir çeşit miras araması yapar. Bir sınıf hiyerarşiniz varsa:

//Person.java
@Nonnull
 public Integer getAge() {...}

//Student.java (inherits from Person)
@Min(5)
public Integer getAge() {...}

Sonra etkin doğrulamalar üzerinde Student.getAge()bulunmaktadır @Nonnull @Min(5). meta ek açıklamasına @Nonnullsahip değil @Inherited.


4
Bu seçilen cevap olmalı
Andrzej Purtak

3
Örneğiniz cevabınızla çelişiyor, bu da @Inheritedsınıf dışında hiçbir etkisi olmadığını söylüyor
Oleg Mikheev

@ Devralınan, yalnızca Sınıf üzerindeki notu kullandığınızda çalışır
Carlos Parker
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.