20 Aralık 2020

Annotations ( Anotasyonlar)-2 Specific Annotation

ile gökhan

Önceki yazıda kendimize ait bir anotasyonu nasıl oluşturabileceğimizden bahsetmiştik. Sırada Java’nın kendine ait olan anotasyonları var. Sırasıyla bunları ele alacağız.

@Target Anotasyonu

Kendi anotasyonumuzu oluşturğumuzda bu anotasyonun sadece belirli türlere( sınıf, metot vb.) etki etmesini sağlayacak şekilde sınırlandırabiliriz. Bu sınırlandırmayı @ Target anotasyonu kullanarak sağlayabiliriz. Kullanımı aşağıdaki gibidir:

@Target({ElementType.METHOD, ElementType.CONSTRUCTOR})
public @interface Test7 {
    }

Yukarıdaki anotasyon örneğinde, bu anotasyonu sadece metod ve constroctor’da kullanılabileceğini ifade ettik. Şimdi bu anotasyonu uygulayalım:

@Test7  //DERLENMEZ... anotasyon sadece metot ve constructor için
public class Alfa {}
class Gama{
    String deneme(){
        return (@Test7 String) "Merhaba"; //DERLENMEZ... anotasyon sadece metot ve constructor için
    }
    @Test7 Gama(@Gama String aciklama){ //DERLENMEZ... ilk anotasyon derlenir ancak ikincisine izin verilmez...
        super();
    }
    @Test7 int sayi1; //DERLENMEZ.. anotasyon sadece metot ve constructor için
}

Aşağıda anotasyonlarda kullanılan bazı ElementType tiplerinin listesi verilmiştir.

ELEMENT TYPE VALUEAÇIKLAMA
TYPEClass, interface,enum,annotation
FIELDInstance ve static değişkenler, enum değerler
METHODMetot deklerasyonu
PARAMETERConstructor, method ve lambda parametreleri
CONSTRUCTORConstructor deklerasyonu
LOCAL_VARIABLELocal değişkenler
ANNOTATION_TYPEAnotasyonlar
PACKAGEPackage deklerasyonu

@Retention Anotasyonu

Anotasyonlar; derleyici tarafından ve ya çalışma zamanında iptal edilmek istenebilir. Bunun için @Retention anotasyonunu kullanıyoruz. Bunlar aşağıdaki tabloda özetlenmiştir.

RetentionPolicyAçıklama
SOURCEYalnızca kaynak dosyada tutulur, derleyici tarafından atılır.
CLASS.class dosyasında tutulur, çalışma zamanında tutulmaz.
RUNTIME.class dosyasında tutulur, çalışma zamanında kullanılır.

@Inherited Anotasyonu

Bu anotasyon bir sınıfa uygulandığında alt sınıf, üst sınıfta bulunan anotasyon bilgilerini alır. Aşağıdaki örnekte Standart isimli anotaston @Inherited anotasyonu ile işaretlenmiştir. Standart isimli anotasyon Memeliler sınıfına eklenmiştir. Kedi sınıfı Memeliler sınıfından miras aldığında Memeliler sınıfı @Inherited olarak işaretlendiği için Kedi sınıfı içinde geçerli olacaktır.

@Inherited public @interface Standart {}

@Standart public class Memeliler {}

public class Kedi extends Memeliler{}

@Repeatable Anotasyonu

Bir anotasyon bir sınıfta metotta ya da değişkende sadece bir kez kullanılabilir. Buna çözüm olarak @Repeatable anotasyonu ortaya çıkmıştır. Uygulanması biraz karışıktır. Örnekler üzerinden gidelim: Bir hayvanat bahçesinde bulunan GoldenRetriever cinsi kopeklerin özelliklerine dair bir anotasyon oluşturalım. Kopeğin birden fazla özelliği olacağı için, bu anotasyonu ilgili sınıfa birden fazla uygulamamız gerekecek. Bunun için yazacağımız anotasyonda bir array tipinde metadatanın eklenmesi gerekmekte. Bunu nasıl yapacağız bakalım:

public @interface KopekTuru {
    String ozellik();
    int sayi() default 10;
}

Yukarıda anotasyonumuzu oluşturduk. Ama bunu bir sınıfa ya da metoda birden fazla eklememiz bir array tipinde KopekTuru adında bir metadataya ihtiyacımız var:

public @interface Kopek {
    KopekTuru[] value();
}

Burada birden fazla ilgili sınıfımıza anotasyon tanımlayabilmemiz için başka bir anotasyon oluşturuldu. İçersinde array tipinde bir metadata bulunuyor. Şimdi yapmamız gereken bu array metadataya sahip anotasyonumuzu KopekTuru isimli anotasyona tanıtalım:

