언어/Java

참조 타입

O_oz 2023. 8. 21. 16:44
반응형

1. 데이터 타입 분류

    - 기본 타입 (원시타입 : primitive type) : 정수, 실수, 문자, 논리 리터럴

    - 참조 타입 (reference type) : 객체의 번지를 참조하는 타입 (배열, 열거, 클래스, 인터페이스)

    - 변수는 스택 영역에 생성되고 객체는 힙 영역에 생성됨

 

2. 메모리 사용 영역

JVM으로 바이트 코드 파일을 실행하면 JVM은 운영체제에서 할당받은 메모리 영역 (Runtime Data Area)을 메소드 영역, 힙 영역, JVM 스택 영역으로 구분해서 사용함

 

메소드 영역

    - 클래스들을 클래스 로더로 읽어 클래스별로 런타임 상수풀 (runtime constant pool), 필드 데이터, 메소드 데이터, 메소드 코드, 생성자 코드 등을 분류해서 저장

    - JVM 실행 시 생성되고 모든 스레드가 공유 가능

 

힙 영역

    - 객체와 배열이 생성되는 영역

    - 객체와 배열은 JVM 스택 영역의 변수나 다른 객체의 필드에서 참조함

    - 참조하는 변수나 필드가 없다면 JVM은 쓰레기 수집기 (Garbage Collector)를 실행시켜 자동으로 객체를 제거

 

JVM 스택 영역

    - 각 스레드마다 하나씩 존재 / 스레드가 시작될 때 할당 / 기본적으로 main 스레드 하나는 존재

    - 메소드를 호출할 때마다 프레임을 추가 (push)하고 메소드가 종료되면 해당 프레임을 제거 (pop)

    - 프레임 내부의 로컬 변수 스택에 기본 타입 변수나 참조 타입 변수가 추가 (push) 되거나 제거 (pop)됨

    - 추가되는 시점은 변수가 초기화 될 때

    - 변수는 선언된 블록 안에서만 스택에 존재하고 블록을 벗어나면 스택에서 제거됨

 

3. 참조 변수의 동등 비교 (==, !=)

    - 참조 타입 변수들 간의 ==, != 연산은 동일한 객체를 참조하는지 판단 = 주소 값 비교 = 동일 객체 참조

 

4. null, NullPointerException

null

    - 참조 타입 변수는 힙 영역의 객체를 참조하지 않는다는 뜻으로 null 값을 가질 수 있음

    - 초기화로도 사용 가능 = 스택 영역에 변수 생성

 

NullPointerException

    - 참조 타입 변수를 잘못 사용하면 발생되는 예외

    - null 값을 가진 참조 타입 변수를 사용하면 발생

 

5. String 타입

    - String 변수에 문자열을 저장하려면 큰 따옴표로 감싼 문자열 리터럴을 대입

    - 문자열 리터럴이 동일하다면 String 객체를 공유함

    - 참조 타입이므로 초기값으로 null 대입 가능

    - new 연산자 (객체 생성 연산자) : 힙 영역에 새로운 객체를 만들 때 사용

    - equals() 메소드 : 동일 객체와는 상관 없이 문자열만을 비교할 때 사용 / 원본 문자열과 매개값으로 주어진 비교 문자열이 동일한지 비교 한 후 true 또는 false 리턴

String str1 = "오즈";
String str2 = "오즈";
String str3 = new String("오즈");

str1 == str2		// true
str2 == str3		// false

boolean result = str1.equals(str3);	// true

 

6. 배열 타입

배열

    - 같은 타입의 많은 양의 데이터를 저장하고 각 데이터에 인덱스를 부여해 놓은 자료구조

    - 선언과 동시에 저장할 수 있는 데이터 타입이 결정됨

    - 한 번 생성된 배열은 길이를 늘리거나 줄일 수 없음

 

선언

타입[] 변수;

타입 변수[];

    - 위 처럼 두 방식으로 선언 가능

    - 대괄호 []는 배열 변수를 선언하는 기호로 사용

    - 참조 변수 / null 값으로 초기화 가능

    - 배열 변수는 배열 객체를 참조하는 상태에서 값을 저장하거나 읽어야 함 / 아닐시 NullPointerException 예외 발생

 

값 목록으로 배열 생성

String[] names = {"김오즈", "이오즈", "정오즈"};

String[] names = null;
names = {"김오즈", "이오즈", "정오즈"};					// 컴파일 에러
names = new String[] {"김오즈", "이오즈", "정오즈"};

