참조 타입
참조 타입
이란 객체의 번지를 참조하는 타입으로 배열, 열거, 클래스, 인터페이스 타입을 말한다
int age = 26; // 기본타입
String name = "youn"; // 참조타입
기본타입과 참조타입 둘 다 변수는 Stack영역에 생성된다
참조타입의 객체는 Heap영역에 생성된다
따라서 Stack영역에 생성된 참조타입의 변수는 Heap영역에 생성된 객체의 주소값을 갖는다
메모리 사용 영역
메소드 영역
- 클래스들을 클래스 로더로 읽어 클래스별로 런타임 상수 풀, 필드 데이터, 메소드 데이터, 메소드 코드, 생성자 코드 등 분류해서 저장한다
- 모든 쓰레드가 공유하는 영역이다
힙 영역
- 객체와 배열이 생성되는 영역이다
- 힙 영역의 객체와 배열은 JVM 스택 영역의 변수나 다른 객체의 필드에서 참조된다
- 만약 참조되는 변수나 필드가 없다면 쓰레기 객체로 보고 GC를 실행시켜 메모리에서 해제시킨다
스택 영역
- 각 쓰레드마다 하나씩 존재한다
- JVM 스택은 메소드를 호출할 때마다 Frame을 추가하고 메소드가 종료되면 해당 Frame을 제거하는 동작을 수행한다
참조 변수의 동등비교 연산
- 참조 타입 변수들간의 동등비교(==, !=) 연산은 주소값을 비교한다
var1 == var2 → true
var1 == var3 → false
var1 != var3 → true
null과 NullPointerException
- 참조 타입 변수가 null을 가지고 있을 경우, 참조할 객체의 주소값이 없는 것이므로 참조 타입 변수를 사용할 수 없다
String 타입
String 변수 = "문자열";
변수 = "문자열";
변수는 Stack영역에 문자열 객체의 주소값을 갖으면서 생성된다
주소값에 대한 String 객체는 Heap영역에 생성된다
String도 참조 타입이므로
String str1 = "Youn";
String str2 = "Youn";위처럼 선언된 경우
str1 == str2
와 같이 비교하게 되면 두 변수에 담겨있는 주소값을 비교하는 것이다변수가 갖는 문자열이 같은지 비교하고 싶다면
equals()
메소드를 이용해 비교해야한다str1.equals(str2);
배열 타입
- 배열은 같은 타입의 데이터를 연속된 공간에 나열시키고, 각 데이터에 인덱스(index)를 부여한 자료구조이다
- 각 인덱스는 각 항목의 데이터를 읽거나 저장하는데 사용된다
배열 선언
dataType[] varName;
dataType varName[];
dataType[] varName = new dataType[arraySize];
int[] intArray1;
int intArray2[];
int[] intArray3 = new int[5]; // 크기가 5인 int 타입을 갖는 배열을 생성
// 값 초기화
dataType[] varName = {val1, val2, val3, ...};
- 위와 같이 배열 항목에 저장될 값의 목록을 만들어 준다면 아래처럼 스택 영역과 힙 영역에 변수와 객체가 생성이 될 것이다
배열은 변수를 이미 선언한 후에는 중괄호를 사용해 배열 생성을 할 수 없다
varName = {val1, val2, val3, ...};
컴파일 에러 발생
배열 변수를 선언한 후에 목록을 넣어주려면 new 연산자를 이용해야한다
varName = new dataType[] {val1, val2, val3, ...};
배열 길이
- 배열 길이는 length 필드를 읽으면 되고 사용은
배열변수.length
와 같이 작성하여 사용하면 된다 - length 필드는 읽기 전용 필드이기 때문에 값의 변경을 할 수 없다
커맨드 라인 입력
- Java의 main 메소드를 보면
public static void main(String[] args) {...}
로 구성되어 잇다 - 여기서 String[] args는 커맨드 창에서
java 클래스명
으로 프로그램을 실행시키면 - JVM은 길이가 0인 배열을 먼저 생성하고 main() 메소드를 호출할 때 매개값으로 전달한다
- 만약
java 클래스명
뒤에 공백으로 구분된 문자열 목록을 주고 실행시키면 문자열 목록으로 구성된 String[] 배열이 생성되고 - main() 메소드를 호출할 때 매개변수 값으로 전달된다
다차원 배열
int[][] scores = new int[2][3];
과 같이 선언하면 2X3 행렬 구조를 갖는 다차원 배열이 생성된다int[][] scores = new int[2][];
scores[0] = new int[2];
scores[1] = new int[3];위와같이 각 행마다 열의 갯수가 다르게 선언할 수 있다
- Stack 영역에 생성된 변수는 배열 객체의 행 정보를 담고 있는 주소값을 바라보며
- Heap 영역의 배열 객체는 각 행의 인덱스마다 열 정보를 담고 잇는 주소값을 가리킨다
객체를 참조하는 배열
- 기본타입(byte, char, short, itn, long, float, double, boolean) 배열은 각 항목에 직접 값을 갖고 있지만
- 참조타입(클래스, 인터페이스) 배열은 각 항목에 객체의 주소값을 갖고 있다
String strArray = new String[3];
strArray[0] = "Java";
strArray[1] = "C++";
strArray[2] = "C#";
배열 복사
- 배열 간의 항목 값들을 복사하려면 for문을 사용하거나 System.arraycopy() 메소드를 사용하면 된다
- 여기서 arraycopy()메소드는
System.arraycopy(원복배열, 복사를 시작할 인덱스, 붙여넣을 새 배열, 붙여넣기 시작할 인덱스, 복사할 갯수)
얕은 복사(shallow copy)
- 배열 복사가 되면 복사되는 값이 객체의 주소값이므로 새 배열의 항목은 이전 배열의 항목이 참조하는 객체와 동일한 경우이다
- 주소값이 복사되므로 값이 변경되면 해당 주소를 참조하는 모든 배열들의 값이 변경된다
int[] arr1 = new int[2];
arr1[0] = 1;
arr1[1] = 2;
int[] arr2 = arr1;
arr2[0] = 3;
arr2[1] = 4;
System.out.println(arr1[0] + ", " + arr1[1]);
깊은 복사(deep copy)
- 참조하는 객체도 별도로 생성되는 것을 말한다
- 새로운 메모리 공간에 값을 복사하는 것이므로 한쪽 값을 수정해도 다른 배열에 영향을 끼치지 않는다
향상된 for문
for문의 증감식을 사용하지 않는 방식이다
배열에 가져올 값이 있는 경우, 타입 변수에 담아서 실행문으로 전달한다
가져올 항목이 없을 경우, 배열을 빠져나간다
for(타입 변수 : 배열) {
실행문;
}
열거 타입
한정된 값만을 갖는 데이터 타입이 열거 타입이다
열거타입을 선언하는 벙법은
public enum 열거타입변수명 {...}
으로 public enum 키워드가 열거 타입을 선언하기 위한 키워드이다public enum Week { MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY }
열거타입 변수는
열거타입 변수 = 열거타입.열거상수
를 사용하면 된다열거 객체의 메소드를 상용 할 수 있는 이유는 모든 열거 타입은 컴파일 시에 Enum 클래스를 상속하게 되어 있기 때문이다
name()
- 열거 객체가 갖고 잇는 문자열 리턴
ordinal()
- 전체 열거된 객체 중 몇번째 열거 객체인지 알려준다
compareTo()
- 매개 값으로 주어진 열거 객체를 기준으로 전후로 몇 번째 위치하는지 비교
enumVar1.compareTo(enumVar2);
로 비교하며 enumVar1과 enumVal2의 순번 차이를 계산하게 되고- enumVar1이 enumVar2보다 앞에 있는 경우 음수의 결과가
- enumVar1이 enumVar2보다 뒤에 있는 경우 양수의 결과를 얻을 수 있다
valueOf()
- 매개 밗으로 주어지는 문자열과 동일한 문자열을 가지는 열거 객체를 리턴
values()
- 열거 타입의 모든 열거 객체들을 배열로 만들어 리턴
Reference
이것이 자바다 - 신용권 지음
'Java' 카테고리의 다른 글
Java의 Class (0) | 2022.01.08 |
---|---|
Java에서 String이 메모리에 생성되는 과정의 이해 (0) | 2022.01.06 |
Java 조건문과 반복문 (0) | 2022.01.05 |
Java의 변수, 타입, 연산자 (0) | 2022.01.05 |
Java에 GC가 있지만 close() 메서드를 사용하는 이유 (0) | 2022.01.03 |