5.1 데이터 타입 분류

2장에서 기본 타입 8가지에 대해 알아보았다.

이번엔 '참조 타입'에 대해 알아보자.

 

참조 타입 : 객체(Object)의 번지를 참조하는 타입

- 배열 타입

- 열거 타입

- 클래스 (String 포함)

- 인터페이스

 

객체 : 데이터(필드) + 메소드

(이해..)

객체 지향 프로그래밍이란?

 데이터를 추상화하여 프로그래밍하는 것..

 

// 기본 타입 변수  --> 직접 값을 변수에 저장한다
int age = 28;
doulbe pi = 3.141592;

// 참조 타입 변수  --> 변수의 값은 String 객체의 번지(주소)를 저장
String name = "홍길동";
String hobby = "여행";

참조 타입으로 선언된 변수는 객체가 생성된 메모리 번지를 저장한다.

 

★ 변수들은 모두 스택(Stack) 메모리 영역에 생성

 

★ 참조 타입 변수는 힙(Heap) 메모리 영역의 객체 번지(주소)를 저장.

→ 이 번지(주소)를 통해 객체를 참조한다. 

 

 

5.2 메모리 사용 영역

● 메소드 영역

바이트코드 파일을 읽은 내용이 저장되는 영역

 

● 힙 영역

객체가 생성되는 영역

 

● 스택 영역

메소드를 호출할 때마다 생성되는 프레임이 저장되는 영역.

메소드 호출이 끝나면 프레임은 자동으로 제거됨.

 

 

5.3 참조 타입 변수의 ==, != 연산

변수의 값이 같은지, 아닌지를 조사한다.

참조 타입 변수의 값은 객체의 번지(주소)이므로 번지(주소)를 비교하는 것이 된다.

주소가 같다면 동일한 객체를 참조한다는 것

 

예시)

int[] arr1;
int[] arr2;
int[] arr3;

arr1 = new int[] {1,2,3};
arr2 = new int[] {1,2,3};
arr3 = arr2;

System.out.println(arr1 == arr2);  // new 연산자에 의해 새로운 객체 번지 할당. 따라서 false
System.out.println(arr2 == arr3);  // arr3에 arr2의 주소값을 대입했기 때문에 같은 객체를 참조. true

 

 

5.4 null과 NullPointerException

● 참조 타입 변수는 아직 번지를 저장하고 있지 않다는 뜻으로 null 값을 가질 수 있다.

null도 초기값으로 사용할 수 있기 때문에 null로 초기화된 참조 변수는 스택 영역에 생성됨.

→ 힙 메모리에 객체가 생성되지 않은 상태.

(질문) new 연산자를 사용하지 않은 클래스는 객체가 생성되지 않는다??

→ new 연산자를 사용하지 않으면 객체가 만들어지지 않는다!! (String 제외..)

 

자바는 프로그램 실행 도중 발생하는 오류예외(Exception)라고 부른다.

참조 변수를 사용하면서 가장 많이 발생하는 예외 중 하나가 NullPointerException.

int[] intArray = null;
intArray[0] = 10;  // NullPointerException

String str = null;
System.out.println(str.length());  // NullPointerException

→ 각각의 참조 변수는 참조하는 객체가 없으므로 예외를 발생 시킨다.

→ 이러한 경우 null 상태의 참조 변수가 사용되고 있음을 알아야 한다.

 

경우에 따라서 참조 타입 변수에 일부러 null을 대입하기도 함.

어떤 변수에서도 객체를 참조하지 않는 경우 힙 메모리만 차지하는 꼴.

→ 자바는 가비지 컬렉터(Garbage Collector)로 쓰레기 객체를 자동으로 제거한다.

 

 

5.5 문자열(String) 타입

자바의 문자열은 String 객체로 생성됨.

String 변수에 문자열 리터럴을 대입하면 객체가 생성되고, 객체의 번지가 각각 대입된다.

(new 연산자를 사용하지 않아도 객체가 생성되는 String!!)

 

● 문자열 비교

자바는 문자열 리터럴이 동일하다면 String객체를 공유하도록 설계되어 있음