int add(int[] scores) { ... }
int result = add({95,  85, 90});					// 컴파일 에러
int result = add(new int[] {95,  85, 90});

    - 중괄호 {}는 주어진 값들을 항목으로 가지는 배열 객체를 힙에 생성하고, 배열 객체의 번지를 리턴

    - 배열 변수를 이미 선언한 후에 다른 실행문에서 중괄호를 사용한 배열 생성 불가능

    - 배열 변수를 미리 선언한 후, 나중에 초기화해야 하는 상황에는 new 연산자를 사용해서 값 목록을 지정

    - 메소드의 매개값이 배열일 경우, 배열을 생성함과 동시에 매개값으로 사용하고자 할 때는 new 연산자 사용

 

 

new 연산자로 배열 생성

    - new 연산자로 향후 값들을 저장할 배열을 미리 생성 가능

타입[] 변수 = new 타입[길이];

타입[] 변수 = null;
변수 = new 타입[길이];

    - 길이는 배열이 저장할 수 있는 값의 수

    - new 연산자로 배열 생성하는 경우에는 배열 변수 선언 후에도 가능

분류 데이터 타입 초기값
기본 타입 (정수) byte[]
char[]
short[]
int[]
long[]
0
'\u0000'
0
0
0L
기본 타입 (실수) float[]
double[]
0.0F
0.0
기본 타입 (논리) boolean[] false
참조 타입 클래스[] null
인터페이스[] null

    - new 연산자로 배열 처음 생성할 경우, 배열은 자동적으로 기본값으로 초기화 됨

변수[인덱스] = 값;

    - 배열이 생성되고 나서 새로운 값을 저장하려면 대입 연산자 사용

 

배열 길이

    - 배열의 길이 : 배열에 저장할 수 있는 전체 항목 수

public class Example {
	public static void main (String[] args) {
    	int[] scores = {83, 90, 87};
        int sum = 0;
        
        for (int i = 0; i < scores.length; i++) {
        	sum += scores[i];
        }
        
        System.out.println("총합 : " + sum);
    }
}

    - length 필드는 읽기 전용 필드이기 때문에 값 변경 불가능

    - 배열의 인덱스를 초과하게 되면 ArrayIndexOutOfBoundsException 예외가 발생

 

커맨드 라인 입력

public static void main(String[] args) { ... }

    -  프로그램을 실행하면 String 배열 args를 먼저 생성하고 main() 메소드 호출시 매개값으로 전달

 

다차원 배열

int[][] arr1 = new int[2][3];

arr1.length			// 2
arr1[0].length		// 3
arr1[1].length		// 3

int[][] arr2 = new int[2][];
arr2[0] = new int[2];
arr2[1] = new int[3];

arr2.length			// 2
arr2[0].length		// 2
arr2[1].length		// 3

int[][] arr3 = {{10, 30}, {70, 90}};

<배열 생성 결과>

arr1
0 0 0
0 0 0
arr2
0 0 -
0 0 0
arr3
10 30
70 90

    - int[][] arr1 = new int[2][3]; 코드는 세 개의 배열 객체를 생성하는데, 배열 변수인 arr1은 길이가 2인 배열 객체를 참조하고 해당 배열 객체의 arr1[0]과 arr1[1]은 다시 길이가 3인 배열 객체를 각각 참조함

    - 자바는 일차원 배열이 서로 연결된 구조로 다차원 배열을 구현하기 때문에 수학 행렬 구조가 아닌 계단식 구조를 가질 수 있음

    - 배열 사용시 배열의 길이를 정확히 알고 사용해야 함

 

객체를 참조하는 배열

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

    - 참조 타입 배열은 각 항목에 객체의 번지를 가지고 있음

    - 상기한 코드는 1개의 배열 객체와 3개의 String 객체를 생성함

 

배열 복사

배열은 한 번 생성하면 크기를 변경할 수 없기 때문에 더 많은 저장 공간이 필요하다면 큰 배열을 새로 만들고 이전 배열의 항목 값들을 복사해야 함

얕은 복사 : 참조 타입 배열의 복사시, 새 배열의 항목이 이전 배열의 항목이 참조하는 객체와 동일

깊은 복사 : 참조하는 객체도 별도로 생성하는 것

for문을 사용한 복사

