@Override gibi ek açıklamalar Java'da dahili olarak nasıl çalışır?


93

Java'da ek açıklamaların dahili olarak nasıl çalıştığını bana açıklayan var mı?

Java'da java.lang.annotation kitaplığını kullanarak nasıl özel açıklamalar oluşturabileceğimizi biliyorum. Ama yine de dahili olarak nasıl çalıştığını anlamıyorum, örneğin @Override ek açıklaması.

Biri bunu detaylı olarak açıklayabilirse gerçekten minnettar olacağım.


4
"Dahili olarak çalışmak" ile ne demek istiyorsun? Derleyici mi? Çalışma zamanı?
chrylis

3
@chrylis Work dahili olarak, bu yöntemin geçersiz kılma yöntemi olduğunu veya bunun geçersiz kılma yöntemi olmadığını nasıl otomatik olarak tanımladığı anlamına gelir. Her iki seferde de çalışır. derleme zamanında ek açıklamayı geçersiz kılma çalışması ve yay denetleyicisi açıklamasının çalışma zamanında çalışması gibi
Chirag Dasani

Yanıtlar:


138

Ek açıklama türleri arasındaki ilk temel ayrım, bunların derleme sırasında kullanılıp atılmaması (beğenilmesi @Override) veya derlenmiş sınıf dosyasına yerleştirilmesi ve çalışma zamanında (Spring'inki gibi @Component) kullanılabilir olmasıdır. Bu, ek açıklamanın @ Saklama politikası tarafından belirlenir . Kendi açıklamanızı yazıyorsanız, açıklamanın çalışma zamanında (belki otomatik yapılandırma için) veya yalnızca derleme zamanında (kontrol veya kod oluşturma için) yararlı olup olmadığına karar vermeniz gerekir.

Ek açıklamalarla birlikte kod derlerken, derleyici ek açıklamayı, erişim değiştiricileri ( public/ private) veya gibi kaynak öğelerde diğer değiştiricileri gördüğü gibi görür final. Bir ek açıklama ile karşılaştığında, belirli bir ek açıklamayla ilgilendiğini söyleyen bir eklenti sınıfı gibi bir açıklama işlemcisi çalıştırır. Açıklama işlemcisi genellikle derlenen öğeleri incelemek için Yansıma API'sini kullanır ve bunlar üzerinde kontroller çalıştırabilir, değiştirebilir veya derlenecek yeni kod oluşturabilir. @Overrideilkine bir örnektir; Üst sınıflardan birinde yöntem imzası için bir eşleşme bulabileceğinden emin olmak için Reflection API'yi kullanır ve yapamazsa Messagerbir derleme hatasına neden olmak için öğesini kullanır .

Ek açıklama işlemcilerinin yazılmasıyla ilgili bir dizi öğretici vardır; işte yararlı bir tane . İlgili yöntemlerle bak arayüzü derleyici bir açıklama işlemci başlatır nasıl; ana işlem , derleyicinin eşleşen bir ek açıklamaya sahip bir öğeyi her gördüğünde çağrılan yöntemde gerçekleşir .Processorprocess


4
Bize Spring'in açıklama işlemcisinin @Component'ı nasıl ayrıştırdığını ve sınıfı kapsayıcısına nasıl enjekte ettiğini tam olarak göstermek güzel olurdu
Junchen Liu,

@shanyangqu Bahara özgü olmayan bu soru için konu dışı. Son işlemci sınıflarını kendiniz okuyabilirsiniz.
chrylis

42

Başkalarının önerdiklerinin yanı sıra, ek açıklamanın nasıl çalıştığını görmek için özelleştirilmiş bir açıklama ve işlemcisini sıfırdan yazmanızı öneririm.

Kendi başıma, örneğin, yöntemlerin derleme zamanında aşırı yüklenip yüklenmediğini kontrol etmek için bir açıklama yazdım.

İlk olarak, adlı bir açıklama oluşturun Overload. Bu ek açıklama yönteme uygulanır, bu yüzden ona ek açıklama yaparım@Target(value=ElementType.METHOD)

package gearon.customAnnotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Target;

@Target(value=ElementType.METHOD)
public @interface Overload {

}

Ardından, tanımlı açıklama ile açıklanmış öğeleri işlemek için karşılık gelen işlemciyi oluşturun. İle açıklama eklenen yöntem için @Overload, imzası birden fazla görünmelidir. Veya hata yazdırılır.

package gearon.customAnnotation;

import java.util.HashMap;
import java.util.Map.Entry;
import java.util.Set;

import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.tools.Diagnostic.Kind;

@SupportedAnnotationTypes("gearon.customAnnotation.Overload")

public class OverloadProcessor extends AbstractProcessor{

    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        // TODO Auto-generated method stub
        HashMap<String, Integer> map = new HashMap<String, Integer>();

        for(Element element : roundEnv.getElementsAnnotatedWith(Overload.class)){
            String signature = element.getSimpleName().toString();
            int count = map.containsKey(signature) ? map.get(signature) : 0;
            map.put(signature, ++count);
        }

        for(Entry<String, Integer> entry: map.entrySet()){
            if(entry.getValue() == 1){
                processingEnv.getMessager().printMessage(Kind.ERROR, "The method which signature is " + entry.getKey() +  " has not been overloaded");
            }
        }
        return true;
    }
}

Ek açıklamayı ve sürecini bir jar dosyasına @Overloadpaketledikten sonra, javac.exe ile bir sınıf oluşturun ve onu derlemek için kullanın.

import gearon.customAnnotation.Overload;

public class OverloadTest {
    @Overload
    public static void foo(){
    }

