
Java 소스 코드에서 HTML 형식의 API 문서를 생성하기 위해 사용되는 문서 생성기
다른 API를 하이퍼링크를 통해 접근할 수 있음
사용 목적
생성 방법
ex
package org.example.javadoc;
/**
* javadoc 테스트
*/
public class Test {
/**
* 테스트 메소드
* @param a 전달받은 매개변수
* @return 'a test'
*/
public String testMethod(int a) {
return a + " test";
}
}
javadoc -d docs Test.java
-d docs
docs/index.html


자바 소스코드에 추가하여
코드에 대한 정보를 제공하는메타 데이터
⭐ 백기선님 라이브 스터디
어노테이션은 주석이다.
런타임 시 필요한 중요한 정보는 안들어간다.
컴파일러 수준에서 사용하는 정적인 정보들이다. 그 정보들로 문서를 만들 수 있다.
따라서 어노테이션에는 변수 자체가 들어갈 수 없다. 정적인 데이터이기 때문에 (static final은 들어갈 수 있음)
어떻게 컴파일하고 처리할 것인지 알려줌package java.lang.annotation;
/**
* The common interface extended by all annotation types. Note that an
* interface that manually extends this one does <i>not</i> define
* an annotation type. Also note that this interface does not itself
* define an annotation type.
*
* More information about annotation types can be found in section 9.6 of
* <cite>The Java™ Language Specification</cite>.
*
* The {@link java.lang.reflect.AnnotatedElement} interface discusses
* compatibility concerns when evolving an annotation type from being
* non-repeatable to being repeatable.
*
* @author Josh Bloch
* @since 1.5
*/
public interface Annotation {
boolean equals(Object obj);
int hashCode();
String toString();
Class<? extends Annotation> annotationType();
}코드 문법 에러 체크를하도록 정보를 제공 (제약 사항 선언)
ex) @Override, @Deprecated, @NotNull
빌드 툴이 코드를 자동 생성할 수 있도록 정보를 제공
ex) Lombok - @Getter @Setter
런타임 시 특정 기능을 수행하도록 정보를 제공
ex) Spring - @RequestMapping, @Autowired
프로그램 관련 설정을 XML이나 properies라는 파일에 지정했음가독성이 매우 좋아짐롬복(lombok)이라는 툴을 이용하면 개발자가 필요한 작업을 어노테이션만으로 처리할 수 있기 때문에 코드를 줄이고 개발을 편하게 할 수 있게 해줌자바 코드에서 사용하기 위해 정해져 있는 어노테이션
오버라이딩 한 메소드 앞에 붙이는 어노테이션
메소드 시그니처 또는 리턴 타입이 다른 경우 컴파일 에러남 → 제대로 오버라이딩 되었는지 확인할 수 있음자바 버전이 올라가면서 더 이상 사용되지 않는 클래스, 메소드에 붙이는 어노테이션
경고와 함께 정상적으로 컴파일 됨 (에러x)하위 호환성을 위해 사용함컴파일러에게 경고가 발생하지 않도록 명시하기 위해 사용하는 어노테이션
Functional Interface임을 명시하는 어노테이션
- Functional Interface
- 구현해야 할 추상 메소드가 1개인 인터페이스
- 해당 어노테이션을 인터페이스에 붙이면 추상 메소드가 1개임을 보장해줌
- 아닐 시 컴파일 에러 발생
어노테이션을 위한 어노테이션
❗ 개발자가 직접 어노테이션을 정의하고 사용할 일은 많지 않으므로 보고 이해할 수 있을 정도로만 파악하자
어노테이션 대상을 지정
public enum ElementType {
/** Class, interface (including annotation type), or enum declaration */
TYPE,
/** Field declaration (includes enum constants) */
FIELD,
/** Method declaration */
METHOD,
/** Formal parameter declaration */
PARAMETER,
/** Constructor declaration */
CONSTRUCTOR,
/** Local variable declaration */
LOCAL_VARIABLE,
/** Annotation type declaration */
ANNOTATION_TYPE,
/** Package declaration */
PACKAGE,
/**
* Type parameter declaration
*
* @since 1.8
*/
TYPE_PARAMETER,
/**
* Use of a type
*
* @since 1.8
*/
TYPE_USE,
/**
* Module declaration.
*
* @since 9
*/
MODULE
}public class MyClass<@MyAnnotation T> {
// Class code...
}
public <@MyAnnotation T> void myMethod(T param) {
// Method code...
}package org.example.annotation;
@MyAnnotation
public class TestClass<@MyAnnotation T> {
@MyAnnotation("hi")
int a;
public<@MyAnnotation TT> @MyAnnotation String test(@MyAnnotation int a, T t, TT tt) {
return "hi";
}
}어노테이션의
유지 시간(유지 정책)지정
SOURCE
CLASS - default
JVM 로딩 시에는 어노테이션 정보가 누락됨 → 리플렉션을 사용할 수 없음RUNTIME
- 클래스 파일에 정보가 저장됨
- 실행 시 리플렉션을 통해 클래스 파일에 저장된 어노테이션 정보를 읽어서 처리함
- 이 때부터 리플렉션이 가능함
public enum RetentionPolicy {
/**
* Annotations are to be discarded by the compiler.
*/
SOURCE,
/**
* Annotations are to be recorded in the class file by the compiler
* but need not be retained by the VM at run time. This is the default
* behavior.
*/
CLASS,
/**
* Annotations are to be recorded in the class file by the compiler and
* retained by the VM at run time, so they may be read reflectively.
*
* @see java.lang.reflect.AnnotatedElement
*/
RUNTIME
}
⭐ SOURCE → CLASS → RUNTIME
어노테이션에 대한 정보가 JavaDoc 문서로 포함되도록 함
어노테이션이 자식 클래스에 상속되도록 함
네이티브 메소드가 참조하는 상수 필드에 붙임
public or default추상 메소드의 형태public 
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
String value() default "value";
String exp() default "exp";
}package org.example.annotation;
public class TestClass {
@MyAnnotation("hi")
int a;
}package org.example.annotation;
import java.lang.reflect.Field;
public class AnnotationMain {
public static void main(String[] args) throws NoSuchFieldException {
TestClass testClass = new TestClass();
Field a = testClass.getClass().getDeclaredField("a");
MyAnnotation annotation = a.getAnnotation(MyAnnotation.class);
System.out.println("annotation.value() = " + annotation.value());
System.out.println("annotation.exp() = " + annotation.exp());
}
}annotation.value() = hi
annotation.exp() = exp기본형, String, enum, class, 어노테이션만 허용매개변수 선언 불가예외 선언 불가타입 매개변수(제네릭)로 정의 불가@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
public int number();
public String text();
}public class UseMyAnnotation {
@MyAnnotation(number = 3, text = "hi")
void sampleMethod() {
}
public static void main(String[] args) throws NoSuchMethodException {
Method method = UseMyAnnotation.class.getDeclaredMethod("sampleMethod");
MyAnnotation annotation = method.getAnnotation(MyAnnotation.class);
int number = annotation.number();
String text = annotation.text();
System.out.println("입력받은 text를 number만큼 반복시키는 어노테이션");
for (int i = 0; i < number; i++) {
System.out.print(text);
}
}
}
public abstract @interface week12_annotation/basic/MyAnnotation
implements java/lang/annotation/Annotation {
// compiled from: MyAnnotation.java
@Ljava/lang/annotation/Target;(value={Ljava/lang/annotation/ElementType;.TYPE, Ljava/lang/annotation/ElementType;.METHOD})
@Ljava/lang/annotation/Retention;(value=Ljava/lang/annotation/RetentionPolicy;.RUNTIME)
// access flags 0x401
public abstract number()I
// access flags 0x401
public abstract text()Ljava/lang/String;
}public class UseMyAnnotation {
public UseMyAnnotation() {
}
@MyAnnotation(
number = 3,
text = "hi"
)
void sampleMethod() {
}
public static void main(String[] args) throws NoSuchMethodException {
Method method = UseMyAnnotation.class.getDeclaredMethod("sampleMethod");
MyAnnotation annotation = (MyAnnotation)method.getAnnotation(MyAnnotation.class);
int number = annotation.number();
String text = annotation.text();
System.out.println("입력받은 text를 number만큼 반복시키는 어노테이션");
for(int i = 0; i < number; ++i) {
System.out.print(text);
}
}
}@Retention(RetentionPolicy.*SOURCE*)
- 어노테이션 정보가 바이트코드에 남아있지 않음

컴파일 시어노테이션을 읽고처리하는 프로그램
사용자 지정 코드를 실행할 수 있음컴파일 중에만 작동하고 여러 개의 어노테이션 프로세서가 등록되어 사용됨AbstractProcessor 인터페이스를 구현해야 함package javax.annotation.processing;
public abstract class AbstractProcessor implements Processor {
...
public Set<String> getSupportedAnnotationTypes() {
...
}
...
/**
* {@inheritDoc}
*/
public abstract boolean process(Set<? extends TypeElement> annotations,
RoundEnvironment roundEnv);
...
}getSupportedAnnotationTypes()
process()
- 해당 어노테이션이 있는 경우 처리할 로직을 작성
- 클래스 (바이트코드) 생성 가능
- 소스 코드와 별개의 리소스 생성 가능
⇒ 필요한 경우 자세히 찾아보기
런타임 시 인터페이스 구현 클래스를 로드하고 인스턴스화 하여 주입해주는 유틸리티 클래스
java.lang.ServiceLoader
META-INF/services/인터페이스 풀네임에서 해당 구현체를 찾고 클래스 로드를 함javadoc
어노테이션 프로세서 만들기