@Repeatable(Kopek.class)
public @interface KopekTuru {
    String ozellik();
    int sayi() default 10;
}

Burada KopekTuru isimli anotasyonumuza tekrarlı kullanabilmek için @Repetable ile işaretleyerek, Kopek anotasyonumuzu gösterdik. Şimdi tekrarlı anotasyonumuz oluşturulmuş oldu. Aşağıdaki gibi bir sınıfa uygulanmasını inceleyelim:

public class HayvanatBahcesi {
    public static class GoldenRetriever{}
    @KopekTuru(ozellik = "evcil")
    @KopekTuru(ozellik ="Sevimli")
    @KopekTuru(ozellik = "dost")
    private GoldenRetriever goldenRetriever;
}

Görüldüğü üzere KopekTuru isimli anotasyonumuzu birden fazla kullanabildik.

@Override Anotasyonu

Bir yöntemin ister bir interface’den ister bir üst sınıftan miras alınmış olsun, miras alınan yöntemin geçersiz kılınmasını sağlar. Geçersiz kılma işleminde önemli olan, metodun gerçersiz kılınacak metodla aynı imzaya, aynı ve ya daha kapsamlı bir erişim sağlayıcıya sahip olması gerekmektedir. Şimdi anotasyonu inceleyelim. Surungenler isminde bir interface oluşturalım; sayi isminde bir metodu olsun:

public interface Surungenler {
    int sayi();
}

Bu interface’i Yilan sınıfına implement edelim:

public class Yilan implements Surungenler{
    @Override
    public int sayi() {
        return Integer.MAX_VALUE;
    }
    void selamla(){
        System.out.println("Yilannnn");
    } 
}

Yukarıda görülüğü gibi Surungenler interface’i implement edildiğinde, sayi metodu daha işlevsel olması için override anotasyonu ile geçersiz kılındı.

@Deprecated Anotasyonu

Java’da kütüphaneler yıllarca geliştirilir. Bu geliştirmeler sonucunda bazı methodlar o kadar çok değişir ki, tamamen farklı bir imzayla onun yeni bir versiyonunu oluşturmamız gerekir. Yine de metodun aniden ortadan kalkması kullanıcılara bir çok derleme sorununa neden olabileceğinden, metodun eski versiyonunu ortadan hemen kaldırmak istemeyiz. @Deprecated anotasyonu kullanıcılara, mevcut metodun yeni bit versiyonunun mevcut olduğunu bildirmenin bir yoludur. Basit kullanımı aşağıdaki gibidir:

@Deprecated
public class EskiVersiyon {}

@Deprecated anotasyonu iki kullanılırken isteğe bağlı olarak iki değer alabilir. Bunlar string tipteki “since” ve boolean tipteki “forRemoval” dır. since metodunun ne sürümden itibaren deprecated olacağını bildirirken, forRemoval metodun yeni versiyonlarla kaldırılıp kaldırılmayacağını ifade eder.

@Deprecated(since="1.8", forRemoval=true)
public class EskiVersiyon {}

@SuppressWarnings Anotasyonu

Java’da yazdığımız bazı kodlara derleyici uyarı verir. Biz yazdığımız kodlara derleyicinin müdahalesi olmasını istemiyorsak, @SuppressWarnings anotasyonu kullanılır. SupressWarnings anotasyonu iki değer alabilir:

DEĞERAÇIKLAMA
“deprecation”@Deprecated anotasyonu ile işaretlenmiş türleri ve ya metotları göz ardı et.
“unchecked”Örneğin: List<String>() yerine List kullanıldığında derleyicinin uyarmaması için kullanılır.

@SafeVarargs Anotasyonu

Bir yöntemin varargs parametresinde herhangi bir potansiyel güvenli olmayan işlem gerçekleştirmediğini derleyiciye belirtmek için kullanılır. Yalnızca geçersiz kılınamayan constructorlara veya yöntemlere uygulanabilir. (static ve ya final olarak işaretlenmiş yöntemler). Bir yöntemin en fazla bir varargs paramatresi ve bu parametrenin en sonda olması gerekmektedir.@SafeVarargs anotasyonu yöntemin güvenli olmayan herhangi bir işlem gerçekleştirmediğini belirtmek için kullanılır.

 @SafeVarargs   //DERLENMEZ... ÇÜNKÜ Varargs yok....
 public static void k1(int x){}
@SafeVarargs  //DERLENMEZ... ÇÜNKÜ static, final veya private ile işaretlenmemiş
protected void k2(String... x){}