공부/인프런 워밍업 클럽_BE

[인프런 워밍업 클럽_0기] BE 첫 번째 과제 (진도표 1일차)

데부한 2024. 2. 18. 16:33
반응형

배너를 클릭하면 해당 사이트로 이동

 

강의 출처

 

자바와 스프링 부트로 생애 최초 서버 만들기, 누구나 쉽게 개발부터 배포까지! [서버 개발 올인

Java와 Spring Boot, JPA, MySQL, AWS를 이용해 서버를 개발하고 배포합니다. 웹 애플리케이션을 개발하며 서버 개발에 필요한 배경지식과 이론, 다양한 기술들을 모두 학습할 뿐 아니라, 다양한 옵션들

www.inflearn.com

 

 

과제 내용

우리는 최초로 API를 만들어 보았습니다. GET API를 만들기 위해 사용했던 어노테이션에 익숙하지 않다면 자바 어노테이션에 대해서 몇 가지 블로그 글을 찾아보세요! 다음 질문을 생각하며 공부해보면 좋습니다! 😊

[질문]

  • 어노테이션을 사용하는 이유 (효과) 는 무엇일까?
  • 나만의 어노테이션은 어떻게 만들 수 있을까?

 

답변

어노테이션의 역할

  • 컴파일러에게 문법 에러를 체크하도록 정보 제공
  • 프로그램을 빌드할 때 코드를 자동으로 생성할 수 있도록 정보 제공
  • 런타임에 특정 기능을 실행하도록 정보 제공

 

반응형

 

(예시가 100% 맞는지 장담은 할 수 없음!)

컴파일러에게 문법 에러를 체크하도록 정보 제공

@Override

@Override 어노테이션은 상속 받은 메서드를 재정의할 때 사용하는 어노테이션이다. 이 어노테이션을 사용하면 부모 객체에 없는 메서드를 재정의했을 때 컴파일러 과정에서 에러를 발생시켜줍니다. (컴파일 에러는 가장 좋은 에러!)

Parent.class

public class Parent {
    public void test1() {
        System.out.println("Parent.test1");
    }

    public void test2() {
        System.out.println("Parent.test2");
    }

    public void test3() {
        System.out.println("Parent.test3");
    }
}

 

Child.class

public class Child extends Parent{
    public void test1() {
        System.out.println("Child.test1");
    }

    public void test4() {
        System.out.println("Child.test4");
    }
}

 

목적은 Child가 Parent 클래스의 test1, test3 메서드를 재정의 하도록 하는 것이었는데 오타로 test3()을 test4()로 적고 실행해보면 당연히 아무런 에러가 발생하지 않고 프로그램이 정상적으로 종료된다.

public class OverrideMain {
    public static void main(String[] args) {
        Child child = new Child();
        child.test1();
        child.test4();
    }
}

실행 결과

 

반응형

 

이런 경우를 방지하기 위해 재정의를 위한 메서드에 @Override 어노테이션을 붙여주면 된다.

public class Child extends Parent{
    @Override
    public void test1() {
        System.out.println("Child.test1");
    }

    @Override
    public void test4() {
        System.out.println("Child.test4");
    }
}

 

@Override 어노테이션을 추가 후 서버를 실행해보면 에러가 발생한다.

 

IDE에서도 직관적으로 바로 알려준다.

 

 

나만의 어노테이션은 어떻게 만들 수 있을까?

Java Class를 생성할 때 Annotation을 선택한다.

 

기본 형식

public @interface MyAnnotation {
}

 

MyAnnotation 코드 추가

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
    String value() default "MyAnnotation : default value";
}
  •  @Target : 생성할 어노테이션이 적용될 수 있는 위치 나열
    • ElementType.TYPE : 클래스, 인터페이스, 열거 타입
    • ElementType.ANNOTATION_TYPE : 어노테이션
    • ElementType.FILED : 필드
    • ElementType.CONSTRUCTOR : 생성자
    • ElementType.METHOD : 메서드
    • ElementType.LOCAL_VARIABLE : 로컬 변수
    • ElementType.PACKAGE : 패키지

 

반응형

 

// Target 클래스 파일
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
    /**
     * Returns an array of the kinds of elements an annotation interface
     * can be applied to.
     * @return an array of the kinds of elements an annotation interface
     * can be applied to
     */
    ElementType[] value();
}

// ElementType[] enum 클래스 파일
public enum ElementType {
    /** Class, interface (including annotation interface), enum, or record
     * declaration */
    TYPE,

    /** Field declaration (includes enum constants) */
    FIELD,

    /** Method declaration */
    METHOD,

    /** Formal parameter declaration */
    PARAMETER,

    /** Constructor declaration */
    CONSTRUCTOR,

    /** Local variable declaration */
    LOCAL_VARIABLE,

    /** Annotation interface declaration (Formerly known as an annotation type.) */
    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,

    /**
     * Record component
     *
     * @jls 8.10.3 Record Members
     * @jls 9.7.4 Where Annotations May Appear
     *
     * @since 16
     */
    RECORD_COMPONENT;
}

 

  • @Retention : 어노테이션이 언제까지 살아 남아있을지를 정함
    • RetentionPolicy.SOURCE : 소스 코드(.java)까지 남아 있음
    • RetentionPolicy.CALSS : 클래스 파일(.class)까지 남아 있음 (= 바이트 코드)
    • RetentionPolicy.RUNTIME : 런타임까지 남아 있음 (= 사실상 안죽음)
// Retention 클래스 파일
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
    /**
     * Returns the retention policy.
     * @return the retention policy
     */
    RetentionPolicy value();
}


// RetentionPolicy enum 클래스 파일
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
}

 

반응형

 

어노테이션 값 꺼내기

MyAnnotationTest.class

public class MyAnnotationTest {

    @MyAnnotation
    public void testMethod1() {
        System.out.println("MyAnnotationTest.testMethod1");
    }

    @MyAnnotation(value = "My new Annotation")
    public void testMethod2() {
        System.out.println("MyAnnotationTest.testMethod2");
    }
}

 

MyAnnotationMain.class

public class MyAnnotationMain {
    public static void main(String[] args) throws NoSuchMethodException {
        // testMethod1 어노테이션 값 가져오기
        Method testMethod1 = MyAnnotationTest.class.getMethod("testMethod1");
        Annotation[] annotations = testMethod1.getDeclaredAnnotations(); // 메서드에 선언된 어노테이션 객체 얻어옴

        for (Annotation annotation : annotations) {
            if(annotation instanceof MyAnnotation) {
                MyAnnotation myAnnotation = (MyAnnotation) annotation;
                System.out.println("value : " + myAnnotation.value());
            }
        }

        // testMethod2 어노테이션 값 가져오기
        Method testMethod2 = MyAnnotationTest.class.getMethod("testMethod2");
        annotations = testMethod2.getDeclaredAnnotations(); // 메서드에 선언된 어노테이션 객체 얻어옴

        for (Annotation annotation : annotations) {
            if(annotation instanceof MyAnnotation) {
                MyAnnotation myAnnotation = (MyAnnotation) annotation;
                System.out.println("value : " + myAnnotation.value());
            }
        }
    }
}

 


Reference

반응형