이 코드에서 @Override가 있으면 문제가 없을까?
class Parent {
public void hello(String name) {
System.out.println("안녕하세요, 저는 " + name + "입니다.");
}
}
class Child extends Parent{
// @Override가 있고 없고 차이가 없을까?
public void hello() {
System.out.println("안녕!");
}
}
위 코드는 @Override 어노테이션을 사용하지 않으면 동작이 되고, 사용하면 예외가 발생한다. 예외가 발생한다는 것은 오버라이딩이 아니라는 의미이다.
오버라이딩의 조건은 다음과 같다.
- 부모 클래스의 메서드와 메서드 이름이 동일해야 한다.
- 매개변수의 타입, 개수, 순서가 일치해야 한다.
- 리턴 타입이 동일해야 한다.
- 접근 제한자는 부모 클래스의 메서드와 같거나 더 넓은 범위어야 한다.
- 부모 메서드의 예외와 같거나 예외의 개수를 줄일 수 있다.
조건에 맞춰 코드를 아래와 같이 고치면 된다.
class Parent {
public void hello(String name) {
System.out.println("안녕하세요, 저는 " + name + "입니다.");
}
}
class Child extends Parent{
@Override
public void hello(Stirng name) {
System.out.println("안녕! " + name );
}
}
오버라이딩을 구현할 때 꼭 @Override가 필요할까?
오버라이딩의 조건만 맞춘다면 @Override 어노테이션을 사용하지 않더라도 동작이 된다. 그래도 @Override 어노테이션을 일관되게 사용하라고 권장한다.
만약 @Override를 붙이지 않고 오버라이딩을 구현한다고 했을 때 조건에 벗어나는 실수를 하였으면 첫 번째 코드처럼 실행에는 문제없이 되지만 올바르게 오버라이딩을 하였는지는 확인이 되지 않는다. @Override를 붙이면 오버라이딩이 된 메서드라는 것이 명시가 되므로 실수를 해도 컴파일러가 바로 알려줄 것이다.
결론적으로, @Override를 일관되게 사용하는 것은 같이 코드를 같이 작성하는 팀원들이나 보는 사람들에게 명확성을 줄 수 있고 컴파일러의 검사를 이용한 개발자의 실수도 방지할 수 있다.
@Override에서 벗어나 어노테이션으로 생각의 범위를 넓혀보면
어노테이션 하면 자바 보단 스프링 같은 프레임워크를 생각하시는 분이 많이 있을 것이다. 실제로 프레임워크 범위로 넘어가면 어노테이션의 역할은 더 다양해진다.
어노테이션의 역할
코드의 특별한 의미를 표기하기 위한 주식의 역할뿐 아니라 많은 역할을 가지고 있다. 대표적인 3가지의 역할을 알아보자.
- 컴파일러에서 코드 작성 문법 에러를 체크
- 빌드도구에서의 사용 (코드 생성)
- 실행 시(런타임 시) 특정 기능을 실행
컴파일러에서 코드 작성 문법 체크는 위에서 알아본 @Override를 생각해 보면 된다. @Override 어노테이션을 선언 후 오버라이딩 조건에 벗어난 메서드 설계를 하면 컴파일러에서 에러 체크를 표기해 준다.
Java에선 Maven이나 Gradle이 대표적인 빌드 도구이다. 빌드 도구엔 라이브러리를 의존성 등록을 할 수 있다.
예를 들어 설명하자면 Lombok 라이브러리가 있다. 해당 라이브러리를 빌드 도구에 등록하면 '@Data', '@Getter', '@Setter' 등 어노테이션이 제공된다.
이 어노테이션들을 통해 재사용, 반복적으로 사용되는 코드(보일러플레이트 코드)를 줄여주는 역할을 한다.
즉, 이러한 어노테이션들은 컴파일 시간동안 빌드 도구에 의해 해석되어 적절한 코드를 생성해 주는 역할을 수행한다. 따라서 빌드도구와 어노테이션은 연관되어 동작하며, 개발자에서 효과적이고 효율적인 코드 환경을 제공해준다.
@Getter
@Setter
public class Person {
private Long id;
private String name;
// @Getter, @Setter의 사용으로 코드를 직접 작성할 필요가 없다.
}
마지막으로 런타임 시 어노테이션의 역할을 보면 런타임 시 특정 기능을 실행하도록 정보를 제공한다고 정의된다.
이러한 행위는 리플렉션(Reflecion)이라는 단어로 정의된다.
리플렉션(Reflecion)이란 간단히 말해 Runtime시에 클래스의 메타 정보를 얻는 기능을 말한다. 예를 들어 클래스가 가지고 있는 필드가 무엇인지, 어떤 메서드를 가졌는지 등 클래스에 대한 정보를 알아내는 것을 리플랙션이라고 한다.
예를 들어, 스프링 프레임워크를 사용하면 '@Autowired` 어노테이션은 런타임에 의존성을 주입하기 위해 사용된다. 런타임에 Spring 컨테이너는 이 어노테이션이 붙은 필드나 메서드를 찾아 적절한 오브젝트를 주입시킨다.
결론적으로 런타임에 메타데이트를 바탕으로 특정 동작을 수행하게 하는 데 사용될 수 있다.
Reference
https://honeyinfo7.tistory.com/56
'Language > Java' 카테고리의 다른 글
[스진초5기/Java] Overriding과 Overloading (0) | 2023.10.27 |
---|---|
[Java] String[]을 List , List를 String[]로 변환하는 방법 (0) | 2023.10.24 |
[Java] 인터프리터와 컴파일러 그리고 Java (1) | 2023.10.23 |
[스친초5기/Java] 인터페이스와 객체지향 (0) | 2023.10.20 |
[스진초5기/Java] 객체지향의 4가지 특징 (0) | 2023.10.19 |