enum 클래스명 {
상수, 상수, 상수...
}
==참고)
상수 : 유일하게 1개 존재
-> 항상 주소가 동일하다
-> 객체 생성과 상관없이 접근 가능하다
-> 단, enum 클래스에 정의한 멤버변수는 이미 객체이며 정적 상수 형태이다
-> enum 클래스에 정의한 멤버변수 : 객체⭕ + final + static
예시) enum 클래스

ㄴ enum클래스 정의

ㄴ 상수다 보니 객체 생성 상관 없이 클래스명으로 바로 접근 가능
예시) 상수니까 1개만 존재 = 주소가 항상 동일하다

ㄴ enum클래스 정의

ㄴ 상수니까 1개만 존재 = 주소가 항상 동일하다
예시) switch~case구문

ㄴ 자료형이 뭔지 예상 할 수 있기 때문에 switch~case구문에서는 enum상수의 자료형 명시 안해도ㅇㅋ
예시) 1), 2) 적용 예시
public enum Transportation {
BUS, //Transportation의 객체, 정적 상수 형태
SUBWAY,
TAXI
}
↓ 내부적으로 이렇게 되어있다
abstract class Transportation extends java.lang.Enum {
public static final BUS = new Transportation();
public static final SUBWAY = new Transportation();
public static final TAXI = new Transportation();
private Transportation(){};
}
private final int fare;
예시)

ㄴ 내부적으로 생성자 함수가 enum상수를 객체로 만들어 주고 있넹
ㄴ Transportation클래스(enum클래스)도 클래스니까 기본생성자함수가 내부적으로 정의되어 있을 것이다

ㄴ 잉? 왜 Transportation클래스(enum클래스)에 기본생성자 함수호출이 안될까 = 왜 Transportation클래스(enum클래스)를 객체로 만들 수 없지?
-> Transportation클래스(enum클래스)를 객체로 만들게 되면 상수로서 가치가 없어짐
-> 상수는 유일해야함, 1개만 존재
-> 근데 직접 객체 생성하게되면 생성자 오버로드에 의해서 객체가 여러개 생성될 수 있잖슴
-> 상수로서의 의미가 상실됨 (유일하지 않음)
-> 그래서 enum클래스의 생성자함수의 접근제어자를 private으로 정의해 외부에서 enum클래스 객체를 생성하는 걸 통제함

ㄴ enum클래스의 기본생성자의 접근제어자는 private
예시2)

ㄴ enum클래스에 접근제어자 명시안하고 기본생성자 함수 정의함
ㄴ 원래는 접근제어자 명시 안하면 default가 접근제어자 이지만 enum클래스는 무조건 생성자함수의 접근제어자는 private이다

ㄴ 증거 : 외부에서 객체 생성 시 에러 뜸
ㄴ 에러뜨는 이유 : 생성자함수의 접근제어자가 private
예시3) enum클래스에 정의된 멤버변수에 매개변수 넣기

ㄴ 에러 뜸 왜?
ㄴ BUS(...) : 생성자를 호출한거랑 같음
public enum Transportation {
BUS(1400), // 생성자를 가리킴 -> Transportation() {}
SUBWAY(4500), // 생성자를 가리킴 -> Transportation() {}
TAXI(1300); // 생성자를 가리킴 -> Transportation() {}
Transportation() {
}
ㄴ 매개변수가 있는 생성자를 호출했는데 기본생성자에 매개변수가 없으니까 에러가 뜬 것

ㄴ 요거 참고하면 왜 BUS(...) 가 생성자를 호출한거 인지 이해 됨ㅇㅇ
ㄴ 자 그럼 에러 가 뜬 원인이 기본생성자에 매개변수가 없어서니까 매개변수 넣어주러 가보장

ㄴ enum클래스에 인스턴스변수 정의해도 되지만 final로 정의하는게(상수로 정의하는게) 관례
ㄴ final 변수 = 상수 : 상수는 값을 꼭 초기화 해붜야함
ㄴ 지금 초기화 안해서 에러 뜬거

ㄴ private final int fare; 초기화 해 줌

ㄴ get() 함수 정의

ㄴ BUS가 객체니까 getFare()함수에 접근 가능 하군
ㄴ 객체의 자원 = 변수 와 함수 -> 객체가 되면 객체의 자원인 변수와 함수 이용가능

ㄴ 값 조회해보자

ㄴ 값이 잘 나왔넹

예시)

