Day 41

ChangWoo·2023년 5월 16일
0

자바의 정석

목록 보기
41/71

ch 9-4~6 hashCode(), toString()

hashCode()

객체의 해시코드(hash code)를 반환하는 메서드

  • 해시코드 = 정수값 ("해시"라는 알고리즘에서 사용)
    Object클래스의 hashCode()는 객체의 주소를 int로 변환해서 반환
public class Object {
	...
    public native int hashCode(); // 네이티브메서드 : OS의 메서드(C언어로 작성되어 있다.) & 이미 작성된 것을 사용하기 때문에 내용이 없다.
}
  • 객체의 주소로 반환하기 때문에 객체마다 다른 값을 가진다.(= 객체의 지문)
    equals()를 오버라이딩하면, hashCode()도 오버라이딩해야 한다.
  • equals()와 hashCode()는 둘 다 주소를 가지고 작업을 한다.
  • equals()가 iv를 통해 작업을 한다면, hashCode()도 iv를 통해 작업을 해야 한다.
  • equals()의 결과가 true인 두 객체의 해시코드는 같아야 하기 때문
  • 주소를 가지고 있지만, iv를 통해 오버라이딩 한다.
  • 위의 String은 오버라이딩이 잘 되어 있는 경우다.
    System.idnetityHashCode(Object obj)는 Object클래스의 hashCode()와 동일
  • idnetityHashCode = 객체마다 다른 해시코드를 반환한다.
  • 32bit JVM은 주소가 int타입 / 64bit JVM은 주소가 8byte(long) 그래서, 64bit JVM으로 HashCode()를 만들게 되면, 겹치는 값이 생성될 수 있다.

toString(), toString()의 오버라이딩

toString() : 객체를 문자열(String)으로 변환하기 위한 메서드

public String toString() {	// Object클래스의 toString()
	return getClass().getName()"@"+Integer.toHexString(hashCode());
    	// 설계도객체  클래스이름 at(위치) 해시코드(객체주소)를 16진수로 표현  
}


  • 클래스이름 + 주소값이 나오게 된다.
  • 그런데, Object에 있는 toString()은 유용하지 못하므로 iv의 값을 출력하도록 오버라이딩 해준다.
  • 결과가 변하게 된다.
  • 객체==iv집합이므로 객체를 문자열로 변환한다는 것은 iv의 값을 문자열로 변환한다는 것과 같다.
  • 그렇기 때문에, 오버라이딩 한다는 것은 iv를 문자열로 바꾸는 의미이므로 오버라이딩을 할 때 iv를 활용한다.

ch 9-7~10 String클래스, 문자열비교, 빈 문자열

String 클래스 (문자열을 다루기 위한 클래스)

String 클랫 = 데이터(char[]) + 메서드(문자열 관련)

  • 데이터 = 문자배열
  • 메서드 = 문자열을 다루는데 필요한 메서드
public final class String implements java.io.Serializable, Comparable {
	private char[] value;
    ...

내용을 변경할 수 없는 불변(immutable)클래스

String a = "a";
String b = "b";
a = a + b;

  • a와 b가 더해져서 기존 주소값에 저장되는 것이 아니라, 새로운 주소값에 저장이 된다.
    (내용을 변경할 수 없으므로)
  • 0x300이 기존의 a의 값에 저장된다.
    덧셈 연산자(+)를 이용한 문장려 결합은 성능이 떨어짐. 문자열의 결합이나 변경이 잦다면, 내용을 변경가능한 StringBuffer를 사용(StringBuffer는 내용 변경 가능)

문자열의 비교

String str = "abc"와 String str = new String("abc");의 비교

  • 첫 번째 = 문자열 리터럴
  • 두 번째 = new 연산자

  • str1과 str2는 "abc"를 가리키고 str3과 str4는 각각의 "abc"를 가리킨다.
  • 즉, 문자열 리터럴로 문자열을 만들면, 하나의 문자열을 여러 참조변수가 공유한다.
  • new 연산자를 사용하면, 항상 새로운 객체(문자열)가 만들어진다.
  • 문자열은 내용 변경 불가. (여러 참조 변수가 공유해도 문제X) 그래서 굳이 new 연산자 사용할 필요 X
  • 그래서 str1과 str2의 참조변수 값을 비교하면 같은 값이 된다.
  • str3과 str4는 서로 다른 객체이므로 다른 값이 된다.
  • 그래서 문자열을 비교할 때는 == 대신 equals()를 사용해야 한다.
  • equals는 내용비교, ==은 주소비교(어떨 때는 true, 어떨 때는 false)

문자열 리터럴

문자열 리터럴은 프로그램 실행시 자동으로 생성된다.(constant pool에 저장)

  • contant pool = 상수 저장소
    같은 내용의 문자열 리터럴은 하나만 만들어진다.
  • 문자열 리터럴도 String 객체다. (내용변경이 불가하다.)

빈 문자열("", empty string)

내용이 없는 문자열. 크기가 0인 char형 배열을 저장하는 문자열

String str = ""; // str을 빈 문자열로 초기화

크기가 0인 배열을 생성하는 것은 어느 타입이나 가능

char[] chArr = new char[0]; // 길이가 0인 char 배열
int[] iArr = {}; // 길이가 0인 int 배열
  • 숫자를 문자로 바꿀 때 사용
  • 배열을 초기화 할 때 null보다 빈 문자열이 유리하다.
    문자(char)와 문자열(String)의 초기화
  • null 혹은 유니코드의 첫번째 문자인 기본값을 사용하지 않고 공백 또는 빈 문자열로 초기화한다.
String str1 = "";   	String str4 = new String("");
String str2 = "";   	String str5 = new String("");
String str3 = "";   	String str6 = new String("");
  • str1~3이 str4~6 보다 더 잘 써진 코드이다.
  • str4~6은 new 연산자를 사용했기 때문에 계속 빈 배열이 생성된다.
profile
한 걸음 한 걸음 나아가는 개발자

0개의 댓글