[Java] 05. 참조 타입

JK·2024년 4월 10일
0

[Java]

목록 보기
5/11

데이터 타입 분류

자바에서는 데이터 타입을 기본 타입(primitive type)참조 타입(reference type)으로 분류한다.

참조 타입객체(object)의 번지를 참조하는 타입으로, 배열, 열거, 클래스, 인터페이스 타입 등이 있다. 객체데이터(필드)와 메소드로 구성된 덩어리를 말한다.

기본 타입 변수와 참조 타입 변수의 차이점기본 타입은 값 자체를 저장하고, 참조 타입은 객체가 생성된 메모리 번지를 저장한다는 것이다. 변수들은 모두 스택이라는 메모리 영역에 생성되고, 객체는 힙 영역에 생성된다. 참조 변수는 해당 객체가 생성된 힙 영역의 메모리 번지를 저장하는 것이다.

메모리 사용 영역

JVM은 운영체제에서 할당받은 메모리 영역을 메소드 영역, 힙 영역, 스택 영역으로 구분해서 사용한다.

메소드 영역은 바이트코드 파일을 읽은 내용이 저장되는 영역으로, 클래스별로 상수, 정적 필드, 메소드 코드, 생성자 코드 등이 저장된다. 힙 영역객체가 생성되는 영역을 말한다. 스택 영역메소드를 호출할 때마다 생성되는 프레임이 저장되는 영역으로, 프레임 내부에는 로컬 변수 스택이 있고 메소드 호출이 끝나면 프레임은 자동으로 제거된다.


참조 타입 변수의 동등 비교 연산

기본 타입 변수의 동등 비교 연산자는 ==, !=이다. 하지만 ==, !=은 변수에 저장된 값 자체를 비교하는 연산자이기 때문에 참조 타입 변수에서 ==, != 연산자를 사용할 경우 객체의 번지를 비교하게 된다.

null과 NullPointerException

참조 타입 변수는 참조하고 있는 객체가 없다는 의미로 null 값을 가질 수 있다. null 값은 ==, != 연산자를 통해서도 확인할 수 있다.

예외(Exception)은 프로그램 실행 도중에 발생하는 오류를 말하는데, 그 중에서도 NullPointerException은 변수가 null인 상태에서 객체의 데이터나 메소드를 사용하려고 할 때 발생한다.

자바에서는 자체적으로 객체를 삭제할 수 있는 방법은 존재하지 않고, 객체를 없애는 유일한 방법은 객체의 모든 참조를 없애는 것이다. 즉, 해당 객체를 참조하고 있는 변수에 null 값을 대입하는 것이다. 이렇게 어떤 변수에서도 해당 객체를 참조하지 않아 사용할 수 없게 된 객체는 자바에서 쓰레기 수집기(Gabage Collector)를 사용하여 자동으로 제거한다.


문자열(String) 타입

자바에서 문자열은 String 객체로 생성된다. 자바는 문자열의 리터럴이 동일하다면 String 객체를 공유하기 때문에 문자열 리터럴로 String 객체를 생성한 경우 ==, != 연산자를 통해 비교할 수 있다. 하지만 new 연산자를 통해 새로운 객체를 생성한 경우, ==, != 연산자로는 객체의 번지가 다르기 때문에 비교할 수 없다. 이 경우에는 equals() 메소드를 사용하여 실제 문자열을 비교해야 한다.

char 문자변수 = 문자열변수.charAt(인덱스); 

문자열에서 특정 위치의 문자를 추출하는 방법charAt() 메소드를 사용하는 것이다. charAt() 메소드는 매개값으로 주어진 인덱스의 문자를 리턴한다. 리턴값이 char 타입이라는 것에 유의해야 한다.

int 문자열길이 = 문자열변수.length();

문자열에서 문자의 개수, 즉 문자열의 길이를 얻고 싶다면 length() 메소드를 사용해야 한다.

String 새로운문자열변수 = 기존문자열변수.replace(바꾸고 싶은 단어, 대체할 단어);

