인프런 영문 브랜드 로고
인프런 영문 브랜드 로고

인프런 커뮤니티 질문&답변

작성자 없음

작성자 정보가 삭제된 글입니다.

스프링 핵심 원리 - 기본편

회원 도메인 실행과 테스트

안녕하세요. enum 질문있습니다.

작성

·

367

0

안녕하세요. 개발자님

제가 전 강의때 enum을 처음보게되서 구글검색으로

간단히 상수를 정렬해서 표현하는 것이라는 느낌은 

알았습니다. 더 강의를 보려고 했는데 궁금한점이 생겨서

질문남깁니다.

1. enum Grade의 BASIC, VIP가 상수로 회원 등급을 

지정해 준 것이라고 판단이 듭니다. 이때 BASIC, VIP가

상수로 지정된 값이 무엇인지 궁금합니다. 

예를들면 String Basic에 BASIC이라는 String이 들어가

있는 것인지, String Basic이라는 공간만 할당되어 있는

것인지 이런 것입니다. 제가 main 에서 테스트 해봤을때,

VIP값이 "VIP"와 비교해봤을때는 false이고 Grade.VIP

와 비교해봤을때는 true가 나온것을 봤을때 enum의

VIP는 문자열 값이 아닌 것 같다 정도입니다.

또 System.out.println으로 Grade.VIP를 출력해봤을때

VIP가 출력되므로 Grade안의 VIP에는 VIP라는 값이

담겨져 있다 정도입니다.

결과적으로 제가 알고 싶은 것은 enum으로 저렇게

선언 시 어떤 동작이 이루어져서 무슨 값이 안에 

들어가 있는건지 궁금합니다. 

제가 추정해보기에는 enum Grade안에 선언한 

BASIC, VIP라는 코드는 실제로

private final Grade BASIC = new Grade();

private final Grade VIP = new Grade();

라는 변수 안에 BASIC은 "BASIC"이라는 String이

setting 되어 있고, VIP는 "VIP라는 String 값이 setting

되어 있는 것 아닌가 싶습니다.

솔직히 필드를 클래스로 선언하는것 부터가 헷갈려서

위의 코드를 적고도 잘 이해가 안가긴 하네요..

열심히 공부해야겠습니다.

답변 2

7

안녕하세요. 

질문을 3 부분으로 나누어 답변을 적어보았습니다. 

(답변 작성 에디터에서는 개행이 여러번 안되서 가독성이 좀 떨어지네요.)

1) Member member = new Member(1L, “이유진”, Grade.VIP); 

System.out.println(member.getGrade()); 로 출력한다면 1이라는 상수가 나와야 할 것 같다고 추정했습니다.

하지만 결과는 VIP가 나왔습니다.

답변 :  Member member = new Member(1L, “이유진”, Grade.VIP);  

여기서 member.getGrade() 메소드는 Grade.VIP의 주소값을 반환합니다. 

member의 grade 필드는 Grade 클래스의 VIP라는 필드의 주소값을 알고 있는 것 입니다.  

그런데 Grade의 필드 VIP는 그 자체로서 Grade 객체입니다. 

Grade가 Enum이라는 열거형 객체이기 때문입니다. 

주소를 따라가서 객체 이름을 출력하므로 VIP 가 출력됩니다. 

Enum 열거형 클래스 Grade 가 선언된 순간, Grade 클래스를 상수처럼 사용할 수 있습니다.

Grade.VIP의 주소값은 컴파일타임에 정해지는 상수 객체이기 때문에 프로그램이 동작하는 동안 변할 수 없고 똑같습니다. 

다시 말하면, Grade의 필드 VIP는 public static final 필드이면서 동시에 Grade객체입니다.

2) System.out.println(member,getGrade() == 1);은 int와 비교 시 에러가 난다는 문구가 나왔습니다.

답변: 맞습니다. 자료형이 다르니까 비교할 수 없어서 컴파일 에러가 발생합니다.