ㄴ {} = 구현내용을 안넣어서 에러 뜬거
BUS(1350) {
public int getTotal(int person) {
return getFare() * person;
}
}
ㄴ 이런식으로 구현 내용 넣어주면 에러해결 될 거임
-> 근데 이렇게는 비효율적이어서 잘 안쓴다고 함
-> enum클래스가 추상클래스라는걸 보여주기 위해 하드코딩한거
예시)

ㄴ 미구현된메서드라 에러 뜸

ㄴ {} = 구현내용 넣어주면 해결 완

참고) 자바문서_Enum
https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Enum.html
Enum 상수이름을 문자열로 변환
String toString()과 동일
예시) name()

ㄴ enum클래스 정의

ㄴ Enum 상수이름을 문자열로 변환
예시)

ㄴ enum클래스 정의

ㄴ enum상수 TAXI의 위치번호 출력
예시)

static valueOf(클래스클래스, String name) 과 다르게 클래스클래스 매개변수로 안 넣어도 ㅇㅋstatic valueOf(클래스클래스, String name) = valueOf(String str)static valueOf(클래스클래스, String name) < valueOf(String str) 예시)

ㄴstatic valueOf(클래스클래스, String name) = valueOf(String str)
ㄴ 코드짜는 방식이 다를 뿐 같은 기능을 함
예시)

;으로 마무리해주고 기본생성자 정의 가능
참고) 자바문서_Annotation
https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/annotation/Annotation.html
참고) java.lang.class
ㄴ 그래서 자바문서 java.lang.class에 에노테이션 확인 가능 메서드 있음
ㄴ 매개변수 클래스클래스 ->getAnnotaion(클래스명.class)
@interface 애노테이션 명 {
}
↓ 내부적으로 이렇게 바껴 있다
interface 애노테이션명 extends java.lang.annotation.Annotation {
}


예시)

↓ @Override 컨트롤 + 마우스 왼쪽키


정보 전달 시점
RetensionPolicy
SOURCE
: 애노테이션이 java파일 상에 유지, 컴파일 완료 후(class 파일)에는 제거
- 컴파일러가 필요한 정보를 제공
- 컴파일러가 필요한 정보
CLASS : 기본값
: 에노테이션이 java파일 상에 유지, 컴파일 완료 후 유지
- 정보 전달x
- 기본값임에도 사용x
RUNTIME
: 애노테이션이 java파일 상에 유지, 컴파일 완료 후(class 파일) 유지
- 정보전달이 실행 중에 제공
예시)

ㄴ A클래스에 메서드 정의함

ㄴ B클래스가 A클래스에 상속받음
ㄴ B클래스가 A클래스에 정의된 메서드 오버라이드(메서드재정의)함
↓ @Override 컨트롤 + 마우스 왼쪽키

↓ RetensionPolicy 컨트롤 + 마우스 왼쪽키

예시)

ㄴ A클래스에 메서드 정의함

ㄴ B클래스가 A클래스에 상속받음
ㄴ B클래스가 A클래스에 정의된 메서드 오버라이드(메서드재정의)함
↓ @Override 컨트롤 + 마우스 왼쪽키

