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


91

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

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가이를 수행하고 해킹으로 간주되지는 않지만 적어도 단일 요소에 동일한 유형의 여러 주석을 허용하는 것이 여전히 타당하다고 생각합니다.


1
Java 7에서 프로그램을 허용하기 위해이 중복 규칙을 완화하려는 노력이 있습니다. 사용 사례를 설명해 주시겠습니까?
notnoop 2009-10-12

이 작업을 수행하려는 이유에 대한 설명으로 내 질문을 편집했습니다. 감사.
Max A.

여러 한정자에 대해 빈을 제공 할 수 있도록하는 것이 CDI에서 편리 할 수 ​​있습니다. 예를 들어, "@Produces @PackageName ("test1 ") @PackageName ("test2 ")"
Richard Corfield

추가 : CDI는 복합을 하나의 Qualifier로 간주하기 때문에 아래 답변은 그 문제를 해결하지 못합니다.
리차드 코 필드

@MaxA. "그린 체크"수락을 mernst 의 올바른 답변 으로 변경하십시오. Java 8은 주석을 반복하는 기능을 추가했습니다.
Basil Bourque

답변:


140

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

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

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

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

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


2
Groovy에서도이 작업을 수행 할 수 있습니까?
Excel20

5
@ Excel20 예. 그래도 대괄호를 사용해야 @Foos([@Foo(bar="one"), @Foo(bar="two")])합니다. 참조 groovy.codehaus.org/Annotations+with+Groovy
sfussenegger

하루에 조금 늦었지만 Foos 내에서 Foo 목록을 처리 할 수있는 조언을 알려 주시겠습니까? 지금은 방법의 결과를 처리하려고하지만 Foos가 가로 채더라도 Foo의 조언은 입력되지 않습니다
Stelios Koussouris 2013 년

업데이트 : Java 8에서이 답변은 구식입니다. mernst 의 올바른 현대 답변 을 참조하십시오 . Java 8은 주석을 반복하는 기능을 추가했습니다.
Basil Bourque


21

언급 된 다른 방법 외에도 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)])


FooContainer의 메서드 / 필드 이름은 "value ()"라는 엄격한 이름이어야한다는 점을 지적 할 가치가 있습니다. 그렇지 않으면 Foo가 컴파일되지 않습니다.
토마스 Mularczyk

... 또한 포함하는 주석 유형 (FooContainer)은 반복 가능한 주석 유형 (Foo)보다 많은 유형에 적용 할 수 없습니다.
토마스 Mularczyk


12

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

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

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


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

예:

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

나는 이것이 어리석게 친숙하다는 것을 알고 있었다. 기억을 되살려 주셔서 감사합니다.
Max A.

이제 Java 8에서 가능합니다.
Anis

4

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

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

//...

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

3

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

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

좀 더 짧고 깔끔한 이모 ..


올바른 요점이지만 OP의 질문에 어떻게 대답하려고 시도합니까?
Mordechai

@MouseEvent 당신이 맞습니다, 나는 그것이 sfussenegger의 상위 답변의 개선이라고 생각하므로 거기에 더 많은 의견에 속합니다. 그러나 반복 가능한 주석으로 인해 답변은 구식입니다 ...
golwig

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.