Bu Sayfayı Paylaş:

Kavram

Annotation

Tanım: Java'da, sınıf, method, değişken vb.. hakkında geliştirme, derleme, çalıştırma ortamlarına ek bilgi verme amacıyla kullanılan bir meta-data özelliği. Örneğin bir method'un üzerine @Override annotation'u eklerseniz bu method'un üst bir method'u override ettiğini derleme ortamına belirtmiş olursunuz. @AnnotationName(elementadi = "deger",elementadi2=deger2) şeklinde kullanılır.

Veri

Annotation Yazım Kuralları

En basit bir annotation @ işareti ve adı ile belirtilir:
@AnnotationAdi
Bir annotation'un içinde birden fazla element olabilir:
@AnnotationName(elementadi = "deger",elementadi2=deger2)
Tek bir element var ise ad belirtilmeyebilir:
@AnnotationName("deger")
Aynı method, sınıf veya değişkene birden fazla annotation verilebilir:
@AnnotationName("deger"), @AnnotationName2(elementname1="deger")
public void get(){
}
Java 8 ile aynı isimle iki annotation kullanılabilir:
@AnnotationName("deger"), @AnnotationName("deger2")
public void get(){
}
İç içe annotation olabilir:
@ComplexAnnotation(@SimpleAnnotation(elementadi = "deger",elementadi2=deger2),@SimpleAnnotation2)

Veri

Built-in Annotations - Dil İle İlgili Temel Annotation'lar

Java ortamı aşağıdaki annotation'ları sağlamaktadır:
  • @Override : Bir method'un üst method'dan override edildiğini belirtir. Derleyici içindir
  • @Deprecated : Bir method'un deprecated (artık kullanılmaması gereken, yakında kaldırılma ihtimali olan) olduğunu belirtir
  • @SuppressWarnings : Derleyiciye uyarı (warning) vermemesi için kullanılır. Örneğin deprecated bir method'u kullanıyorsanız uyarı vermemesini sağlayabilirsiniz
  • @SafeVarargs : Varargs parametresi içeren bir method'a eklenmektedir. Varargs parametresi olarak generics bir parametre verilirse bunun güvenli olmayacağı (unsafe) uyarısı verilir. SafeVarargs uyarının verilmesini engeller
  • @FunctionalInterface : Java 8 ile gelmiştir ve bir interface'sib functional interface (tek method'u olan interface) olduğunu belirtir.

Örnek

Öntanımlı Annotation'ların Kullanıldığı Bir Örnek

Aşağıda @Deprecated ve @Override gibi öntanımlı annotation'ları (predefined annotation) kullanılan bir sınıf gözükmektedir:
package com.test.annotation;

public class PredefinedAnnotations {
	
	int x=1;
	
	public int getX(){
		return x;
	}
	
	public void setX(int x){
		this.x=x;
	}
	
	@Deprecated
	public void setXValue(int x){
		this.x=x;
	}
	
	@Override
	public String toString() {
		return "x:"+x;
	}
	
}
setXValue method'u @Deprecated ile deprecated edilmiştir. toString method'unda ise Object sınıfın toString method'unun override edileceği belirtilmiştir. Örneğin yanlış olarak
@Override
public String tostring() {
    return "x:"+x;
}
yazarsak, derleyici tostring adında override edilen bir method'un olmadığını söyler ve hata yapmanızı engeller: The method tostring() of type PredefinedAnnotations must override or implement a supertype method Yukarıdaki sınıfı aşağıdaki gibi kullanalım
package com.test.annotation;

public class OtherClass {

	@SuppressWarnings("deprecation")
	public OtherClass() {
		
		PredefinedAnnotations predefinedAnnotations=new PredefinedAnnotations();
		
		predefinedAnnotations.setXValue(15);
		
		System.out.println(predefinedAnnotations.getX());
		
	}
	
}
setXValue deprecated bir method olmasından dolayı derleyi uyarı verecektir. Bu uyarının verilmemesi için @SuppressWarnings("deprecation") eklenmiştir.

Veri

Annotation Kullanıldığı Konumlar