public @interface Override {
}
ㄴ 인터페이스 안쪽에 정의된 내용이 하나도 없음
ㄴ ② 추상 메서드 정의에 있는 예시 연결해서 보기
에노테이션도 추상메서드를 정의할 수 있다
에노테이션에서 추가 정보 전달 방식 = 추상 메서드 정의
추가 정보= 설정항목
추상 메서드 정의 = 설정항목들을 주로 정의
에노테이션 조회
설정항목이 추가되면 무조건 설정을 추가해 줘야 함(값을 넣어줘야 함)
ex)
public @interface 에노테이션클래스명 {
int min(); // min 설정 항목
int max(); // max 설정 항목
}
↓
@에노테이션클래스명(min=10, max=100) // 설정 추가
클래스가 로드 될 때 에노테이션 추상메서드의 구현객체가 설정값을 담은 상태로 객체가 만들어진다
= 에노테이션 추상메서드는 클래스가 로드 될 때 설정추가 한 값을 반환값으로한 객체가 생성된다
default : 설정항목에 설정추가 안하고 기본값 넣기
-> 기본값이 있으면 설정추가 안해도 ㅇㅋ
-> 기본값이 없으면 필수로 설정추가해줘야 함(값을 넣어줘야 함)
ex)
public @interface MyAnno {
int min() default 10; // min() 설정 항목, 기본값 10
int max() default 100;// max() 설정 항목, 기본값 100
}
설정추가가 한개만 있는 경우 value()를 많이 쓴다
-> 설정추가 할 때 생략 가능하기 때문에
ex)
String value(); // 에노테이션 추상메서드 정의(설정항목)
↓
@MyAnno(value = "이름1") //이렇게 설정항목에 설정추가해주는게 정석이지만
↓
@MyAnno("이름1") // 설정추가가 한개만인경우 이렇게 생략가능
예시)
↓ @Target 컨트롤 + 마우스 왼쪽키

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();
}
ㄴ 인터페이스 안쪽에 정의된 내용이 있음
ㄴ 에노테이션도 추상메서드를 정의할 수 있다
ㄴ 설정항목들을 주로 정의
예시) 에노테이션 만들어보기

ㄴ 에노테이션 클래스 생성

ㄴ 인터페이스이자 클래스이다

ㄴ 에노테이션 만들기 완

ㄴ 내가 만든 에노테이션(MyAnno) 적용해보기
ㄴ 에노테이션 적용 범위 늘리고 싶은뎅

ㄴ MyAnno 에노테이션클래스에 정의한 @Target(ElementType.Type) 에서 ()쪽에 입력된 값은 value()에 할당된 것
ㄴ value() : 설정에대한 이름
ㄴ ElementType[] value(); : 배열 형태로 되어있다 = 설정항목을 늘릴 수 있음
참고) 배열형태가 아니면 설정 한개만 가능
↓ @Retention 컨트롤 + 마우스 왼쪽키

ㄴ @Target(ElementType.Type) -> @Target(value={ElementType.Type, ElementType.METHOD})
ㄴ 에노테이션 적용 범위 늘리기 완

ㄴ 코드 줄이기
ㄴ @Target({ElementType.Type, ElementType.METHOD}) : value 생략 가능
ㄴ import static java.lang.annotation.ElementType.*; : import하면 매번 ElementType안붙이고 상수명만으로도 ㅇㅋ

ㄴ 에노테이션 적용 범위 늘어난거 확인 완
예시) 에노테이션에 추상 메서드 정의 + 에노테이션 객체 생성(클래스 로드시점)

ㄴ MyAnno 에노테이션에 int min();, int max();추상메서드 정의
-> int min(); : min 설정 항목
-> int max(); : max 설정 항목
-> 설정항목이 추가되면 무조건 설정을 추가해 줘야 함

ㄴ 설정항목(min, max)을 포함해서 설정 추가 함 = 정보를 전달
ㄴ 정보를 전달 했으니 확인 할 수 있어야 겠징
ㄴ 정보 전달 시점 : RUNTIME으로 정의함 -> 실행과정중에 확인 가능함
ㄴ 에노테이션도 클래스 정의의 일부(클래스의 구성요소) = 클래스 안에 에노테이션 정의함 = 클래스클래스 객체에서 에노테이션 확인가능

ㄴ 그래서 자바문서 java.lang.class에 에노테이션 확인 가능 메서드 있음
ㄴ 매개변수 클래스클래스 -> getAnnotaion(클래스명.class)

MyAnno anno = (MyAnno)cls.getAnnotation(MyAnno.class);
ㄴ 에노테이션 정보를 한번 조회해보자
ㄴ 상위-> 하위클래스니까 강제형변환 해주기