특정 문자열을 다른 문자열로 대체하고 싶은 경우에는 replace() 메소드를 사용하면 기존 문자열을 대체한 새로운 문자열을 얻을 수 있다. String 객체는 수정이 불가능하기 때문에, 기존 문자열은 그대로 두고, 대체한 새로운 문자열을 리턴한다.

문자열에서 특정 위치의 문자열을 잘라내어 가져오고 싶다면 substring() 메소드를 사용한다.

메소드설명
substring(int beginIndex)beginIndex에서 끝까지 잘라내기
substring(int beginIndex, int endIndex)beginIndex에서 endIndex 앞까지 잘라내기

특정 문자열의 위치를 찾고 싶으면 indexOf() 메소드를 사용한다. indexOf() 메소드는 주어진 문자열이 시작되는 인덱스를 리턴하고, 만약 없다면 -1을 리턴한다. 단순히 특정 문자열이 포함되어 있는지의 여부만 알고 싶다면 contains() 메소드를 사용한다.

만약 구분자와 함께 여러 문자열로 구성된 하나의 문자열이 있다면 split() 메소드를 사용하면 매개값으로 준 구분자를 기준으로 문자열을 여러 개로 분리할 수 있다.


배열(Array) 타입

변수는 하나의 값만 저장할 수 있기 때문에 여러 개의 많은 값을 저장하기 위해서는 많은 변수가 필요하다. 하지만 여러 개의 변수를 일일이 생성하여 관리하는 것은 비효율적이기 때문에 많은 양의 값을 효율적으로 다루기 위해서 배열을 사용한다. 배열은 연속된 공간에 값을 나열시키고, 각 값에 인덱스를 부여해 놓은 자료구조를 말한다. 인덱스는 대괄호 []와 함계 사용하여 각 항목의 값을 읽거나 저장하는 데에 사용한다.

배열의 특징

  1. 배열은 같은 타입의 값만 관리한다. 배열은 여러 개의 값을 저장할 수 있지만, 배열을 생성할 때 지정한 한 가지 타입의 값들만 관리할 수 있다.
  2. 배열은 생성과 동시에 길이가 결정되며, 결정된 길이는 늘리거나 줄일 수 없다.

배열 변수 선언

타입[] 변수;    // 주로 사용하는 방법
타입 변수[];

타입은 배열에 저장될 값들의 타입을 의미한다. 배열은 참조 변수이므로, 참조할 배열이 없다면 null로 초기화할 수 있다.

배열 생성

타입[] 변수 = { 값0, 값1, 값2, 값3, ... };

배열에 저장할 값의 목록을 중괄호 {}로 묶어 배열을 선언할 때 대입하면 중괄호 {}는 나열된 값들을 항목으로 가지는 배열을 생성하고 번지를 리턴한다. 단, 배열을 선언할 경우에만 위와 같이 배열을 생성할 수 있고, 배열 변수를 미리 선언한 후에는 위와 같이 값 목록을 배열 변수에 대입할 수 없다.

변수 = new 타입[] { 값0, 값1, 값2, 값3, ... };

배열 변수를 선언한 시점과 값 목록이 대입되는 시점이 다를 경우에는 위와 같이 new 타입[]을 중괄호 앞에 붙여 주어야 한다.

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

배열을 선언할 때, 값의 목록이 없어도 배열을 미리 생성해 둘 수 있다. new 연산자는 주어진 길이의 배열을 생성하고 배열의 번지를 리턴한다. new 연산자로 생성할 경우, 값이 주어지지 않았기 때문에 기본값으로 초기화된다. 기본값은 아래와 같다.

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

배열을 생성한 후 특정 인덱스의 항목을 새로운 값으로 변경하고 싶을 때는 변수에 대괄호[]를 이용하여 인덱스를 지정하고 값을 대입한다.

배열의 길이

배열의 길이란 배열에 저장할 수 있는 항목의 수를 말한다. 아래와 같이 해당 배열의 길이를 읽어올 수 있다.

배열변수.length;