Bir annotation aşağıdaki konumlarda kullanılabilir :
  • Paket : @Test package com.test.x;
  • Sınıf, interface , enum : @Test class A {..}
  • Alan : @Test int x;
  • Yöntem : @Test void setX(){..}
  • Kurucu : @Test X() {..}
  • Parametre : xMethod (@Test a, @Test2 b) { .. }
  • Nesne Yaratma : new @Interned A();
  • Cast : x = (@NonNull String) y
  • Implement : class X implements @Readonly List<@Readonly T>
  • Exception : x() throws @Critical XException { .. }

Veri

Annotation Yaratımında Kullanılan Annotation'lar

Bir yazılımcının bir annotation yaratması için de annotation'lar kullanılır. Kullanılan annotation'lar aşağıdaki gibidir:
  • @Target : Yaratılan annotation'un nerelerde kullanılabileceğini belirtir. ANNOTATION_TYPE , CONSTRUCTOR (kurucu) , FIELD (alan), LOCAL_VARIABLE (local değişken) , METHOD (metod), PACKAGE (paket) , PARAMETER (parametre) , TYPE (class, enum veya interface) ve TYPE_PARAMETER (bir sınıfın herhangi bir elementine uygulanabilir) değerleri kullanılır
  • @Retention : Yaratılan annotation'un nerede işleneceğini belirtir. SOURCE (kaynak kodu ile ilgili, derleyici dikkate almaz), CLASS (derleyici ile ilgilidir, çalışma zamanında kullanılmaz), RUNTIME (çalışma sırasında JVM tarafından işlenir)
  • @Inherited : Bir Annotation'un alt sınıflara da otomatik işlemesi içindir. @Inherited kullanılmaz ise bir sınıfı etkileyen annotation o sınıftan türetilen sınıfı etkilemez
  • @Documented : Kullanıldığı yerde, Java Doc dökümanlarında bilgi verilebileceği anlamına gelir. @Documented verilmez ise kullanıldığı yerlerde Java Doc ile oluşturulan dökümanlarda bilgi bulunmaz
  • @Repeatable : Aynı element üzerinde (class, kurucu, interface, method vb..) birden fazla aynı annotation'un kullanılabileceğini belirtir. (Java 8 ile gelmiştir)

Örnek

İşlem Hakkında Bilginin Sistem Ekranına Basılması İçin Kullanılan Bir Annotation Örneği

Print adında bir annotation yaratıyoruz. Bu annotation eğer verilmez ise sistem çıktısına herhangi bir şey basılmamaktadır. Eğer simple verilirse basit bir çıktı, full verilirse daha açıklamalı bir bilgi basılacaktır. Bunun için aşağıdaki gibi bir annotation'ı yaratabiliriz:
package com.test.annotation;
import java.lang.annotation.*;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Print {
	// simple veya full olabilir
	String model() default "none";
	
}
@interface ifadesi bunun bir Annotation olduğunu belirtir. @Target(ElementType.METHOD) ile sadece method'lar için olduğunu belirtiyoruz. @Retention(RetentionPolicy.RUNTIME) ile de sadece derleme zamanında çalışacağını belirtir. String model() default "none" ile model değişkeni yaratıyoruz ve varsayılan değerini none yapıyoruz.
Aşağıdaki gibi bir interface olsun :
public interface Operation {
	
	public int operate(int p1, int p2);
}
Bu interface iki int alır ve bir int döner. Bir Operator sınıfımız olsun ve verilen bir Operation nesnesinin operate method'u çağırsın ve operasyonu gerçekleştirsin. Operation sınıfı operate method'un Print annotation'u olup olmadığını kontrol eder. Eğer var ise ona göre operate işlemini yaptıktan sonra print işlemini yapar. Operator sınıfı aşağıdaki gibidir :
package com.test.annotation;
import java.lang.reflect.Method;
public class Operator {
	
	private int p1;
	private int p2;
	
	public Operator(int p1,int p2) {
		this.p1=p1;
		this.p2=p2;
	}
	