ㄴ @MyAnno에노테이션은 추상메서드에 불과 = @MyAnno(min=10, max=100) 에서 10, 100은 설정만 한 것 뿐이지 아직 이 값이 반환값인건 아님
-> 실제 반환값이 있게 만들어 질려면 객체가 되야 함
-> 로드 될 때 에노테이션의 구현객체가 만들어진다
ㄴ 클래스를 컴파일 하고 실제 로딩이 됬을 때 프록시가 에노테이션의 구현객체를 대신해서 만들어 줌
ㄴ 프록시 : 대신해서 완성된 구현객체 생성
ㄴ 메서드에 값이 있다 = 메서드가 완전하다

ㄴ int min = anno.min();, int max = anno.max(); : 호출해야 에노테이션 추상메서드에 담겨있는 값이 에노테이션 추상메서드 구현체의 반환값이 됨
ㄴ 출력되는거 보니까 반환값이 있넹
ㄴ MyAnno는 추상메서드인데 어떻게 반환값이 있지?
-> 반환값이 있다 = 메서드 구현내용이 있다
= 반환값은 메서드의 구현부분에 있으니까 반환값이 있다는 것은 메서드의 구현내용이 있다는 뜻
-> 반환값이 나올 수 있게 MyAnno 추상메서드에 구현내용이 추가되었다
-> 클래스가 로드 될 때 프록시형태의 어떤 객체로 MyAnno 추상메서드의 구현객체가 설정값@MyAnno(min=10, max=100)을 담은 그 상태로 만들어진다
예시) default : 설정하지 않고 기본값 넣기

ㄴ default : 설정하지 않고 기본값 넣기

ㄴ 기본값을 설정했기 때문에 설정추가 안해도 에러 안 뜸

ㄴ default로 넣은 기본값이 출력되는 것을 볼 수 있음
예시) 설정값이 여러개인 경우 -> 배열로 정의

ㄴ 배열형태로 에노테이션 추상메서드 정의하면 설정값을 여러개 넣을 수 있음
ㄴ default로 기본값 설정 안했으니 설정 추가 즉, 값을 넣어줘야 함
-> 배열이니까 배열형태로 값 넣어주기
-> String으로 정의했으니 문자형태로 값 넣기
참고) 배열에서 default 설정 형식

ㄴ String자료형 + 배열형태로 설정 추가 해 줌 = 값들을 넣어줌
참고)
설정추가할 값이 한개만 있으면 {}로 생략가능

ㄴ 조회해보자
ㄴ 출력 잘 되었군ㅎㅎ
예시) 설정추가가 한개만 있는 경우 value()를 많이 쓴다

ㄴ String value(); : 에노테이션 추상메서드 정의

ㄴ 원래는 이렇게 하는게 맞음

@MyAnno(value = "이름1") -> @MyAnno("이름1")
ㄴ value() 의 설정추가가 한개만 있는 경우 value= 생략가능
ㄴ 두개이상이면 생략x
ㄴ 그래서 설정추가가 한개만 있는 경우 value()를 많이 쓴다
참고) 설정추가 2개 ->
value=생략x
ㄴ 생략했더니 에러 뜸
ㄴ ㅇㅋㅇㅋ

ㄴ 출력 잘 됨
예시) @Repeatable

ㄴ todos 에노테이션 클래스 정의

ㄴ todo 에노테이션 클래스 정의
ㄴ 에러 뜨는 이유 : 설정이 필수로 한개 들어가야 함
↓ Repeatable 마우스 우클릭

ㄴ @Repeatable : 매개변수가 클래스클래스
ㄴ 즉 반복해서 담아 줄 에노테이션이 뭔지 알려줘야 한다



ㄴ @Repeatable 이기 때문에 반복해서 값을 담을 수가 있음
ㄴ 값의 조회는 Todos를 통해 가능

ㄴ 할일1, 할일2, 할일3 출력 됨
안녕하세요. 미슐랭가이드 심사위원입니다.
⭐️⭐️⭐️드리겠습니다.