    @Overload
    public static void foo(String s){

    }

    @Overload
    public static void nonOverloadedMethod(){

    }
} 

Yana nonOverloadedMethod()aslında aşırı edilmedi, aşağıda gibi çıktıyı alırsınız:

görüntü açıklamasını buraya girin


Yukarıdaki bilgiler JDK6'ya çok saygı duyuyor (bunun için +1), ancak aynı şeyi JDK5 kullanarak nasıl başarabiliriz? JDK6 SupportedAnnotationTypes, AbstractProcessor sınıfını kullanarak daha basit hale geldi, ancak geçmişte aynı şey nasıl oldu (jdk5'teki Spring FrameWork 2.5 gibi) JVM, jdk5'teki sınıf gibi açıklama işlemcisini nasıl algılar? 2. bölümdeki cevabı düzenleyerek rehberlik edebilir misiniz (bir tane JDK5 için, Mevcut Sürüm Jdk6 + için)?
prajitgandhi

Sınıfınızda OverloadProcessor::processneden var entry.getValue() == 1? Ana sınıfa / arayüze bir açıklama eklemek zorunda değilsiniz, bu yüzden ana sınıfı / arayüzü roundEnv.getElementsAnnotatedWith(Overload.class)almayacaksınız, değil mi?
Raining

Bu kısımda kafam karıştı ama cevabınızın çok yardımcı olduğunu düşünüyorum.
Raining

@ s̮̦̩e̝͓c̮͔̞ṛ̖̖e̬̣̦t̸͉̥̳̼ Bir yöntem Aşırı Yük olarak değerlendirilirse, Sınıfta tanımlanan aynı ada sahip en az başka bir yöntem olmalıdır.
Eugene

1
Bir yöntemin Aşırı Yüklendi demek için @Raining, aynı sınıfta birden fazla görünmesi gerekir, ancak `== 1` ise bu bir hatadır.
KrishPrabakar

5

İşte @Override: http://www.docjar.com/html/api/java/lang/Override.java.html .

Kendinize yazabileceğiniz bir açıklamadan ayıran özel bir şey yok. İlginç bitler , ek açıklamaların tüketicilerindedir . Böyle bir açıklama @Overrideiçin, bu Java derleyicisinin kendisinde veya statik bir kod analiz aracında veya IDE'nizde olabilir.


1
Geçersiz Kılma ek açıklamasının kaynak kodunu biliyorum. Ama içeride nasıl çalıştığı. nasıl tanımlanabileceği gibi, bu yöntem geçersiz kılma yöntemi değil mi yoksa bu geçersiz kılma yöntemi mi? veya özel geçersiz kılma ek açıklamamı oluşturabilir miyim? ve java geçersiz kılma notu gibi tam olarak aynı davranışta çalışmalıdır
Chirag Dasani

3
Cevabımda söylediğim gibi , davranış ek açıklamanın bir parçası değildir. Yorum, açıklamayı tüketen şeylerde yatmaktadır. Bu nedenle, tüketiciyi değiştirmediğiniz sürece, kendi özel sürümünüzü @Override(veya diğer standart ek açıklamaları) pratik olarak oluşturamazsınız .
Matt Ball

3

Temel olarak, ek açıklamalar yalnızca derleyici veya uygulama tarafından okunan işaretçilerdir. Saklama politikalarına bağlı olarak, yalnızca derleme zamanında kullanılabilirler veya yansıma kullanılarak çalışma zamanında okunabilirler.

Birçok çerçeve çalışma zamanı saklama kullanır, yani bir sınıfta, yöntemde, alanda vb. Bazı ek açıklamaların olup olmadığını yansıtarak kontrol eder ve açıklama varsa (veya yoksa) bir şeyler yapar. Ek olarak, ek açıklama üyeleri daha fazla bilgi aktarmak için kullanılabilir.


3

Bu bağlantıyı takip edin . Bu, sorununuz için yakın bir cevap sağlayacaktır. İçindeki ek açıklamalara odaklanırsak Java, Ek Açıklamalar Java 5'te sunulmuştur ve Bahar'a özgü değildir. Genel olarak, ek açıklamalar bir sınıfa, yönteme veya değişkene meta veriler eklemenize olanak tanır. Bir açıklama, derleyici (örneğin, @Override açıklaması) veya yay gibi bir çerçeve (örneğin, @Component açıklaması) tarafından yorumlanabilir.

Ayrıca daha fazla referans ekliyorum.

  1. http://www.codeproject.com/Articles/272736/Understanding-Annotations-in-Java
  2. http://docs.oracle.com/javase/7/docs/api/java/lang/annotation/package-summary.html
  3. http://www.coderanch.com/how-to/java/AnnotationsExample

@LuiggiMendoza java 1.7 ek açıklama belgesi eklendi
Ruchira Gayan Ranaweera

@Ruchira tüm bağlantıları açtım ama yine de nasıl çalıştığı konusunda net değilim. Beni bahar ek açıklamaları olarak düşünmek gibi ayrıntılarla açıklayabilir misiniz? Spring.xml dosyasında herhangi bir konfigürasyon yazmadan ek açıklama kullanarak her şeyi yapabilirim. ek açıklamayı dahili olarak xml yapılandırmasına bağlar mı?
Chirag Dasani

@ChiragDasani şuna bir göz atın. bu size static.springsource.org/spring/docs/3.0.0.M3/reference/html/… yardımcı olabilir ve ayrıca bu SO gönderisine bakın stackoverflow.com/questions/2798181/…
Ruchira Gayan Ranaweera

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.