	public int operate(Operation operation){
		
		// kütüphane ile ilgili ek bir şeyler yapar
		
		int result = operation.operate(p1, p2);
		
		try {
			Method method=operation.getClass().getMethod("operate", int.class, int.class);
			
			if(method.isAnnotationPresent(Print.class)){
				
				Print printAnnotation=method.getAnnotation(Print.class);
				
				if(printAnnotation.model().equals("simple")){
					
					System.out.println(p1+","+ p2 + " = "+ result);
					
				}else if(printAnnotation.model().equals("full")){
					
					System.out.println(p1 +" ve " + p2 +" operasyona girdi. Sonuç : "+result);
					
				}
			}
			
		} catch (Exception e) {}
			
		// kütüphane ile ilgili ek bir şeyler yapar
		
		return result;
		
	}
}
Operator operasyona sokacağı iki değeri en baştan alıyor. operate fonksiyonu, hangi operasyonu yapacağını parametre olarak alıyor. İlk önce int result = operation.operate(p1, p2) şeklinde operasyonu gerçekleştiriyor. Sonra Print annotation'unun kullanılıp kullanılmadığı kontrol ediliyor. Bunun için önce
Method method=operation.getClass().getMethod("operate", int.class, int.class);
ile operate method'u alınıyor. Ardından
if(method.isAnnotationPresent(Print.class))
kontrolü ile Print annotation'un kullanılıp kullanılmadığına bakıyor. Eğer kullanılıyor ise annotation'u alıyor :
Print printAnnotation=method.getAnnotation(Print.class);
Ardından model değerine göre print işlemini gerçekleştiriyor.
Şimdi bu sınıfları kullanan bir uygulama yapabiliriz. Aşağıdaki gibi toplama ve çarpma için iki operasyon sınıfı tanımlıyoruz. Toplama için :
package com.test.annotation;
public class SumOperation implements Operation {
	@Override
	@Print(model="simple")
	public int operate(int p1, int p2) {
		
		return p1+p2;
		
	}
}
Çarpma için ise :
package com.test.annotation;
public class MultiplyOperation implements Operation {
	@Override
	@Print(model="full")
	public int operate(int p1, int p2) {
		
		return p1*p2;
		
	}
}
Toplama işlemi @Print(model="simple") ile basit modeli seçmişken, çarpma işlemi için @Print(model="full") ise açıklamalı bilginin basılması istenmiştir. Bu iki sınıfı kullanarak uygulama aşağıdaki gibi test edilebilir:
package com.test.annotation;
public class MyOperationApp {
	
	public static void main(String[] args) {
		
		SumOperation sumOperation=new SumOperation();
		sumOperation.operate(10, 12);
		
		MultiplyOperation multiplyOperation=new MultiplyOperation();
		multiplyOperation.operate(10, 12);
		
		//operator üzerinden yapılırsa ekrana basılacak bilgiler
		Operator operator=new Operator(10, 12);
		
		operator.operate(sumOperation);
		operator.operate(multiplyOperation);
		
	}
}
İlk operasyon işlemlerinde ekrana hiç bir bilgi basılmayacaktır:
SumOperation sumOperation=new SumOperation();
sumOperation.operate(10, 12);
		
MultiplyOperation multiplyOperation=new MultiplyOperation();
multiplyOperation.operate(10, 12);

Ancak Operator sınıfını kullanarak operasyon yapılırsa istenildiği gibi çıktıda bilgiler görünecektir. Uygulama çalıştığında aşağıdaki gibi bir çıktı oluşur:
10,12 = 22
10 ve 12 operasyona girdi. Sonuç : 120
Görüldüğü gibi bir Print annotation'ı yarattık ve onun kullanılmasını sağladık.



Bu Sayfayı Paylaş:

İletişim Bilgileri

Takip Et

Her Hakkı Saklıdır. Bu sitede yayınlanan tüm bilgi ve fikirlerin kullanımından fibiler.com sorumlu değildir. Bu sitede üretilmiş , derlenmiş içerikleri, fibiler.com'u kaynak göstermek koşuluyla kendi sitenizde kullanılabilirsiniz. Ancak telif hakkı olan içeriklerin hakları sahiplerine aittir