이것이 자바다 신용권의 Java 프로그래밍 정복 - 5장
5장
* 해당 글은 "이것이 자바다 신용권의 Java 프로그래밍 정복"을 기반으로 작성하였으며
책의 모든 목차를 다루는 것은 아니기에 내용중에 목차에서 빠진 부분도 있다는점 참고바랍니다.
5장 목차
- 5.1 데이터 타입 분류
- 5.2 메모리 사용 영역
- 5.3 참조 변수의 ==, != 연산
- 5.4 null과 NullPointerException
- 5.5 String 타입
- 5.6 배열 타입
- 5.7 열거 타입
5.1 데이터 타입 분류
자바의 데이터 타입에는 크게 기본타입(원시 타입)과 참조 타입으로 분류된다.
기본타입 : 정수, 실수, 문자, 논리 리터럴
참조타입 : 배열, 열거, 클래스, 인터페이스
(참조타입은 객체의 번지를 참조하는 타입이라고 생각하면 됨)
기본타입으로 선언된 변수와 참조타입으로 선언된 변수의 차이점은 저장되는 값이 다르다는 것이다.
기본타입으로 선언된 변수는 실제 값을 변수 안에 저장하지만
참조타입으로 선언된 변수는 메모리의 번지를 값으로 갖는다.
위에서 언급했던 것처럼 번지를 통해 객체를 참조한다는 뜻에서 참조타입이라고 부른다.
int age = 25;
double price = 100.5;
String name = "신용권"
String hobby = "독서"
위와 같이 코드를 작성하면 스택영역에
age는 25 로 작성한 값이 그대로 저장이 되지만
name은 Bang이 아닌 100으로 저장이된다. (여기서 100은 값이 아닌 힙 영역에 번지수를 가리킨다.)
<변수는 스택영역에 생성되고 객체는 힙 영역에 생성된다>
5.2 메모리 사용 영역
java.exe로 JVM이 시작되면 운영체제에서 할당받은 메모리 영역을 구분해서 사용한다.
- 메소드 영역
메소드 영역은 JVM이 시작할 때 생성되고 모든 스레드가 공유하는 영역이다.
- 힙 영역
힙 영역은 객체와 배열이 생성되는 영역이다.
힙 영역에 생성된 객체와 배열은 JVM 스택 영역의 변수나 다른 객체의 필드에서 참조한다.
- JVM 스택 영역
JVM 스택 영역은 각 스레드마다 하나씩 존재하며 스레드가 시작될 때 할당된다.
자바 프로그램에서 추가적으로 스레드를 생성하지 않았다면 main 스레드만 존재하므로 JVM 스택도 하나이다.
JVM 스택은 메소드를 호출할 때마다 프레임을 추가 하고 메소드가 종료되면 해당 프레임을 제거하는 동작을 수행한다.
5.3 참조 변수의 == , != 연산
기본 타입 변수의 == , != 연산은 변수의 값을 놓고 비교하지만,
참조 타입 변수들간의 == , != 연산은 동일한 객체를 참조하는지, 다른 객체를 참조하는지 알아볼 때 사용된다.
참조타입 변수의 값은 힙 영역의 객체 주소이므로 결국 주소 값을 비교하는 것이 된다.
동일한 주소 값을 갖고 있다는 것은 동일한 객체를 참조한다는 의미이다.
5.4 null과 NullPointerException
힙 영역의 객체를 참조하지 않는다는 뜻으로 null(널) 값을 가질 수 있다.
null 값도 초기값으로 사용할 수 있기 때문에 null로 초기화된 참조 변수는 스택영역에 생성된다.
5.6 배열 타입
배열은 같은 타입의 데이터만 저장할 수 있다. ( int 배열은 int 값만, String 배열은 string만 )
만약 다른 타입의 값을 저장하려고 하면 타입 불일치 컴파일 오류가 발생한다.
배열은 한번 생성된 배열은 길이를 늘리거나 줄일 수 없다.
3개의 값을 저장하는 배열을 생성한 후에는 실행 도중에 5개의 값을 저장하는 배열로 수정할 수 없다는 의미이다.
만약 5개의 값을 저장하려고한다면 길이 5의 새로운 배열을 생성하고,
기존 배열을 복사하는 방법이있다.
5.6.6 커맨드 라인 입력
main() 메소드의 매개값인 String[] args는 왜 필요할까?
바로 main() 메소드를 호출할때 매개값을 전달받기 위해서이다.
java 클래스 문자열0 문자열1 과 같이 작성해서 실행시키면,
String[] args = { 문자열0, 문자열1 } 이라는 값을 갖게되고,
main method에서 문자열0과 1이 담긴 args라는 배열을 사용할 수 있게 되는 것이다.
5.6.7 다차원 배열
int[][] scores = new int[2][3];
위와 같이 작성하면 2(행) x 3(열) 인 2차원 배열이 생성된다.
여기서 이 코드는 메모리에 세 개의 배열 객체를 생성한다.
모든걸 감싸는 객체 1개, 그 안에 3개의 배열을 가진 객체 2개로 총 3개의 객체가 생성된다.
하지만 만약에 int라는 기본타입변수가 아니라 String과 같은 참조타입 변수로 다차원 배열이 만든다면
3개가 아니라 9개가 될 것이다. ( 변수 값이 모두 다를 경우 )
모든걸 감싸는 객체 1개, 그 안에 3개의 배열을 가진 객체 2개, 객체안에 3개의 배열에 각각 들어있는 String 객체 x 2
총 9개이다.
5.6.9 배열 복사
위에서 언급했던것처럼 자바에서는 배열을 선언한 이후에는 배열의 크기를 변경하지 못해
복사라는 방법을 사용해야한다.
이때 유용하게 쓰이는 함수가 System.arraycopy() 메소드이다.
함수 사용 방법은 다음과 같다.
System.arraycopy(Object src, int srcPos, Object dest, int destPos, int length);
src는 원본 배열이고, srcPos는 원본 배열에서 복사할 항목의 시작 인덱스이다.
dest 매개값은 새 배열이고, destPos는 새 배열에서 붙여넣을 시작 인덱스이다.
length는 복사할 개수이다.
System.arraycopy(arr1, 0 ,arr2 , 0 , arr1.length);
따라서 위와같이 작성하면,
arr1배열의 인덱스 0 부터 arr1.length 길이 만큼 arr2배열의 인덱스 0부터 집어넣겠다는 의미이므로
arr1의 모든 항목을 arr2에 복사하겠다는 의미이다.
※ 참조 타입 배열일 경우, 배열 복사가 되면 복사되는 값이 객체의 번지이므로 새 배열의 항목은 이전 배열의 항목이 참조하는 객체와 동일하다. 이와 같은 복사를 얕은 복사라고 한다.
5.7 열거 타입
데이터 중에는 몇 가지로 한정된 값만을 갖는 경우가 흔히 있다.
예를들어 요일은 7개의 한정된 값만을 갖고, 계절은 4개의 한정된 값만을 가진다.
이와같이 한정된 값만을 갖는 데이터 타입을 열거 타입이라한다.
5.7.1 열거 타입 선언
열거 타입을 선언하기 위해서는 먼저 열거 타입의 이름을 정하고 열거 타입이름으로 소스파일을 생성해야한다.
열거 타입이름은 관례적으로 첫문자를 대문자로 하고 나머지는 소문자로 구성한다.
ex) Week.java, MemberGrade.java, ProductKind.java
위와같은 이름으로 파일을 생성한 후 소스파일에는 아래와 같이 열거 타입을 선언한다.
public enum Week { MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY }
Week은 열거타입이름이고 안에들어있는 값들이 열거 상수이다.
보다시피 열거상수는 모두 대문자로 작성하는것이 관례이다.
(참고로 열거 상수는 객체이다. 즉, 위와같이 작성했을 경우 7개의 객체가 생성되는 것이다.)
5.7.3 열거 객체의 메소드
열거 객체는 열거 상수의 문자열을 내부 데이터로 가지고있다.
열거 객체에서 사용하는 메소드는 java.lang.Enum 클래스에 선언된 메소드로,
모든 열거 타입은 컴파일 시에 Enum 클래스를 상속하게 되어 있기 때문에
열거 객체에서도 사용할 수 있다.
name() 메소드
name() 메소드는 열거 객체가 가지고 있는 문자열을 리턴한다.
Week today = Week.SUNDAY;
String name = today.name();
위와 같이 작성하면 today.name()으로 문자열 "SUNDAY" 를 리턴하고 해당 값이 name 변수에 저장된다.
ordinal() 메소드
ordinal()메소드는 전체 열거 객체 중 몇 번째 열거 객체인지 알려준다. (순서는 0부터 시작)
Week today = Week.SUNDAY;
int ordinal = today.ordinal();
위와 같이 작성하면 today.ordinal() 메소드에 의해 6이 리턴되어 해당값이 ordinal 변수에 저장된다.
valueOf() 메소드
valueOf() 메소드는 매개값으로 주어지는 문자열과 동일한 문자열을 가지는 열거 객체를 리턴한다.
이 메소드는 외부로부터 문자열을 입력받아 열거 객체로 변환할 때 유용하게 사용할 수 있다.
Week weekDay = Week.valueOf("SATURDAY")
위와 같이 작성할 경우 weekDay 변수는 Week.SATURDAY 열거 객체를 참조하게 된다.
"SATURDAY"라는 값을 가진 weekDay라는 열거 객체가 생성된 것이다.
values() 메소드
values() 메소드는 열거 타입의 모든 열거 객체들을 배열로 만들어 리턴한다.
다음은 Week 열거 타입의 모든 열거 객체를 배열로 만들어 향상된 for문을 이용해서 반복하는 코드이다.
Week[] days = Week.values();
for(Week day : days) {
System.out.println(day);
}