배열의 길이를 읽어오는 것은 가능하지만, 변경하는 것은 불가능하다. 배열의 마지막 인덱스는 배열의 길이 -1이고, 배열의 인덱스를 초과하여 사용하려고 할 경우 ArrayIndexOutOfBoundsException이 발생한다.

다차원 배열

다차원 배열은 배열 항목에 또 다른 배열을 대입한 것으로, 배열이 관리하는 값이 배열인 경우를 말한다.

타입[][] 변수 = {
    {값1, 값2, ... },    // 1차원 배열의 0 인덱스
    {값3, 값4, ... },    // 1차원 배열의 1 인덱스
    ...
};

다차원 배열을 선언할 경우 차원의 수만큼 대괄호를 붙이고, 값 목록으로 다차원 배열을 생성할 경우 차원의 수만큼 중괄호를 중첩한다.

타입[][] 변수 = new 타입[1차원수][2차원수];

new 타입 연산자로 다차원 배열을 생성할 수도 있다. 이 경우 마찬가지로 차원의 수만큼 대괄호를 붙이고, 각 차원에 해당하는 배열의 길이를 지정한다.

다차원 배열에서 각 차원 마다 길이를 다르게 정하는 것도 가능하다. 이 경우 아래와 같이 각 차원에 들어갈 배열의 길이를 각각 선언한다.

타입[][] 변수 = new 타입[2][];
변수[0] = new 타입[2];    // 변수[0].length는 2가 됨
변수[1] = new 타입[3];    // 변수[1].length는 3이 됨

배열 복사

배열은 한 번 생성할 경우 길이를 변경할 수 없다. 따라서 더 많은 저장 공간이 필요할 경우 더 큰 길이의 배열을 생성한 후 기존 배열의 항목들을 복사해와야 한다.

배열을 복사하는 방법

  1. for 문을 사용하여 항목을 하나씩 읽어 새로운 배열에 저장한다.
  2. System.arraycopy() 메소드를 이용한다.
System.arraycopy(원본 배열, 원본 배열 복사 시작 인덱스, 새 배열, 새 배열 붙여넣기 시작 인덱스, 복사 항목 수);

향상된 for 문

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

배열 항목을 가져오기 위해 for 문을 사용할 때 향상된 for 문을 사용하는 것이 더 효율적이다. 향상된 for 문은 증감식을 사용하지 않고, 배열 항목의 개수만큼 반복하며 배열 항목을 하나씩 가져와 타입 변수에 저장한 뒤 배열이 끝나면 자동으로 for 문을 빠져나간다.


열거(Enum) 타입

열거(Enum) 타입은 몇 가지로 한정된 값을 갖는 타입으로, 사용 시 열거 타입의 이름으로 소스 파일(.java)을 생성한 후 한정된 값을 정의해야 한다. 열거 타입의 이름은 첫 문자를 대문자로 하고 캐멀 스타일로 작성하는 것이 관례이다.

public enum LoginResult {
    LOGIN_SUCCESS,
    LOGIN_FAILED
}

열거 상수는 열거 타입으로 사용할 수 있는 한정된 값으로, 모두 대문자 알파벳으로 작성하여 정의하며 여러 단어로 구성될 경우 언더바(_)로 연결하는 것이 관례이다. 열거 타입을 사용할 경우, 열거 타입도 데이터 타입이므로 변수를 선언한 뒤에 사용해야 한다.

LoginResult loginResult = LoginResult.LOGIN_SUCCESS;

열거 타입 변수에 열거 상수를 대입할 경우 위와 같이 '열거타입.열거상수' 형태로 작성한다. 열거 변수의 값이 특정 열거 상수인지 비교할 경우에는 ==, != 연산자를 사용한다.

Calendar

컴퓨터의 날짜 및 요일, 시간을 얻을 때 사용한다. 열거 타입 변수처럼 Calendar.YEAR, Calendar.MONTH와 같은 형태로 사용한다.


"한빛 미디어 출판 도서, 이것이 자바다"를 읽고 학습한 내용을 토대로 작성되었습니다.

0개의 댓글