20강. 참조 타입과 참조 변수(1) - 기본 타입과 참조 타입
21강. 참조 타입과 참조 변수(2) - String 타입
22강. 배열(1) - 배열 선언, 생성, 길이
23강. 배열(2) - 명령 라인 입력
24강. 배열(3) - 다차원 배열, 객체를 참조하는 배열
25강. 배열(4) - 배열 복사, 향상된 for문
26강. 열거 타입
20강. 참조 타입과 참조 변수(1) - 기본 타입과 참조 타입
ㅁ
- 참조 타입이 무엇이고 참조 타입으로 어떻게 변수를 선언하는지
- 참조 타입의 종류와 참조 변수를 어떻게 만드는지
- 기본 타입과 참조 타입의 변수가 메모리를 어떻게 사용하는지
- 참조 변수의 ==, != 연산
- 참조 변수만이 가지고 있는 null이라는 값과 NullPointException 예외에 대해
- String 타입이 참조 타입이다.
- 자바의 데이터 타입은 크게 두 가지가 있다. 기본 타입과 참조 타입.
ㅁ 기본 타입 변수
- int age = 25; double price = 100.5;
- 기본 타입를 선언하고 값을 저장하면 메모리 스택 영역에 이들 변수가 생성되고 값이 저장됨.
ㅁ 참조 타입 변수
- String name = "독서";
- String은 기본 타입이 아니고 참조 타입이다.
ㅁ 기본 타입 변수라고 하지 않고 참조 타입 변수라고 하는 이유
- 문자열을 String 객체라고 이야기 함.
- 코드에서 문자열을 작성하면 자바는 힙이라는 메모리 영역에 String이라는 객체로 생성을 함.
- 리터럴로 "독서"라고 하는 문자열을 작성하면, 자바는 String 객체를 만들고 이 안에 문자열 독서를 저장함.
- 객체는 자신이 생성된 번지를 갖고 있음. 예를 들면 "독서"라는 문자열을 갖고 있는 String객체는 100번지의 주소를 가짐.
- 모든 변수는 스택 영역에 생성이 됨. // (지역변수만?)
(문자열은 String 객체로 힙 영역에 생성이 됨. )
기본 타입 변수인 age와 price뿐 아니라 참조 타입 변수인 name도 스택 영역에 생성이 됨.
그런데 기본 타입 변수와 달리 name에는 "독서"라는 문자열이 저장되는게 아니고, 객체의 번지가 저장이 됨.
이런 변수는 번지를 참조해서 객체를 이용한다 해서 참조 타입 변수라고 함.
참조 타입 변수는 배열, 열거, 클래스, 인터페이스가 있다. // String이 클래스 타입.
기본 타입 변수에는 직접 값이 저장됨.
ㅁ String 변수의 동작 방식
(1) 문자열 리터럴
- 문자열 리터럴(예: "hello")은 자바의 문자열 상수 풀(String Constant Pool)에 저장됩니다.
- 문자열 상수 풀은 힙의 한 부분으로, 동일한 문자열 리터럴이 여러 번 사용될 경우 메모리를 절약하기 위해 공유됩니다.
- 예를 들어, 두 개의 String 변수 str1과 str2가 동일한 리터럴 값을 가지면 둘 다 동일한 문자열 상수 풀의 객체를 참조하게 됩니다.
String str1 = "hello";
String str2 = "hello"; // str1과 str2는 같은 문자열 상수 풀의 객체를 참조합니다.
(2) new 키워드로 생성된 문자열
- new 키워드를 사용하여 String 객체를 생성하면 항상 새로운 객체가 힙 영역에 생성됩니다.
- 이 경우, 문자열 상수 풀과는 별개로 새로운 객체가 생성됩니다.
String str1 = new String("hello");
String str2 = new String("hello"); // str1과 str2는 서로 다른 객체를 참조합니다.
(3) 로컬 변수
- String 변수가 로컬 변수로 선언된 경우, 그 변수 자체는 스택에 생성되지만, String 객체는 힙에 생성됩니다.
- 로컬 변수는 힙에 있는 실제 String 객체를 참조(reference)합니다.
public void someMethod()
{ String str = "hello"; // str은 스택에 생성되지만, "hello"는 힙의 문자열 상수 풀에 생성됩니다. }
ㅁ 메모리 사용 영역(Runtime Data Area)
- 자바는 메모리 사용 영역을 3가지로 나누어서 사용함.
- 메소드 영역에는 클래스 코드들이 저장됨. 클래스 별로 분류해 저장함.
각 클래스에는 정적 필드/상수, 메소드 코드, 생성자 코드 이런 것들이 저장이 됨.
우리가 .java라는 소스코드를 작성하고 컴파일 하면 .class라는 바이트 코드 파일이 생성됨.
우리가 바이트 코드 파일(.class 파일)을 사용하면 메소드 영역에 로딩(저장)이 됨.
이렇게 저장된 클래스를 가지고 객체를 만들다든지(힙 영역) 변수를 생성한다든지(JVM 스택 영역) 용도로 씀.
- 메소드 영역에는 클래스의 바이트 코드들이 저장된다.
- 힙 영역에는 클래스로부터 생성된 객체들이 저장되는 영역.
- JVM 스택 영역은 이렇게 bucket 모양으로 생긴 메모리. 여기에 프레임이라는 것들이 쌓여서 저장이 됨.
프레임 안에는 또 bucket 모양 구조다.
여기에는 메소드가 호출할 때 사용되는 변수들이 저장되는 곳.
메소드가 실행하는 동안에만 이 프레임이 존재하고, 메소드가 종료되면 이 프레임 자체가 제거됨.
ㅁ JVM 스택 영역
- v1, v2, v3, v4 같은 기본 타입 변수에 저장된 값들은 직접 프레임 내부에 저장이 됨.
- 배열 등의 참조 타입 변수는 배열 객체 자체가 변수에 저장되는 게 아니고,
프레임 안에 scores라는 변수에 저장되는 것은 힙 영역에 생성된 배열 객체의 번지가 저장이 됨.
(배열도 객체다.)
ㅁ 참조 타입 변수 간의 ==, != 연산
- 기본 타입은 값을 비교할 때 ==, !=를 쓰지만, 참조 타입은 저장된 번지를 비교할 때 사용.
- 동일한 객체를 참조하는지, 다른 객체를 참조하는지 알아볼 때 사용.
ㅁ null과 NullPointerException
- 참조 타입 변수는 객체를 참조하지 않는다는 뜻으로 null 값을 가질 수 있음.
- null로 초기화된 참조 변수도 스택 영역에 생성
- null은 현재 참조하는 객체가 없다는 뜻.
ㅁ 예외(Exception)
- 프로그램 실행 도중 발생하는 오류
- 자바는 Error와 Exception을 구분함.
Error는 주로 하드웨어, OS의 문제로 발생. // 하드웨어 교체, OS 재설치
Exception은 프로그램이 실행하는 도중 발생. // 프로그램 소스 변경
ㅁ NullPointException
- 참조 타입 변수가 null 상태(참조하는 객체가 없는데)에서 존재하지 않는 객체의 데이터나 메소드를 사용할 경우 발생.
- 해당 참조 변수가 객체를 참조하도록 수정하여 해결.
int[] intArray = null; // = new int[3]; (해결)
intArray[0] = 10; // NullPointerException
String str = null; // "abc"; (해결) (문자열 변수는 이렇게)
System.out.println( "총 문자 수: " + str.length() ); // NullPointerException
- 배열도 객체이기 때문에 번지를 가짐.
- NullPointerException가 발생하면 이 변수가 null 값을 갖고 있는 상태인 것.
null 값을 안갖게끔 어떤 객체를 대입한다든지 문자열을 대입한다.
21강. 참조 타입과 참조 변수(2) - String 타입
ㅁ String 변수에 문자열 리터럴을 대입할 경우
(1) String 객체로 생성되고 변수가 String 객체를 참조( =변수에 String 객체의 번지가 저장됨.)
- name이라는 변수는 스택 영역에 생성되고, 문자열에 대한 String 객체는 힙 영역에 생성됨.
String name = "쿠하";
(2) 문자열 리터럴이 동일한 경우 같은 String 객체를 공유
- 이 문자열을 가진 String 객체가 2개 생성되지 않고, 생성된 String 객체의 번지를 똑같이 두 변수가 가짐.
String name1 = "쿠하";
String name2 = "쿠하";
(스택 영역에 name1, name2 변수 생성되고 힙 영역 String 객체(동일한 하나의)의 번지를 가짐.)
ㅁ new 연산자
- 객체 생성 연산자
- 힙 영역에 새로운 String 객체를 생성
String name1 = new String("가나다");
String name2 = new String("가나다");
(스택 영역에 name1, name2 변수 생성되고 힙 영역 String 객체의 각각 다른 번지를 가짐.)
- 문자열이 똑같아도 이 두 객체는 다르다. 문자열이 같을 뿐. (new로 새로운 String 객체를 만드니까)
String name1 = "쿠하";
String name2 = "쿠하";
String name3 = new String("쿠하");
name1 == name2 // true
name2 == name3 // false
ㅁ 문자열 비교
- 자바에서 문자열 비교할 때 == 연산자보다는 equals() 연산자를 사용함.
- '== 연산자'는 번지를 비교.
- 'equals() 연산자'는 문자열을 비교.
String str1 = new String("가나다");
String str2 = new String("가나다");
boolean result = str1.equals(str2); // true
boolean result = (str1 == str2); // false
ㅁ String으로 선언된 변수에 초기값으로 null을 대입할 수 있음.
- String 변수가 null이라면 참조하는 객체가 없음을 의미.
String hobby = null;
ㅁ 참조를 잃은 String 객체는 Garbage Collector를 통해 메모리에서 자동 제거
String hobby = "여행"; // 처음엔 문자열을 대입했다가 나중에 null을 대입.
hobby = null;
- 스택 영역의 hobby는, 처음엔 힙 영역의 여행이라는 문자열을 가진 String 객체를 참조하고 있었음.
그러나 null이 들어가서 hobby가 참조하던 번지가 없어짐.
힙 영역의 여행이라는 문자열을 가진 String 객체는 참조를 잃어버린 것.
- 자바는 힙 영역의 참조 없이 단독으로 생성되어 있는 객체를 쓰레기 객체라고 함.
왜냐면 참조가 있어야 이 객체를 찾아서 이용할 수 있기 때문.
- 자바에서는 Garbage Collector가 힙 영역에서 참조를 잃은 객체들을 수거해서 메모리에서 제거해버림.
그래서 자바는 개발자가 따로 메모리를 정리하지 않아도 Garbage Collector가 편리하게 메모리를 정리함.
- 고로 내가 만든 객체를 메모리에서 제거하고 싶으면 모든 참조를 끊으면 됨. (변수에 null을 대입하면 됨.)
자바는 따로 객체를 메모리에서 제거하는 코드 자체가 없음.
ㅁ 예제
(1)
String hobby = null;
System.out.println(hobby.length());
- NullPointerException 발생.
객체가 없는데 객체의 length라는 메서드를 쓰려고 해서.
(2)
String hobby = "null";
System.out.println(hobby.length()); // 4
Q1. 내가 length() 메소드를 만들지 않았는데 length() 메서드를 쓸 수 있는 이유?
A1. 자바에서 String 클래스는 자바 표준 라이브러리(java.lang 패키지)의 일부로, 이미 정의된 다양한 메서드를 제공합니다. length() 메서드도 그중 하나입니다. 자바에서 String 객체를 사용할 때 이 클래스에 포함된 모든 메서드를 사용할 수 있습니다.
Q2. 내가 new로 객체를 생성한게 아닌데도 length() 메서드를 쓸 수 있는 이유?
A2. 자바에서 String 클래스의 메서드는 new 연산자로 객체를 생성하지 않아도 사용할 수 있습니다.
이는 자바가 String 리터럴을 다루는 특별한 방식을 가지고 있기 때문입니다.
자바에서 문자열 리터럴(예: "hello")을 사용할 때, 자바는 이를 자동으로 String 객체로 취급합니다.
이는 자바가 문자열 리터럴을 효율적으로 처리하기 위해 내부적으로 문자열 상수 풀(constant pool)을 사용하기 때문입니다.
String 클래스의 모든 메서드는 문자열 리터럴과 new 연산자로 생성된 문자열 객체 모두에서 사용할 수 있습니다.
※ String 클래스의 length() 메서드는 다음과 같이 정의됩니다.
이는 자바 표준 라이브러리의 일부이므로 우리가 직접 작성할 필요가 없습니다.
public final class String {
// 여러 다른 메서드와 필드 정의...
public int length() {
return value.length;
}
// 여러 다른 메서드와 필드 정의...
}
length() 메서드는 String 객체 내부의 문자 배열(value)의 길이를 반환합니다.
여기서 value는 문자열의 실제 내용을 저장하는 배열입니다.
22강. 배열(1) - 배열 선언, 생성, 길이
ㅁ 배열은 많은 양의 데이터를 적은 코드로 처리할 수 있다.
데이터가 많을 수록 코드가 길어진다. 1000개, 2000개 ...
ㅁ 배열
- 데이터를 (메모리의) 연속된 공간에 나열하고 각 데이터에 인덱스(0부터 시작하는 번호)를 부여한 자료구조.
- 배열에는 같은 타입의 데이터만 저장할 수 있음.
- 한 번 생성된 배열은 길이를 늘리거나 줄일 수 없음.
ㅁ 배열 변수 선언
int[] intArray; int intArray[];
String[] strArray; String strArray[];
- 배열은 참조 타입이기 때문에 이 변수에는 배열의 번지가 저장됨.
- 참조할 배열 객체가 없는 경우에 배열 변수는 null 값으로 초기화가 가능함.
int[] intArray = null; // 위와 같이 초기화 없이 선언할 수도 있고, 이렇게 변수를 선언하고 null로 초기화도 가능.
ㅁ 배열 생성
- 배열 변수를 선언하고 이 변수에 배열의 주소를 저장하려면 배열을 생성해야 함.
배열을 생성하는 방법은 값 목록으로 생성하는 방법과, new 연산자를 이용해서 배열을 생성하는 방법이 있음.
타입[ ] 변수 = { 값0, 값1, 값2, ... };
int[] scores = new int[30]; // 배열이 생성되고 배열의 생성번지가 scores에 저장됨.
ㅁ 값 목록을 이용해서 배열 생성
(1) 배열 변수를 선언한 뒤에는 다른 실행문에서 값 목록으로 배열 생성 불가능.
타입[ ] 변수;
변수 = { 값0, 값1, 값2, ... }; // 컴파일 에러 (변수를 선언할 때 값의 목록을 줘야 함.)
- 자바는 { 값0, 값1, 값2, ... }; 이 값의 list를 가지고 힙 영역에 배열 객체를 만듦.
변수에는 배열의 번지가 들어감(참조함).
(2) 배열 변수를 미리 선언하고 값 목록을 나중에 주고 싶으면,
new 연산자를 사용하여 값 목록 지정
변수 = new 타입[ ] { 값0, 값1, 값2, ... };
String[] names = null; or String[] names;
names = new String[] { "가나다", "라마바", "사아자" }; // 변수부터 선언하고 나중에 배열 객체생성 후 대입.
- 보통 (2)와 같이 쓰는 경우는 별로 없지만,
다른 메소드에 배열의 주소값을 전달하는 경우엔 쓰임.
그럴 땐 값의 목록을 줄 수 없음. // 이미 선언된 변수에 나중에 값의 목록을 주는 것과 같다.
public static void main(String[] args) {
int[] scores;
int sum = add( new int[] {83, 87, 90} );
System.out.println(sum);
}
public static int add( int[] scores ) {
int sum = 0;
for(int i=0; i<3; i++)
sum += scores[i];
return sum;
}
ㅁ new 연산자로 배열 생성
- 타입[ ] 변수 = new 타입[길이];
- 타입[ ] 변수 = null;
변수 = new 타입[길이];
- new 연산자로 배열 처음 생성할 때 배열은 자동적으로 기본값으로 초기화 됨.
int 배열은 0으로, String 배열은 null로 초기화 됨.
ㅁ 예제
String[] arr = new String[3];
arr[0] = "1월"; arr[1] = "2월"; arr[2] = "3월";
for(int i=0; i<3, i++)
System.out.print(arr[i] + " "); // 1월 2월 3월
- 값을 주지 않고 그냥 출력하면 null null null 나옴.
ㅁ 예제2
int[] intArray = { 1, 2, 3 };
int num = intArray.length; // 3
Q. length를 내가 선언하지 않았는데 쓸 수 있는 이유?
A. 자바에서 배열은 객체이며, 모든 객체는 Object 클래스의 하위 클래스인 배열 클래스로부터 상속됩니다.
따라서 배열은 Object 클래스의 메소드를 상속받습니다. 그 중 하나가 length 속성(변수)입니다.
length 속성은 배열의 길이를 반환합니다. 따라서 배열을 선언할 때 값을 할당하면 해당 배열의 길이를 바로 구할 수 있습니다. 이 속성은 배열의 크기를 동적으로 추적하는 데 유용합니다. 그렇기 때문에 내장된 length 속성을 사용하여 배열의 길이를 얻을 수 있습니다. 별도로 메소드를 만들거나 선언할 필요가 없습니다.
23강. 배열(2) - 명령 라인 입력
ㅁ main() 메소드의 String[] args 매개변수
(1) 실행할 때 명령라인 매개값을 주지 않았을 경우 길이 0인 String 배열 생성 후 main() 메서드 호출.
System.out.println(args.length); // 0
(2) 실행할 때 명령라인 매개값을 주었을 경우
[JDK 11 이후 버전] java -p, -m 모듈명/패키지.클래스 문자열0 문자열1 문자열2 ... 문자열n-1
[JDK 8 이전 버전] java 패키지.클래스 문자열0 문자열1 문자열2 ... 문자열n-1
String[] args = { 문자열0 문자열1 문자열2 ... 문자열n-1 };
(main() 메서드 호출시 전달)
public static void main(String[] args) { ... }
- 이클립스에서 실행을 하면 그냥 클래스를 실행하는 명령어가 동작함. ( cmd의 "java -p, -m 모듈명/패키지.클래스"와 같다. )
이런 경우에 main() 메소드 호출시 이 매개값에는 String[] args = { }; 이런 String 배열이 생성되고 이 배열 객체가 대입됨.
실행할 때 매개값을 주지 않았기 때문에 이 String 배열은 길이가 0이다. (= 요소가 없는 빈 배열)
- 클래스를 실행할 때 뒤에 실행 매개값으로 문자열을 줄 수 있음.
이클립스에서 어떻게 실행 매개값을 주느냐,
run 버튼 옆에 Run Configurations..를 누르고
project와 Main class를 확인하고
옆의 Arguments 탭을 눌러서 Program arguments 칸에 입력하면 됨.
이때 공백(스페이스 바)이 실행 매개값을 구분하는 기호다.
ㅁ 예제
- 실행 매개값으로 "가나다", "라마바" 전달.
public static void main(String[] args) {
System.out.println(args.length); // 2
System.out.println(args[0]); // 가나다
System.out.println(args[1]); // 라마바
System.out.println(args[0]+args[1]); // 가나다라마바
}
- 실행 매개값으로 "30", "40" 전달.
public static void main(String[] args) {
if(args.length != 2) {
System.out.println("값의 수가 부적절합니다.");
System.exit(0);
}
String strNum1 = args[0];
String strNum2 = args[1];
int num1 = Integer.parseInt(strNum1); // 30
int num2 = Integer.parseInt(strNum2); // 40
int result = num1 + num2; // 70
System.out.println(result);
}
System.out.println(Integer.parseInt(args[0])); // 이렇게 바로 해도 됨.
System.out.println(Integer.parseInt(args[1]));
- System.exit은 자바 프로그램을 종료시킨다.
System.exit(0)은 정상 종료, System.exit(1)은 비정상 종료를 의미한다.
- return은 메소드나 함수의 실행을 종료하고, 호출자에게 제어를 반환하는 키워드이다.
- return 0은 주로 C/C++와 같은 언어에서 메인 함수(main function)가 정수 값을 반환하면서 프로그램을 종료할 때 사용됩니다. 자바에서는 return 키워드만 사용하며, main 메서드가 void 타입이므로 반환값이 없습니다.
- cmd에서 실행.
(패키지는 error 나서 일단 패키지 빼고)
javac f.java
java f // 값의 수가 부적절합니다.
java f 30 40
- cmd에서 실행2 (패키지)
컴파일할 때, javac C:\SelfStudyJava\kuiki\src\kuiki02\exam01\Example.java
이렇게 전체경로 지정해야 함.
실행할 때, java -cp C:\SelfStudyJava\kuiki\src kuiki02.exam01.Example 30 40 // 70
이렇게 전체경로와 -cp로 클래스패스까지 지정해줘야 함.
- 강의에서는 이클립스로 컴파일하고 cmd에서 실행.
[자바11] java -p. -m kuiki/kuiki02.exam01.Example 30 40 // 70
[자바8] java kuiki02.exam01.Example 30 40 // 70
24강. 배열(3) - 다차원 배열, 객체를 참조하는 배열
ㅁ 2차원 배열
- 행렬 구조라고 하지만, 실제로 자바에서 행렬구조를 가지는 것은 아니다.
int[][] scores = new int[2][3];
- 구현 방법: 1차원 배열[2]이 다시 1차원 배열[3]을 참조.
( 길이가 2인 1차원 배열이 다시 길이가 3인 1차원 배열을 참조. )
scores.length; // 2
scores[0].length; // 3
scores[1].length; // 3
스택 영역에 생기는 scores라는 변수는 힙 영역의 길이 2짜리 배열을 참조한다.
힙 영역의 길이 2짜리 배열은 각각 길이가 3인 1차원 배열을 또 참조한다.
- 자바는 1차원 배열을 연결해서 다차원 배열을 계단식 구조로 만들 수도 있다.
int[][] scores = new int[2][]; <- 행의 길이만 정하고 열은 비워 둠.
scores[0] = new int[2]; 0 1
scores[1] = new int[3]; 0 1 2
scores.length; // 2
scores[0].length; // 2
scores[1].length; // 3
- 값 목록을 이용한 2차원 배열 생성
타입[ ][ ] 변수 = { {값1, 값2, ...}, {값1, 값2, ...}, ... };
int[][] scores = { {95, 80}, {92, 96} };
int score1 = scores[0][0]; // 95
int score2 = scores[1][1]; // 96
25강. 배열(4) - 배열 복사, 향상된 for문
ㅁ 참조 타입 배열 // 기본 타입이 아니라
- 요소에 값(정수, 실수, 논리값)을 저장하지 않고, 객체의 번지를 가지고 있음.
String[] strArray = new String[3];
strArray[0] = "Java";
strArray[1] = "Java";
strArray[2] = new String("Java");
System.out.println( strArray[0] == strArray[1] ); // true. 자바에서 문자열 리터럴은 메모리를 절약하기 위해 문자열 상수 풀에 한번만 저장하고 이후엔 동일 객체를 참조함. 배열엔 번지수가 들어감.
( 자바에서는 문자열 리터럴이 같으면 동일한 String 객체를 공유함. )
strArray[0]과 strArray[1]의 번지수는 다르지만, 그 둘이 참조하고 있는 번지수는 같다.
( == 연산자는 두 참조 변수가 동일한 객체를 참조하는지를 확인합니다. )
System.out.println( strArray[0] == strArray[2] ); // false
System.out.println( strArray[0].equals( strArray[2] ) ); // true
ㅁ 배열 복사
(1) for문을 이용해서 요소 하나 하나를 복사
int[] sourceArray = {1, 2, 3, 4, 5};
int[] targetArray = new int[sourceArray.length];
for (int i = 0; i < sourceArray.length; i++) {
targetArray[i] = sourceArray[i];
}
(2) System.arraycopy()를 이용한 복사
int[] sourceArray = {1, 2, 3, 4, 5};
int[] targetArray = new int[sourceArray.length];
System.arraycopy(sourceArray, 0, targetArray, 0, sourceArray.length);
- 첫번째 매개값: 원본 배열
- 두번째 매개값: 원본 배열의 어느 부분부터 읽어올지.
- 세번째 매개값: 대상 배열
- 네번째 매개값: 대상 배열의 어느 부분부터 쓸 것인지.
- 다섯번째 매개값: 몇개를 복사할지.
- String 타입(참조 타입) 배열이므로 원본 배열에 실제로 저장되어 있는 것은 Sting 객체의 번지가 저장되어 있다.
이 것을 복사해서 새로운 배열로 만들게 되어도 원본 배열의 번지가 그대로 복사된다.
그래서 두 배열은 동일한 객체를 참조하게 된다.
원본 배열이 참조하고 있는 객체는 변함이 없고 단지 새로운 배열에 번지가 복사되어서 저장된 것 뿐이다.
(3) Arrays.copyOf() 메서드 사용
int[] sourceArray = {1, 2, 3, 4, 5};
int[] targetArray = Arrays.copyOf(sourceArray, sourceArray.length);
(4) Arrays.copyOfRange() 메서드 사용
int[] sourceArray = {1, 2, 3, 4, 5};
int[] targetArray = Arrays.copyOfRange(sourceArray, 0, sourceArray.length);
ㅁ 향상된 for 문
- 기존의 for문을 간결하게 만들어 배열이나 컬렉션을 좀 더 쉽게 처리.
- 반복 실행 위해 루프 카운터 변수나 증감식을 사용하지 않음. 초기화식, 조건식, 증감식 전부 없음.
(루프 카운터 변수: 반복문에서 사용되는 변수. int i )
26강. 열거 타입
ㅁ 열거 타입
- 데이터 중에는 몇 가지로 한정된 값만을 갖는 경우가 있다. ( 요일, 계절 )
이러한 한정된 값을 갖는 타입을 열거 타입이라고 한다. // 열거 상수 = 한정된 값 = 사전에 정의된 상수 집합.
- int형으로 선언된 변수는 정수값이면 뭐든지 가질 수 있기 대문에 한정된 값을 갖는다 볼 수 없다.
String형으로 선언된 변수에 대입할 수 있는 문자열에도 다양한 문자열이 올 수 있다.
- 열거 타입은 한정된 값만 저장할 수 있다.
Week형으로 선언된 변수에는 7개의 열거 상수만 대입할 수 있다.
ㅁ 열거 타입 선언
- 자바 표준 라이브러리에서는 java.time.DayOfWeek와 같은 열거 타입을 제공합니다.
(여기에 MONDAY ~ SUNDAY 있음. Week은 따로 정의한 거.)
- enum은 열거형(Enumeration)을 축약한 용어.
자바에서는 enum 키워드를 사용하여 열거형을 정의합니다.
열거형을 사용하면 프로그래머가 명시적으로 상수들을 정의하고, 이를 가독성있게 사용할 수 있습니다.
- 관례적으로 열거 상수는 전부 대문자로 작성한다.
- 이렇게 작성된 열거 타입을 프로그램에서 사용하면, 열거 타입은 메서드 영역에 올라가고 열거 상수는 힙 영역에 열거 객체로 생성되어 참조된다.
- MONDAY ~ SUNDAY가 힙 영역에 Week 객체 7개로 각각 생성이 되고, 그리고 열거 상수 이름들( MONDAY ~ SUNDAY)이 Week 객체에 들어가게 된다.
- 메서드 영역에 저장된 Week라는 바이트 코드 파일에서는 각각의 상수들이 해당 Week 객체를 참조함. (번지가 저장됨)
그래서 열거 타입을 참조 타입이라고 한다.
= Week라고 하는 열거 타입이 메서드 영역에 올라감. 여기서 열거 상수는 해당 열거 객체를 참조함.
MONDAY라는 상수에 MONDAY를 가지고 있는 Week 객체의 주소값이 들어감.
ㅁ 열거 타입 변수 선언
열거타입 변수;
Week today;
Week reservationDay;
ㅁ 선언한 열거 타입 변수에 열거 상수 저장
열거타입 변수 = 열거타입.열거상수;
Week today = Week.SUNDAY;
Week 타입 변수 today를 선언하고, 여기에 Week 타입이 가지고 있는 열거 상수인 SUNDAY를 대입.
today에는 SUNDAY를 갖고 있는 힙 영역의 Week 객체의 주소값이 복사됨.
today == Week.SUNDAY; // true
그래서 today가 참조하는 객체와 Week.SUNDAY 상수가 참조하는 객체는 같은 객체.
Week birthday = null;
Week가 참조 타입이므로 Week 타입 변수에 아직 객체 참조가 없다는 뜻에서 이와 같이 null로 초기화할 수 있다.
'혼자 공부하는 자바' 카테고리의 다른 글
혼자 공부하는 자바 (34강 ~ 39강) (0) | 2024.05.29 |
---|---|
혼자 공부하는 자바 (27강 ~ 33강) (0) | 2024.05.28 |
혼자 공부하는 자바 (13강 ~ 19강) (0) | 2024.05.24 |
혼자 공부하는 자바 (7강 ~ 12강) (0) | 2024.05.23 |
혼자 공부하는 자바 (1강 ~ 6강) (0) | 2024.05.23 |