String name1 = "홍길동";
String name2 = "홍길동";

→ name1과 name2는 같은 번지를 참조한다!!

 

String name1 = new String("홍길동");
String name2 = new String("홍길동");

→ 이 경우에는 new 연산자를 사용하여 객체를 생성했기 때문에 서로 다른 String객체 번지를 가진다.

 

그렇기 때문에 문자열 리터럴로 생성하느냐, new 연산자로 생성하느냐에 따라 비교 연산자의 결과가 달라질 수 있음.

 

※ 내부 문자열만을 비교할 경우, String 객체의 equals() 메소드를 사용!

 

● 문자 추출 : charAt() 메소드

문자열에서 특정 위치의 문자를 얻고 싶을 때

String subject = "자바 프로그래밍";
char charValue = subject.charAt(3);  // 3번째 인덱스 "프"를 추출한다.

 

 

● 문자열 길이 : length() 메소드

String subject = "자바 프로그래밍";
int length = subject.length();  // subject 변수의 문자열 길이 "8"을 length에 저장

 

 

● 문자열 대체 : replace() 메소드

String 객체의 문자열은 변경이 불가한 특성을 갖기 때문에

replace() 메소드가 리턴하는 문자열은 원래 문자열의 수정본이 아니라 완전히 새로운 문자열이다.

String oldStr = "자바 프로그래밍";
String newStr = oldStr.replace("자바", "JAVA");

→ newStr은 "JAVA 프로그래밍" 이 된다.

 

● 문자열 잘라내기 : substring() 메소드

substring(시작인덱스); // 시작 인덱스부터 끝까지 잘라내기
substring(시작인덱스, 끝인덱스);  // 시작 인덱스부터 지정한 끝인덱스 전까지 잘라내기
String ssn = "911203-1234567";
String n1 = ssn.substring(0,6);
String n2 = ssn.substring(7);

n1은 "911203" 문자열을 참조

n2는 "1234567" 문자열을 참조

 

● 문자열 찾기 : indexOf() 메소드, contains() 메소드

특정 문자열의 위치를 찾고자 할 때 사용.

String subject = "자바 프로그래밍";
int index = subject.indexOf("프로그래밍");

index 변수에는 3이 저장됨.  subject 문자열에서 "프로그래밍"문자열의 시작 인덱스 위치가 3번이기 때문

주어진 문자열이 포함되어 있지 않을 경우 -1을 리턴 → if 조건식을 활용할 수 있음.

 

boolean result = subject.contains("프로그래밍");

→ 원하는 문자열이 포함되어 있으면 true를 리턴, 그렇지 않으면 false를 리턴

 

● 문자열 분리 : split() 메소드

문자열이 구분자를 사용하여 여러 개의 문자열로 구성되어 있을 경우,

이를 따로 분리해서 얻고 싶을 때 split() 메소드를 사용한다.

String board = "번호,제목,내용,성명";
String[] arr = board.split(",");

arr[0]  → "번호"

arr[1] →  "제목"

arr[2] → "내용" 

arr[3] → "성명"

 

 

5.6 배열(Array) 타입

저장할 값의 수가 많을 때, 많은 양의 값을 효율적으로 다루는 방법.

연속된 공간에 값을 나열시키고, 각 값을 인덱스(index)를 부여해 놓은 자료구조

 

● 선언 방법

타입[] 변수;  // 이렇게만 선언하면 배열타입은 기본타입 : 0 또는 참조타입 : null로 초기화
타입[] 변수 = { 값0, 값1, 값2, ... };  // 값 목록으로 배열 생성
타입[] 변수 = new 타입[길이];  // new 연산자로 배열 생성 (길이 지정 가능)

◎ 배열은 같은 타입의 값만 관리

◎ 배열의 길이는 늘리거나 줄일 수 없다. (생성과 동시에 길이가 결정됨)

 

 

5.7 다차원 배열

배열은 2차원, 3차원 등 다차원 배열을 만들 수 있다.

