※ 본문은 코드스테이츠에서 제공해준 학습자료를 공부하고 정리한 내용임을 알립니다.
기본 자료형
자료형 / 타입
자료형, 타입은 변수에 저장되는 값의 종류와 범위를 결정짓는 요소이다. 이는 얼만큼 메모리 공간을 쓸 것인지에 대한 선언이기도 하다.
자바의 자료형은 값을 참조하는 기본 타입(primitive type), 객체를 참조하는 참조 타입(reference type), 두가지의 데이터 타입을 가지고 있다.
기본 타입에는 int, float, char, Boolean과 같은 타입들이 있고, 참조 타입에는 String, 배열, enum, 클래스, 인터페이스와 같은 타입들이 있다.
정수 타입 (byte, short, int, long)
정수는 모두 4개의 타입이 있으며 저장할 수 있는 값의 범위가 서로 다르다. 예전에는 메모리의 용량이 넉넉하지 않았다. 그렇기에 필요에 따라 변수에 자료 범위를 변경해야 할 필요가 있었고 적은 메모리를 사용하는 short(2byte), 가장 많은 메모리를 사용하는 long(8byte), 중간 정도의 메모리를 사용하는 int(4byte)로 나누어 사용하게 되었다.
타입 | 메모리 | 범위 |
---|---|---|
byte | 1byte | -128 ~ 127 |
short | 2byte | -32,768 ~ 32,767 |
int | 4byte | -2,147,483,648 ~ 2,147,483,647 |
long | 8byte | -9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807 |
변수의 값이 자료형의 범위를 넘을 경우 '오버플로우', '언더플로우' 가 발생하기 때문에 필요에 따라 long과 같은 타입을 사용한다. 하지만 너무 남발하면 성능 이슈가 생길 수 있다.
실수 타입 (float, double)
- float 타입 : 4byte
- double 타입 : 8byte
논리 타입 (boolean)
논리값(true / false)을 저장할 수 있는 데이터 타입이다. 두 가지 상태 값을 저장할 필요성이 있을 경우에 사용되지만, 상태 값에 따라 조건문과 제어문의 실행 흐름을 변경하는 데 주로 사용된다.
char 타입
자바는 모든 문자를 유니코드로 처리한다. 유니코드는 세계 각국의 문자들을 코드값으로 매핑한 국제 표준 규학이고, 하나의 문자에 대해 하나의 코드값을 부여한다. 이에 자바는 하나의 유니코드를 저장하기 위해 2byte 크기인 char 타입을 제공한다.
char alphabet = 'A';
char hangeul = '가';
타입 변환
타입 변환이란 데이터 타입을 다른 데이터 타입으로 변환하는 것을 의미한다. 두 가지 종류가 있는데, 하나는 자동 타입 변환이고 다른 하나는 강제적 타입 변환이다.
자동 타입 변환
작은 크기를 가지는 자료형에서 큰 크기를 가지는 자료형으로 이동할 때 자동으로 형 변환을 시켜준다. 이 때 크기의 구분 기준은 메모리 크기이다.
강제 타입 변환
큰 자료형에서 작은 자료형으로는 자동 타입 변환을 할 수 없다. 그래서 큰 데이터 타입을 작은 데이터 타입으로 쪼개서 저장하는 것을 강제 타입 변환(casting)이라고 한다. 강제 타입 변환은 캐스팅 연산자 ()를 사용하고, 연산자 안에 들어가는 타입은 쪼개지는 단위를 의미한다.
int intValue = 1020304055;
byte byteValue = (byte) intValue;
참조 자료형
참조 타입은 객체의 주소를 참조하는 타입으로 String, 배열, 열거, 클래스 타입을 말한다.
기본 타입 변수와 참조 타입 변수의 차이점은 저장되는 값이 무엇이냐 이다. 기본 타입을 이용해서 선언된 변수는 실제 값을 변수에 저장하지만, 참조 타입으로 선언된 변수는 메모리의 주소를 값으로 가진다.
메모리 영역
JVM이 시작되면 운영체제에서 할당받은 메모리 영역을 세부 영역으로 나누어서 사용하게 된다.
Method 영역
메소드 영역에는 코드에서 사용되는 클래스들을 클래스 로더로 읽어 클래스 별로 런타임, 상수풀, 필드 데이터, 메소드 데이터, 메소드 코드, 생성자 코드 등을 분류해서 저장한다. 메소드 영역은 JVM이 시작할 때 생성되고 모든 스레드가 공유하는 영역이다.
Heap 영역
힙 영역은 객체와 배열이 생성되는 영역이다. 힙 영역에 생성된 객체와 배열은 JVM 스택 영역의 변수나 다른 객체의 필드에서 참조한다. 만약 참조하는 변수나 필드가 없다면, 연결고리가 없는 객체가 되기 때문에 쓰레기로 취급하고 Garbage Collector를 실행시켜 쓰레기 객체를 힙 영역에서 자동으로 제거한다.
JVM Stack 영역
이 영역은 각 스레드(프로세스 내 일종의 코드가 실행되는 흐름)마다 하나씩 존재하며 스레드가 시작될 때 할당된다. 자바 프로그램에서 추가적으로 스레드를 생성하지 않았다면 main 스레드만 존재하므로 JVM 스택도 하나다. JVM 스택은 메소드를 호출할 때마다 프레임을 추가(push)하고 메소드가 종료되면 해당 프레임을 제거(pop)하는 동작을 수행한다.
프레임 내부에는 로컬 변수 스택이 있다. 기본 타입 변수와 참조 타입 변수가 추가(push)되거나 제거(pop)된다. 변수가 이 영역에 생성되는 시점은 최초로 변수에 값이 저장될 때이다. 변수는 선언된 블록 안에서만 스택에 존재하고 블록을 벗어나면 스택에서 제거된다.
기본 타입 변수는 스택 영역에서 직접 값을 가지고 있지만, 참조 타입 변수는 값이 아니라 힙 영역이나 메소드 영역의 객체 주소를 가진다.
String 타입
기본적으로 String 타입은 큰따옴표("")로 감싸진 문자열의 타입이며, char의 배열이다.
대표적인 String 메소드
메소드 이름 | 설명 |
---|---|
char charAt(int index) | 해당 문자열의 특정 인덱스에 해당하는 문자 반환 |
int compareTo(String str) | 해당 문자열을 전달된 문자열과 사전 편찬 순으로 비교 |
String concat(String str) | 해당 문자열의 뒤에 전달된 문자열을 추가하여 새로운 문자 반환 |
String[] split(String regex) | 해당 문자열을 전달된 정규 표현식에 따라 나눠서 반환 |
indexOf(char char) / indexOf(String str) | 해당 문자열에서 특정 문자나 문자열이 처음 등장하는 위치의 인덱스 반환 |
String substring(int begin, int end) | 해당 문자열의 전달된 시작 인덱스부터 마지막 인덱스까지를 새로운 문자로 반환 |
length() | 해당 문자열의 길이 반환 |
Array 타입
변수에는 한 개의 데이터만 저장할 수 있지만, 더 많은 데이터를 저장하기 위한 효율적인 방법으로 배열이라는 타입을 사용한다. 배열도 객체이므로 힙 영역에 생성되고 배열 변수는 힙 영역의 배열 객체를 참조하게 된다. 참조할 배열 객체가 없다면 배열 변수는 null 값으로 초기화될 수 있다.
배열 생성 방법
- 값 목록으로 배열 생성
타입[] 변수 = {값0, 값1, 값2, 값3};
String[] names = {"고길동", "피카츄"}
- new 연산자로 배열 생성
타입[] 변수 = new 타입[길이];
int[] intArray = new int[5];
※ 배열 생성 후 대입 연산자로 새로운 값 저장하기
변수[인덱스] = 값;
int[] scores = new int[3];
scores[0] = 36;
scores[1] = 749;
scores[2] = 2;
객체를 참조하는 배열
기본 타입 배열은 각 항목에 직접 값을 가지고 있지만 참조 타입 배열은 각 항목에 객체의 힙 주소를 갖는다.
Enum 타입
데이터가 몇 가지로 한정된 값만 가질 경우, 열거 타입을 사용한다.
public enum MemberAuthority { ADMIN, GENERAL };
MemberAuthority me = MemberAuthority.ADMIN;
열거 타입 변수는 참조 타입이기 때문에 null 값을 저장할 수 있다.
열거 객체 메소드
리턴 타입 | 메소드(매개변수) | 설명 |
---|---|---|
String | name() | 열거 객체가 가지고 있는 문자열 리턴 |
int | ordinal() | 열거 객체의 순번을 리턴 |
int | compareTo(비교값) | 주어진 매개값과 비교해서 순번 차이를 리턴 |
열거 타입 | valueOf(String name) | 주어진 문자열의 열거 객체를 리턴 |
열거 배열 | values() | 모든 열거 객체들을 배열로 리턴 |
Boxing, Unboxing
Wrapper Class
프로그래밍을 하다 보면 기본 타입 데이터를 객체로 표현해야 하는 경우가 종종 있다. 이럴 때 기본 자료 타입을 객체로 다루기 위해서 사용하는 클래스들을 래퍼 클래스라고 한다. 이런 객체를 포장 객체라고도 하는데 그 이유는 기본 타입의 값을 내부에 두고 포장하기 때문이다. 래퍼 클래스로 감싸고 있는 기본 타입 값은 외부에서 변경할 수 없다. 만약 값을 변경하고 싶다면 새로운 포장 객체를 만들어야 한다.
래퍼 클래스는 java.lang 패키지에 포함되어 있는데, 다음과 같이 기본 타입에 대응되는 클래스들이 있다.
기본 타입 | 래퍼 클래스 |
---|---|
byte | Byte |
char | Character |
int | Integer |
float | Float |
double | Double |
boolean | Boolean |
long | Long |
short | Short |
객체 자료형
자바에서는 모든 것이 객체로 이루어져 있다고 해도 과언이 아니다. 기본 자료형을 제외한 다른 타입, 자료형들도 전부 객체로 만들어서 사용 가능하다. 참조 자료형인 String, Enum, Interface, Class도 객체 자료형에 속한다.
Boxing과 Unboxing
기본 타입의 값을 포장 객체로 만드는 과정을 박싱이라고 하고, 반대로 포장객체에서 기본 타입의 값을 얻어 내는 과정을 언박싱이라고 한다.
자동 Boxing과 Unboxing
직접 박싱, 언박싱을 하지 않아도 자동으로 박싱과 언박싱이 일어나는 경우가 있다. 자동 박싱은 포장 클래스 타입에 기본값이 대입될 경우에 발생한다.
Integer obj = 123; //자동 박싱
int 타입의 값을 Integer 클래스 변수에 대입하면 자동 박싱이 일어나서 Integer 객체가 생성된다.
Integer obj = new Integer(200);
int value = obj; //자동 언박싱
int value2 = obj + 100; //자동 언박싱
반면에 자동 언박싱은 기본 타입에 포장 객체가 대입될 경우에 발생한다.
Wrapper class 내부 값 비교
포장 객체는 내부의 값을 비교하기 위해 == 연산자와 != 연산자를 사용할 수 없다. 이 연산자는 내부의 값을 비교하는 것이 아니라, 포장객체의 주소를 비교하기 때문이다.
따라서 equals() 메소드로 내부 값을 비교하는 것이 좋다.
'JVM > Java' 카테고리의 다른 글
예외처리 (0) | 2021.06.26 |
---|---|
객체지향 프로그래밍 (0) | 2021.06.26 |
제어문 (0) | 2021.06.26 |
Java 소개 (0) | 2021.06.26 |
좋은 객체 지향의 5가지 원칙 SOLID (0) | 2021.03.16 |