[F-Lab 모각코 챌린지 8일차] TIL

JeongheeKim·2023년 6월 8일

TIL

목록 보기
8/66

학습계획


  • 자바의신 6장 읽고 연습문제 풀이
  • equals(), hashCode() 정리

Today I Learned


  • 비교대상 변수는 long타입을 제외한 타입을 사용할 수 있다.
  • break문을 빼먹을 경우 아래 case에 적힌 코드까지 실행되므로 case마다 break문을 꼭 넣어야한다.
  • default문은 위의 case의 경우가 맞지 않을 경우 기본으로 수행할 조건식 인데 default의 순서는 가장 마지막에 와야한다.
switch(비교대상변수) {
    case 입력값1: ...
         break;
    case 입력값2: ...
         break;
    ...
    default: ...
         break;
}
  • while문의 조건에는 boolean조건만 가능하다.
  • true일 경우 중괄호 코드가 수행된다.
while (조건문) {
    <수행할 문장1>;
    <수행할 문장2>;
    <수행할 문장3>;
    ...
}
  • while문은 조건문이 맞아야만 while문이 수행되는데 do-while은 한번은 꼭 수행된 뒤 조건에 맞을 경우 계속 반복한다.
do {
    <수행할 문장1>;
    <수행할 문장2>;
    <수행할 문장3>;
    ...
} while(boolean조건)

정리해봅시다

  • if 문장의 소괄호 안에는 어떤 타입의 결과가 제공되어야 하나요?
    • boolean타입의 결과가 제공되어야한다.
  • if 조건에 맞지 않는 모든 경우를 처리할 때 사용하는 예약어는 뭔가요?*
    • else
  • switch를 사용할 수 있는 기본 자료형의 타입에는 어떤 것들이 있나요?*
    • long타입을 제외한 타입이 사용 가능하다.
  • switch블록 안에서 비교 대상값 앞에 사용하는 예약어는 무엇인가요?*
    • case
  • switch 조건을 빠져나가도록 하는 예약어는 무엇인가요?*
    • break
  • switch 조건들에 맞지 않을 때 기본 처리를 하기 위한 예약어는 무엇인가요?*
    • default
  • while 문의 소괄호 안에는 어떤 형태의 결과가 제공되어야 하나요?*
    • boolean 결과값을 제공해야한다.
  • while 문을 무조건 한번은 실행하게 하려면 어떻게 해야 하나요?*
    • do while문을 사용해야한다.
  • while문을 마음대로 빠져나가게 하려면 어떤 예약어를 사용하면 되나요?*
    • break 문을 사용한다.
  • while문의 중간에 while문의 소괄호 점검 구문으로 건너뛰도록 할 때 사용하는 예약어는 무엇인가요?
    • continue
  • for루프의 소괄호안의 가장 첫 구문(첫 세미 콜론 앞의 문장)은 for루프가 수행되는 동안 몇 번 수행되나요?*
    • for(int i=0; i<n; i++) 일 경우 n번 수행된다.
  • for루프의 소괄호 안의 중간에 있는 구문은 어떤 타입의 결과가 제공되어야 하나요?
    • boolean타입으로 제공되어야한다.
  • for루프의 소괄호 안의 마지막에 있는 구문에서는 어떤 작업을 수행하나요?
    • for루프가 계속 반복될 수 있도록 조건 값을 증가시킨다.

equals도 내부적으로 ==를 사용하는데, 왜 동등성을 비교할 때 equals를 사용해야 할까?

동치라는 개념에 대해 먼저 알아보자.

  • 레퍼런스 동치(reference equality) Heap영역에 있는 객체를 두 레퍼런스가 참조하는 것
  • 객체 동치(object equality) 힙에 객체가 두개 있을때, 두 레퍼런스가 각 객체를 참조하지만 그 두 객체가 동치인것 을 간주할 수 있는 것

기본 자료형의 값을 비교할때는 !=,== 연산자를 사용해서 비교한다. !=,== 연산자를 기본 자료형 비교에 사용했을때는 값의 비교가 이루어 지지만, 참조자료형에 대해서는 주소값 비교가 일어난다.

❓참조 자료형에서는 왜 주소값 비교가 일어나는가?

참조변수는 객체를 가르키는 변수이므로, 참조변수에는 객체에 대한 주소(Heap 주소)값이 들어있다. 그러므로 객체에 대해 !=,== 연산 시 메모리 주소값을 비교하게 된다. 다시말해 객체마다 최상위 부모클래스 Object로 부터 상속받은 hashCode()를 리턴하게 된다.

아래 예시를 보면 참조변수 member1, member2의 객체의 필드값은 동일하지만 주소값이 다른것을 확인 할 수 있다.

public class EqualityTest {
	public static void main(String[] args) {
		EqualityTest equalityTest = new EqualityTest();
		equalityTest.equalMethod();
	}

	public void equalMethod() {
		MemberDTO member1 = new MemberDTO("smith");
		System.out.println("member1 = " + member1);
		MemberDTO member2 = new MemberDTO("smith");
		System.out.println("member2 = " + member2);

		if(member1 == member2) {
			System.out.println("member1 and member2 is same");
		} else {
			System.out.println("member1 and member2 is not same");
		}
	}
}
member1 = MemberDTO@59a6e353
member2 = MemberDTO@7a0ac6e3
member1 and member2 is not same

❓equals도 내부적으로 ==를 사용하는데, 왜 동등성을 비교할 때 equals를 사용해야 할까?

== 연산자를 사용하는것은 인스턴스 변수에 들어있는 주소값을 비교하는 연산이므로 객체의 동치를 확인 하기 위해서는 Object로 부터 상속받은 equals(), hashCode()를 Overring해서 동등한 객체에서 같은 해시코드를 리턴하도록 해야한다. Overriding 하지 않는 경우 조상 Object의 메서드를 사용하게 된다.

  • equals()를 Overriding하면 hashCode()도 Overriding해야한다.
    • equals()는 ==연산으로 Heap 영역에서 동일한 객체를 참조하는지 확인하는데, 두 객체의 주소 값에 대한 값은 hashCode()에서 구할 수 있기 때문이다.
    • a.equals(b)a.hashCode() == b.hashCode()가 성립하지만 a.hashCode() == b.hashCode() 맞다고 해서 a.equals(b)이 성립하지 않는다.
  • hashCode()에서는 Heap영역에 있는 객체마다 가지고 있는 고유한 주소값(정수) 리턴. 클래스에서 hashCode()를 Overring하지 않으면 절대로 같은 객체라고 간주 될 수 없다.

위의 예시에서 비교할 객체에 equals()와 hashCode()를 재정의 하였다.

public class MemberDTO {
	private String name;

	public MemberDTO(String name) {
		this.name = name;
	}

	@Override
	public boolean equals(Object o) {
		if (this == o)
			return true;
		if (o == null || getClass() != o.getClass())
			return false;
		MemberDTO memberDTO = (MemberDTO)o;
		return name.equals(memberDTO.name);
	}

	@Override
	public int hashCode() {
		return Objects.hash(name);
	}
}

0개의 댓글