// 값 목록으로 다차원 배열 생성
타입[][] 변수 = {
	{ 값1, 값2, ... },
    { 값3, 값4, ... },
    ...
};

// new 연산자로 다차원 배열 생성
타입[][] 변수 = new 타입[1차원수][2차원수];

// 서로 길이를 다르게 할 수도 있다.
int[][] scores = new int[2][3];

// 또 다르게 길이를 설정하는 방법
int[][] scores = new int[2][];
scores[0] = new int[3];
scores[1] = new int[2];

 

 

5.8 객체를 참조하는 배열

기본 타입 배열은 각 항목에 값을 직접 저장 (byte, char, short, int, long, float, double, boolean)

참조 타입(클래스, 인터페이스) 배열은 각 항목에 객체의 번지를 저장

String[] strArray = new String[3];
strArray[0] = "Java";
strArray[1] = "C++";
strArray[2] = "C#";

String[ ] 배열의 항목은 String 변수와 동일하게 참조 타입 변수로 취급된다.

 

★ ==, != 연산자를 사용하면 배열 항목이 참조하는 객체가 같은 객체인지 다른 객체인지를 확인할 수 있고,

문자열만 비교할 때는 equals( ) 메소드를 사용한다.

 

★ String은 리터럴 문자열이 같으면 동일한 번지에 저장된다.

하지만 new 연산자로 생성된 String 객체는 다른 번지에 저장된다.

String[] strArray = new String[3];
strArray[0] = "홍길동";
strArray[1] = "홍길동";
strArray[2] = new String("홍길동");

System.out.println( strArray[0] == strArray[1] );  // true -> 같은 객체를 참조
System.out.println( strArray[0] == strArray[2] );  // false -> 다른 객체를 참조
System.out.println( strArray[0].equals(strArray[2]) );  // true -> 문자열이 동일

 

 

5.9 배열 복사

배열은 한 번 생성하면 길이를 변경할 수 없다.

더 많은 저장 공간이 필요하다면 더 큰 길이의 배열을 새로 만들고 이전 배열로부터 항목들을 복사해야 한다.

 

1) for 문을 이용

// 길이 3인 배열
int[] oldIntArray = {1, 2, 3};
// 길이 5인 배열을 새로 생성
int[] newIntArray = new int[5];
// 배열 항목 복사
for(int i=0; i<oldIntArray.length; i++) {
	newIntArray[i] = oldIntArray[i];
}
// 배열 항목 출력
for (int i = 0; i < newIntArray.length; i++) {
    System.out.print(newIntArray[i] + ", ");
}

 

2) System의 arraycopy( ) 메소드 이용

System.arraycopy(원본 배열, 원본 배열 복사 시작 인덱스,
				새로운 배열, 새로운 배열 붙여넣기 시작 인덱스, 복사 항목의 수);
// 길이 3인 배열
int[] oldIntArray = {1, 2, 3};
// 길이 5인 배열을 새로 생성
int[] newIntArray = new int[5];
// 배열 항목 복사
System.arraycopy(oldIntArray, 0, newIntArray, 0, oldIntArray.length);
// 배열 항목 출력
for (int i = 0; i < newIntArray.length; i++) {
    System.out.print(newIntArray[i] + ", ");
}

 

위의 코드 예시에서 newStrArray 변수가 참조하는 배열의 항목 초기값은 null이므로 복사되지 않은 3번 인덱스와 4번 인덱스 항목은 null을 유지하고 있다.

그리고 항목의 값이 String 객체의 번지이므로 번지 복사가 되어 참조하는 String 객체는 변함이 없다.

얕은 복사(shallow copy) : 참조하는 객체가 동일한 복사 (객체 번지 값만 복사)

깊은 복사(deep copy) : 참조하는 객체를 별도로 생성하는 복사 (새로운 객체를 따로 생성)

 

 

5.10 배열 항목 반복을 위한 향상된 for 문

자바는 배열컬렉션을 좀 더 쉽게 처리할 목적으로 향상된 for 문을 제공

 

 

5.11 main( ) 메소드의 String[ ] 매개변수 용도

자바 프로그램을 실행하기 위해 지금까지 main( ) 메소드를 작성했다.

