신용권 님의 ''이것이 자바다'' 5장 공부 기록
책을 보면서 새롭게 눈에 들어온 부분만 담았다. 이전에 배운 부분이기도 하고, 비교적 간단한 내용을 다루고 있기 때문이다.
데이터 타입에는 기본 타입과 참조 타입이 있다.
둘의 차이는 변수에 저장되는 값이 다르다는 것이다. 기본 타입은 실제 값을 변수 안에 저장하고, 참조 타입은 메모리의 번지를 값으로 가진다. 이렇게 번지를 통해 객체를 참조한다는 뜻에서 참조타입이라고 한다.
변수는 스택 영역에, 객체는 힙 영역에 저장된다.
JVM은 메모리 영역(Runtime Data Area)를 메소드, 힙, 스레드 영역으로 나누었다.
메소드 영역에는 클래스, 필드, 런타임 상수풀 등이 저장된다. JVM이 시작할 때 생성되고 모든 스레드가 공유하는 영역이다.
힙 영역은 객체와 배열이 생성되는 영역이며, 생성된 객체와 배열은 스택 영역의 변수나 다른 객체의 필드에서 참조한다. 참조하는 변수나 필드가 없다면 쓰레기 객체로 간주되어 쓰레기 수집기에 의해 제거된다.
스레드 영역은 .. 솔직히 아직 이해 못했다. 스택의 영역을 말하는 것 같은데, main스레드와 같은 말로 대강 이해했다. 프로그램이 실행되는 영역으로 생각하고 있다.
String a = "어떻게";
String b = "어떻게";
String c = new String("어떻게");
System.out.println(a==b);//true
System.out.println(a==c);//false
System.out.println(a.equals(c));//true
배열이란, 같은 타입의 데이터를 연속된 공간에 나열시키고, 각 데이터에 인덱스(index)를 부여해 놓은 자료구조이다.
만약, 다른 타입의 데이터를 저장하려고 하면 타입 불일치(Type mismatch) 컴파일 오류가 발생한다.
생성된 배열의 타입과 길이는 바꿀 수 없다.
타입 [] 변수; 혹은 타입 변수 []; 의 형태를 가진다. ex) int [] arr; , int arr [];
이 때 배열은 참조변수에 속하므로 참조할 배열 객체가 없으면 배열 변수들을 null 값으로 초기화 된다. 이 변수를 읽거나 저장하려 하면 앞에서 언급했던 NullPointerException이 발생한다. 배열을 생성하고 참조하는 상태에서 값을 저장하거나 읽어야 한다.
타입 [] 변수 = {값1, 값2, 값3}; 의 형태를 가진다. ex) int [] arr = {1, 3, 5 };
중괄호로 주어진 값들을 항목으로 가지는 배열 객체를 힙 영역에 생성하고 배열 객체의 번지를 리턴한다.
한편, 선언 후(타입 변수 [];)에는 중괄호를 사용한 배열 생성이 불가하다. 그러나 new연산자를 사용하면 가능하다.
-> 타입 [] 변수; //원래는 중괄호 사용 불가 but
변수 = new 타입[] {값1, 값2, 값3};
메소드의 매개값으로 값 목록이 없는 배열이 사용될 경우에도 new 연산자와 중괄호를 사용하면 매개값으로 사용이 가능해진다.
int result = add( {100, 39, 40});//컴파일 에러
int result = add( new int[]{100, 39, 40}); //가능
값의 목록이 없지만 향후 값들을 저장할 배열을 미리 만들고 싶다면 new 연산자를 활용하면 된다.
값 목록 없는 배열 크기 설정
-> 타입 변수 [] = new 타입[길이]; ex) int arr [] = new int [3];
그리고 new로 배열을 생성하면 자동 초기화가 되어 초기값이 null값이 된다.
배열 길이를 얻을 때는 length필드(객체 내부의 데이터)를 읽으면 된다. 이는 for문에 많이 쓰이며, 인덱스를 초과하여 사용할 경우에는 ArrayIndexOutOfBoundsException이 발생하게 된다.
배열은 한 번 생성 후 크기 변경을 할 수 없으므로 더 많은 저장 공간이 필요하다면 보다 큰 배열을 만들고 이전 배열로 부터 항목 값들을 복사해야 한다.
이 때 두 가지의 방식을 사용할 수 있다.
int [] oldArray = {1,3,4};
int [] newArray = new int [5];
for(int i=0; i<oldArray.length; i++){
newArray[i] = oldArray[i];
}
int [] oldArray = {1,3,4};
int [] newArray = newArray int [5];
System.arraycopy(oldArray, 0, newArray, 0, oldArray.length);
//매개 값 : 원본배열, 원본 복사 시작인덱스, 새 배열, 새 배열 붙여넣을 시작인덱스, 복사할 개수
for(타입변수 : 배열 ){
실행문
} //향상된 for문 예시
//Week.java
public enum Week{ //열거타입 이름
MONDAY, TUESDAY, WENESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY //열거상수
}
//열거타입 변수 = 열거타입.열거상수;
Week today = Week.SUNDAY;
//이는 메소드 영역의 참조번지 주소를 스택의 변수영역에 복사한 것과 같다.
//그러므로 이 둘은 같은 객체를 참고하게 되고, ==연산의 결과가 참으로 나오게 된다.
Week birthday = null; // 열거 타입 변수도 참조타입이므로 열거 상수는 객체이고, 따라서 null값을 저장할 수 있다.
name() 메소드
Week today = Week.SUNDAY;
String name = today.name();//열거 객체 내부의 문자열인 "SUNDAY"를 리턴하고 name 변수에 저장한다.
ordinal() 메소드
Week today = Week.SUNDAY;
int ordinal = today.ordinal();
compareTo() 메소드
Week day1 = Week.MONDAY;
Week day2 = Week.WEDNESDAY;
int result1= day1.compareTo(day2); //-2
int result2= day2.compareTo(day1); //2
valueOf() 메소드
Week weekDay = Week.valueOf("SATURDAY");
// weekday는 Week.SATURDAY 열거객체를 참조하게 된다.
values() 메소드
//예시
Week[] days = Week.values();
for(Week day : days){
System.out.println(day);
}