[java] 한 요소에 동일한 유형의 여러 주석이 있습니까?

단일 요소 (이 경우 메서드)에 동일한 유형의 두 개 이상의 주석을 슬랩하려고합니다. 작업중인 대략적인 코드는 다음과 같습니다.

public class Dupe {
    public @interface Foo {
      String bar();
    }

    @Foo(bar="one")
    @Foo(bar="two")
    public void haha() {}
}

위를 컴파일 할 때 javac는 중복 주석에 대해 불평합니다.

max @ upsight : ~ / work / daybreak $ javac Dupe.java
Dupe.java:5 : 중복 주석

이와 같은 주석을 반복 할 수 없습니까? 간절히 말하면 위의 @Foo 두 인스턴스는 내용이 다르기 때문에 다르지 않습니까?

위의 방법이 가능하지 않은 경우 잠재적 인 해결 방법은 무엇입니까?

업데이트 : 내 사용 사례를 설명하라는 요청을 받았습니다. 여기 있습니다.

저는 POJO를 MongoDB와 같은 문서 저장소에 “매핑”하는 구문 설탕 메커니즘을 구축하고 있습니다. getter 또는 setter에 대한 주석으로 인덱스를 지정하도록 허용하고 싶습니다. 다음은 인위적인 예입니다.

public class Employee {
    private List<Project> projects;

    @Index(expr = "project.client_id")
    @Index(expr = "project.start_date")
    public List<Project> getProjects() { return projects; }
}

당연히 Project의 다양한 속성별로 Employee의 인스턴스를 빠르게 찾을 수 있기를 바랍니다. 다른 expr () 값으로 @Index를 두 번 지정하거나 허용 된 답변에 지정된 접근 방식을 사용할 수 있습니다. Hibernate가이를 수행하고 해킹으로 간주되지는 않지만 적어도 단일 요소에 동일한 유형의 여러 주석을 허용하는 것이 여전히 타당하다고 생각합니다.



답변

동일한 유형의 두 개 이상의 주석은 허용되지 않습니다. 그러나 다음과 같이 할 수 있습니다.

public @interface Foos {
    Foo[] value();
}

@Foos({@Foo(bar="one"), @Foo(bar="two")})
public void haha() {}

하지만 코드에서 Foos 주석을 전용으로 처리해야합니다.

btw, 나는 2 시간 전에 동일한 문제를 해결하기 위해 이것을 사용했습니다. 🙂


답변

자바 8에서 반복되는 주석

에서 자바 8 (2014 년 3 월 출시), / 중복 주석을 반복 작성할 수 있습니다.

튜토리얼, 반복 주석을 참조하십시오 .

사양, JEP 120 : 반복 주석을 참조하십시오 .


답변

언급 된 다른 방법 외에도 Java8에는 덜 장황한 방법이 하나 더 있습니다.

@Target(ElementType.TYPE)
@Repeatable(FooContainer.class)
@Retention(RetentionPolicy.RUNTIME)
@interface Foo {
    String value();

}

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface FooContainer {
        Foo[] value();
        }

@Foo("1") @Foo("2") @Foo("3")
class Example{

}

기본적으로 예 FooContainer는 주석 으로 가져 옵니다.

    Arrays.stream(Example.class.getDeclaredAnnotations()).forEach(System.out::println);
    System.out.println(Example.class.getAnnotation(FooContainer.class));

위의 두 인쇄 :

@ com.FooContainer (value = [@ com.Foo (value = 1), @ com.Foo (value = 2), @ com.Foo (value = 3)])

@ com.FooContainer (value = [@ com.Foo (value = 1), @ com.Foo (value = 2), @ com.Foo (value = 3)])


답변

http://docs.oracle.com/javase/tutorial/java/annotations/repeating.html

Java8부터 반복 가능한 주석을 설명 할 수 있습니다.

@Repeatable(FooValues.class)
public @interface Foo {
    String bar();
}

public @interface FooValues {
    Foo[] value();
}

참고 value값 목록 필드가 필요합니다.

이제 배열을 채우는 대신 주석을 반복하여 사용할 수 있습니다.

@Foo(bar="one")
@Foo(bar="two")
public void haha() {}


답변

sfussenegger가 말했듯이 이것은 불가능합니다.

일반적인 해결책은 이전 주석의 배열을 처리하는 “다중”주석 을 작성하는 것입니다. 일반적으로 이름은 ‘s’접미사로 동일합니다.

그건 그렇고, 이것은 대규모 공공 프로젝트 (예 : Hibernate)에서 매우 사용되므로 해킹으로 간주해서는 안되며 오히려 이러한 요구에 대한 올바른 솔루션으로 간주되어야합니다.


필요에 따라 이전 주석에서 여러 값을 처리하도록 허용하는 것이 더 나을 수 있습니다 .

예:

    public @interface Foo {
      String[] bars();
    }


답변

다른 답변을 가장 간단한 형식으로 결합 … 간단한 값 목록이있는 주석 …

@Foos({"one","two"})
private String awk;

//...

public @interface Foos{
    String[] value();
}


답변

매개 변수 “bar”가 하나만있는 경우 “값”으로 이름을 지정할 수 있습니다. 이 경우 다음과 같이 사용할 때 매개 변수 이름을 전혀 쓸 필요가 없습니다.

@Foos({@Foo("one"), @Foo("two")})
public void haha() {}

좀 더 짧고 깔끔한 이모 ..