여기서 문자열 배열 형태인 String[ ] args 매개변수가 왜 필요한지 알아보자.

 

윈도우의 명령 프롬프트(또는 파워쉘)나 맥 OS, 리눅스의 터미널에서 프로그램을 실행할 때는 요구하는 값이 있을 수 있다.
예를 들어 두 수를 입력받고 덧셈을 수행하는 Sum 프로그램은 실행할 때 다음과 같이 두 수를 요구할 수 있다.

java sum 10 20

공백으로 구분된 10과 20은 문자열로 취급 (키보드로 입력되는 모든 입력 값)

이 값을 main( ) 메소드 호출 시 매개값으로 전달된다.

main( ) 메소드 중괄호 내에서 문자열 "10"과 "20"은 다음과 같이 얻을 수 있다.

String x = args[0];
String y = args[1];

매개값이 몇 개 입력되었는지 확인하려면?

args.length;

 

 

 

5.9 열거(Enum) 타입

데이터 중 몇가지는 한정된 값(고유값)을 갖는 경우가 있다. (요일, 계절 등)

이런 한정된 값을 갖는 타입을 열거 타입(enumeration type)이라고 한다.

 

○ 열거 타입 이름으로 소스파일(.java)을 생성하고 한정된 값을 코드로 정의

○ 첫 문자를 대문자로 하고 캐멀 스타일로 작성하는 것이 관례

Week.java
MemberGrade.java
ProductKind.java

 

Enum 파일로 생성한다.

public enum Week {  // 열거 타입 이름
    MONDAY,  // 열거 상수 목록(한정된 값 목록)
    TUESDAY,
    WEDNESDAY,
    THURSDAY,
    FRIDAY,
    SATURDAY,
    SUNDAY
}

열거 상수는 열거 타입으로 사용할 수 있는 한정된 값.

관례적으로 알파벳으로 정의하며 모두 대문자로 작성

열거 상수가 여러 단어로 구성될 경우엔 언더바(_)로 연결하는 것이 관례

public enum LoginResult {
    LOGIN_SUCCESS,
    LOGIN_FAILED
}

 

열거 타입도 하나의 데이터 타입이므로 변수를 선언하고 사용해야 한다.

Week today;
Week reservationDay;

 

예시 코드르 보며 이해하자.

Week today = Week.SATURDAY;

if(today == Week.SATURDAY) {
    System.out.println("즐거운 토요일입니다.");
} else {
    System.out.println("토요일이 아닙니다.");
}

// 나중에 배울 것 // 클래스, 인스턴스
Calendar now = Calendar.getInstance();
int year = now.get(Calendar.YEAR);
int month = now.get(Calendar.MONTH) + 1;
int day = now.get(Calendar.DAY_OF_MONTH);
int week = now.get(Calendar.DAY_OF_WEEK); // 일요일부터 1로 시작
int hour = now.get(Calendar.HOUR);
int minute = now.get(Calendar.MINUTE);
int second = now.get(Calendar.SECOND);

switch(week) {
case 1: 
    today = Week.SUNDAY; 
    break;
case 2: 
    today = Week.MONDAY; 
    break;
case 3: 
    today = Week.TUESDAY; 
    break;
case 4: 
    today = Week.WEDNESDAY; 
    break;
case 5: 
    today = Week.THURSDAY; 
    break;
case 6: 
    today = Week.FRIDAY; 
    break;
case 7: 
    today = Week.SATURDAY; 
    break;
}

if(today == Week.SUNDAY) {
    System.out.println("일요일에는 자바 공부를 합니다.");
} else {
    System.out.println("열심히 자바 공부를 합니다.");
}

'JAVA' 카테고리의 다른 글

17일차 2024 - 3 - 20  (0) 2024.03.20
16일차 2024 - 3 - 19  (0) 2024.03.19
4일차 2024 - 2 - 29  (0) 2024.03.18
15일차 2024 - 3 - 18  (0) 2024.03.18
11일차 2024 - 3 - 12  (0) 2024.03.17

+ Recent posts