2010-07-19 17 views
19

Faceci jest sposobem na przekazanie adnotacji jako bezpośredniego parametru (raczej przez wykonanie całego narzutu refleksji)? Na przykład w poniższym kodzie, mam numer adnotacji, która posiada wartość int, chcę przekazać jako parametr do metody addImpl, jak mogę to zrobić (inny niż przez odbicie)?Czy istnieje sposób przekazywania adnotacji Java jako parametru?

Code Snippet:

@Retention(RetentionPolicy.RUNTIME) 
@Target({ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD}) 
public @interface Number { 
    int value(); 
} 

public void add(int x2) { 
    addImpl(@Number(value = 10) lol, x2); 
} 

public void addImpl(Number a, int b) { 
    System.out.println(a.value() + b); 
} 

public static void main(String[] args) { 
    new TestClass().add(3); 
} 
+4

Dlaczego jest zdefiniowany jako liczba adnotacji zamiast regularnej klasie? Celem adnotacji jest statyczne dołączanie metatanych w czasie kompilacji. Jeśli to nie jest twój cel, z jakiego powodu jest on zdefiniowany jako adnotacja? – jthg

+0

Liczba jest tylko próbką, którą wymyśliłem, robię to, aby ułatwić protokół;) –

Odpowiedz

17

Tak, można przejść wokół adnotacji tak (tak jak gdyby były normalne interfejsy).

Jedyne, czego nie można zrobić, to utworzyć wystąpienia tego interfejsu w środowisku wykonawczym. Możesz tylko wstawiać istniejące adnotacje i przekazywać je.

import java.lang.annotation.*; 

public class Example { 

    @Retention(RetentionPolicy.RUNTIME) 
    @Target(ElementType.METHOD) 
    public static @interface Number { 
     int value(); 
    } 

    @Number(value = 42) 
    public int adder(final int b) throws SecurityException, NoSuchMethodException { 
     Number number = getClass().getMethod("adder", int.class).getAnnotation(Number.class); 
     return addImpl(number, b); 
    } 

    public int addImpl(final Number a, final int b) { 
     return a.value() + b; 
    } 

    public static void main(final String[] args) throws SecurityException, NoSuchMethodException { 
     System.out.println(new Example().adder(0)); 
    } 
} 
+1

Okaaay - czy są jakieś przypadki użycia w tym świecie? –

+1

@Andreas_D: na pewno, gdziekolwiek zareagujesz na jakąś adnotację, łatwo zrekompensujesz kod, aby wykonać swoją pracę na kilka sposobów (lub nawet na zajęcia), a możliwość przekazania adnotacji może być bardzo przydatna. –

+2

Innym przypadkiem użycia może być przetestowanie walidatora JSR 303. Posiada metodę initialize(), która przyjmuje adnotację. –

3

Zgodnie z moją najlepszą wiedzą, nie ma czegoś takiego jak „adnotacji dosłowny” jak chcesz go używać w implementacji add.

Myślę, że najbliżej tego byłoby zadeklarowanie metody przyjmowania parametru typu java.lang.annotation.Annotation - ale wtedy trzeba by uzyskać te wystąpienia za pomocą odbicia od obiektów klasy/metody.

8

Można zrobić to lubią:

public void add(int x2) { 
    addImpl(new Number() { 

     @Override 
     public int value() { 
      return 10; 
     } 

     @Override 
     public Class<? extends Annotation> annotationType() { 
      return Number.class; 
     } 
    }, x2); 
} 

Ponieważ ilość jest w zasadzie interfejs, trzeba utworzyć instancję anonimowej klasy, która implementuje ten interfejs, i przekazać, że do tej metody.

Chociaż dlaczego chcesz to zrobić, to mnie przerasta. Jeśli chcesz przekazać jakąś wartość, powinieneś naprawdę użyć klasy.

+0

Liczba jest tylko próbką: 3 –

+0

Należy zauważyć, że ta implementacja jest wystarczająco dobra dla tego konkretnego przypadku użycia, ale może nie wystarczyć dla innych zastosowań, takich jak kwalifikatory 'CDI', w których' równy' i 'hashcode' powinny być implementowane zgodnie z Dokumentacja "Adnotacji". –

1

Liczba to także dobry stary interfejs, można zaimplementować konkretną klasę.

Faceci, to jest przydatne. Podczas gdy moduł najczęściej zajmuje się adnotacjami, które są naprawiane w czasie kompilacji, czasami musimy podać inne informacje uzyskane w czasie wykonywania z innych źródeł (takich jak xml, wytryskuj!). Możemy przesadzić z architekturą, lub po prostu stworzyć środowisko uruchomieniowe obiekt typu annotaion.

+1

Implementowanie interfejsów do adnotacji we własnych klasach to przynajmniej zapach kodu. –

+0

zapach mistrzostwa jest dobry. – irreputable

1

Jeśli chcesz przesłać adnotację w teście, możesz zrobić z niej egzekucję. Na przykład testu JSR 303 walidator może wyglądać następująco:

public void test() { 
    final TextLengthValidator validator = new TextLengthValidator(); 
    validator.initialize(mock(TextLength.class)); 
    final boolean valid = validator.isValid("some text", mock(ConstraintValidatorContext.class)); 
    assertThat(valid, is(true)); 
} 
Powiązane problemy