public class Example {
	public static void main(String[] args) {
    	int[] oldArr = {1, 2, 3};
        int[] newArr = new int[5];
        
        for (int i = 0; i < oldArr.length; i++) {
        	newArr[i] = oldArr[i];
        }
        
        for (int i = 0; i < newArr.length; i++) {
        	System.out.print(newArr[i] + ", ");		// 1, 2, 3, 0, 0, 
        }
    }
}

    - 복사되지 않은 항목은 기본 초기값으로 채워짐

 

System.arraycopy() 메소드를 사용한 복사

System.arraycopy(Object src, int srcPos, Object dest, int destPos, int length);

    - src : 원본 배열 / srcPos  : 원본 배열에서 복사할 항목의 시작 인덱스 / dest : 새 배열 / destPos : 새 배열에서 붙여넣을 시작 인덱스 / length : 복사 할 개수

 

향상된 for문

for (타입 변수 : 배열) {
	실행문;
}

    - 반복 실행을 위한 카운터 변수와 증감식을 사용하지 않음

    - 배열 및 컬렉션 항목의 개수만큼 반복하고 자동적으로 for문을 빠져나옴

    - 실행 순서 : 배열에서 가져올 값이 존재하는 지 평가 > 값이 존재한다면 해당 값을 변수에 저장 > 실행문 실행 > 배열에서 가져올 다음 값이 존재하는 지 평가

 

7. 열거 타입 (enumeration type)

한정된 값만을 갖는 데이터 타입

몇 개의 열거 상수 (enumeration constant) 중에서 하나의 상수를 저장하는 데이터 타입

 

선언

    - 순서 : 열거 타입 이름 정하기 > 열거 타입 이름으로 소스 파일 생성 (관례 : 첫 문자를 대문자, 나머지 소문자 / 여러 단어로 구성된다면 각 단어의 첫 문자는 대문자)

public enum Week {MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY}

    - public enum : 열거 타입을 선언하기 위한 키워드

    - 열거 타입 이름은 소스 파일명과 대소문자가 모두 일치 해야됨

    - 관례 : 열거 상수는 모두 대문자 / 여러 단어로 구성된다면 언더바 (_)로 연결

 

열거 타입 변수

Week today = Week.SUNDAY;

    - 열거 타입 변수에 열거 상수 저장 가능

    - 열거 타입도 참조 타입이기 때문에 null 값 저장 가능 / 열거 상수는 열거 객체로 생성됨 (상기 코드는 7개의 Week 객체로 생성됨)

 

열거 객체의 메소드

    - 모든 열거 타입은 컴파일 시 Enum 클래스를 상속하기 때문에 java.lang.Enum 클래스에 선언된 메소드를 사용 가능

    - name() 메소드 : 열거 객체가 가지고 있는 문자열을 리턴

    - ordinal() 메소드 : 0부터 시작해서 열거 객체들이 몇 번째 열거 객체인지 리턴

    - compareTO() 메소드 : 매개값으로 주어진 열거 객체를 기준으로 해당 열거 객체가 몇 번째에 위치하는지를 비교

    - valueOf() 메소드 : 매개값으로 주어지는 문자열과 동일한 문자열을 가지는 열거 객체를 리턴 / 외부로부터 문자열을 입력받아 열거 객체로 변환할 때 유용하게 사용

    - values() 메소드 : 열거 타입의 모든 열거 객체들을 배열로 만들어 리턴

public class Example {
	public static void main(String[] args) {
    	// name() 메소드
        Week today = Week.SUNDAY;
        String name = today.name();
        System.out.println(name);		// SUNDAY
        
        // ordinal() 메소드
        int ordinal = today.ordinal();
        System.out.println(ordinal);	// 6
        
        // compareTo() 메소드
        Week day1 = Week.MONDAY;
        Week day2 = Week.WEDNESDAY;
        int result1 = day1.compareTo(day2);
        int result2 = day2.compareTo(day1);
        System.out.println(result1);	// -2
        System.out.println(result2);	// 2
        
        // valueOf() 메소드
		if (args.length == 1) {
            Week weekDay = Week.valueOf(name);
            if (weekDay == Week.SATURDAY || weekDay == Week.SUNDAY) {
            	System.out.println("주말");
            } else {
            	System.out.println("평일");
            }
        }
        
        // values() 메소드
        Week[] days = Week.values();
        for (Week day : days) {
        	System.out.println(day);
        }
    }
}
반응형

'언어 > Java' 카테고리의 다른 글

접근 제한자  (0) 2023.08.23
클래스  (2) 2023.08.23
조건문과 반복문  (0) 2023.08.20
연산자  (0) 2023.08.20
변수와 타입  (0) 2023.08.18