왜냐하면 1은 int라는 기본 자료형(primitive type)이고,

member.getGrade()는 enum 참조형(reference type) 즉, 객체형입니다. 

3) equals로 Grade.VIP와 비교 했을 경우만 true가 나오고, 

equals(“VIP”)는 false, ==를 통한 비교는 에러가 나게됩니다.

답변 :  equals 는 메소드입니다.  == 는 연산자 입니다.

메소드는 ‘값’을 비교합니다. 연산자는 대상의 ‘주소값’을 비교합니다. 

call by value와 call by reference 차이를 떠올리시면 될 것 같습니다. 

member.getGrade() 를 equals(Grade.VIP) 로 비교하면 true가 나옵니다.

둘다 주소값을 알고 있고 둘 다 객체가 상수객체이므로 주소가 같습니다. 

모든 Grade 타입의 객체의 VIP는 같은 주소값을 가집니다.

그래서 Grade.VIP와 비교하면 true가 나옵니다. 

member.getGrade() 를 equals(“VIP”) 로 비교하면 false가 나옵니다.

equals 메소드는 String객체 “VIP”와 컴파일 타임에 주소값이 정해진 객체 Grade.VIP 은 서로 다르기 때문입니다.  

member.getGrade()  == “VIP”  는 에러가 납니다.  

member.getGrade() 는 컴파일 타임에 힙 영역에 주소값이 *정해진* 객체 Grade.VIP의 주소값을 참조합니다. 

“VIP” 는 동적으로 생성한 객체의 주소값입니다. (프로그램 실행 도중 주소가 정해짐) 

이미 할당된 주소값과 동적으로 생성하는 주소값은 비교할 수 없기 때문에 컴파일 에러가 납니다. 

적고 보니 엄청 길어졌습니다...  조금이나마 도움이 되었으면 좋겠습니다. 

감사합니다. 

친절한 답변 정말 감사드립니다. 여러번 읽어서 꼭 이해할 수 있도록 하겠습니다. 고맙습니다.

좋은일 많으시길 바랍니다!

1

안녕하세요.

enum은 선언된 순서에 따라 0, 1, 2 .. 의 순차적으로 증가된 값을 가집니다. 

예시를 들자면, 

enum Season{

	spring, summer, fall, winter
}

spring == 0 

summer == 1

fall ==2 

winter ==3 

따라서 

수업 시간에 사용한 enum Grade안에 선언한 

BASIC라는 코드는 0값을 가지는 상수입니다. 

VIP라는 코드는 1값을 가지는 상수입니다. 

김영한님의 프로필 이미지
김영한
지식공유자

brocoli님 감사합니다^^

답변 감사드립니다. 하지만 이해가 안되는 점이 있어서 질문 남깁니다.

수업시간에 main에서 test 했을대 Member member = new Member(1L, "이유진",

Grade.VIP); 이런식으로 member를 생성했던걸로 기억합니다.

그렇다면 말씀해주신 정보를 토대로 System.out.println(member.getGrade()); 로 출력

한다면 1이라는 상수가 나와야 할 것 같다고 추정했습니다. 하지만 결과는 VIP가 나왔습니다.

또한 System.out.println(member,getGrade() == 1);은 int와 비교 시 에러가 난다는 문구가

나왔습니다.

추가적으로 수업시간에 enum 값은 ==로 비교 하라고 했는데 위의 문구에서 equals로

Grade.VIP와 비교 했을 경우만 true가 나오고 equals("VIP")는 false, ==를 통한 비교는

에러가 나게됩니다. 그래서 Grade라는 enum 안에 BASIC과 VIP 안의 값을 본문에 기재된

내용처럼 추정한 것인데 어떻게 상수 값 0과 1 로 차례로 설정된 것인지 이해가 가지 않아서

재질문 남깁니다 ㅠ

작성자 없음

작성자 정보가 삭제된 글입니다.

질문하기