이 글은 백기선님의 라이브 스터디 참여 및 학습 내용 정리용으로 작성한 글입니다.
해당 데이터가 메모리에 어떻게 저장되는지, 해당 데이터가 프로그램에서 어떻게 처리 되어야 하는지를 명시적으로 정의하는 것이다. 자바에서 타입은 크게 기본형(Primitive Type) 타입과 참조형(Reference Type) 타입으로 분류된다.
자료형 | 키워드 | 크기 | 기본값 | 값의 범위 |
---|---|---|---|---|
논리형 | boolean | 1 Byte | false | true or false(0과 1이 아님) |
문자형 | char | 2 Byte | \u0000 | 0 ~ 65,535 |
정수형 | byte | 1 Byte | 0 | -128 ~ 127 |
short | 2 Byte | 0 | -32,768 ~ 32,767 | |
int | 4 Byte | 0 | -2,147,483,648 ~ 2,147,483,647 | |
long | 8 Byte | 0 | -9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807 | |
실수형 | float | 4 Byte | 0.0 | -3.4E38 ~ +3.4E38 |
double | 8 Byte | 0.0 | -1.7E308 ~ +1.7E308 |
소스 코드 내에 직접 입력된 값(데이터)
를 의미한다.(즉, 변수의 초기화 값)
상수는 값을 한 번 저장하면 변경할 수 없는 변수
를 뜻하므로 둘은 비슷해 보여도 의미하는 대상이 다르다.
정수 리터럴
정수 형태의 값으로 byte, char, short, int ,long의 정수 타입 기본 데이터 타입이 저장될 수 있다. 정수 리터럴은 기본적으로 int 형이며, long 타입을 표현하기 위해서 정수형 리터럴 값 마지막에 L
을 붙여준다.
// 정수형 숫자 33을 리터럴로 표현해보자
int decimal = 33; // 10진법
int octal = 041; // 8진법 (앞에 0을 붙여서 8진법이라는 것을 표현)
int hexadecimal = 0x21; // 16진법 (앞에 0x를 붙여 16진법임을 표현)
int binary = 0b100001; // 2진법 (앞에 0b를 붙여 2진법임을 표현)
실수 리터럴
실수형 리터럴은 기본적으로 double 타입이며, float 타입으로 표현하기 위해서는 실수 리터럴 값 마지막에f
를 붙여준다.
double a = 1.0; // 1.0
double b = 5E-1; // 0.5
float c = 0.7f; // float 타입의 0.7
문자 리터럴
문자는 작은 따옴표(')
안에 문자 값을 표현할 수 있다
char c = 'c'; // 문자 c
변수를 선언한다는 것은 어떤 자료형(타입)으로 특정한 값을 저장할 공간을 만드는 것이다.
초기화를 한다는 것은 해당 변수의 특정 값을 넣어주는 것을 의미한다. 이 변수 초기화를 하지 않는다면 해당 변수에는 쓰레기 값이 들어가게되는데 자바에서는 자료형의 default 값으로 들어가게된다.
int test = 10000; // 정수형 타입의 변수를 선언하였고 10000 이라는 값으로 초기화
위와 같이 변수의 선언과 동시에 값의 초기화를 코드 한 줄로 나타낸 것이다.
스코프란 사전적 의미로 '범위'를 뜻한다. 여기서 변수의 스코프란 무엇일까?
말 그대로 풀이하면 변수의 범위(영역), 변수는 범위(영역)을 가지고 있구나 라는것을 추측해 볼 수 있다. 자바에서는 변수에 접근할 수 있는 범위(영역)를 변수의 스코프라고 부른다.
변수의 스코프의 종류로는 Instance Variables, Class Variables, Local Variables 세 가지가 있다.
Instance Variables
Class Variables
Local Variables
public class Test {
int instanceVar; // Instance Variables
static int classVar; // Class Variables
// Instance Method
public void testFunction() {
int localVar = 0; // Local Variables
}
// Class Method
public staic printFunction() {
// System.out.println(instanceVar); <- 컴파일 에러 발생
System.out.println(classVar);
}
}
위 코드를 보며 Instance 와 Class 를 JVM과 연관지어 생각을 해보자.
먼저, 클래스 변수는 JVM의 클래스 로더를 통해 클래스 파일의 정보를 읽고 메모리의 Method
영역에 올라가게된다. 이때 클래스 변수의 정보가 담긴 Method
영역은 전체 공유가 가능한 영역이기 때문에 해당 클래스 내부에서 어느 영역에서든 사용이 가능한 것이다.
인스턴스 변수는 클래스의 생성자를 통해서 생성된 인스턴스들이 Heap
영역에 저장된다. 따라서 생성자를 통해 Heap
메모리에 할당되기 때문에 클래스 메소드에서 인스턴스 변수를 사용하려고 코딩을 하면 컴파일 에러가 발생하게 된다. 컴파일러는 해당 인스턴스 변수가 언제 메모리에 올라가게되는지 모르기 때문이다.
라이프 타임은 변수 데이터가 메모리에 올라가고 소멸되는 과정이라고 볼 수 있고, 더 이상 사용되지 않는 변수들은 JVM의 GC(Garbage Collector)에 의해서 메모리에서 정리된다. 위 변수의 스코프와 연관성이 있는데 변수의 스코프 종류별로 각각 생명주기가 다르다.
타입 변환이란 변수의 타입을 다른 타입으로 변환하는 것이다.
Type Casting (명시적 형변환)
자료형의 크기가 더 큰 타입에서 작은 크기의 자료형으로 타입을 바꾸는 과정을 말한다.
Type Promotion (묵시적 형변환)
자료형의 크기가 더 작은 타입에서 큰 타입의 자료형으로 대입을 할 때 자동으로 작은 타입의 자료형이 큰 타입으로 변환하는 과정을 말한다.
int a = 10;
short s = 1;
long m = 30L;
a = s; // 타입 프로모션
a = (int) m; // 타입 캐스팅
자바에서 1차, 2차 배열을 선언하는 방법은 다음과 같다
int size = 5;
// 1차 배열 선언 case
int[] arr1 = new int[]; // 크기 할당 없이 배열 참조변수만 선언
int[] arr2 = new int[size]; // 배열의 크기를 선언
int[] arr3 = new int[] {1, 2, 3}; // 배열의 크기 선언 및 값 초기화
int[] arr4 = {1, 5, 2, 3}; // 위와 동일하지만 다른 방식으로 선언
// 2차 배열 선언 case
int[][] arr10 = new int[size][size] // 2차원 배열의 각 크기 선언
// 배열의 크기 선언 및 값 초기화
int[][] arr11 = new int[][] {
{1, 3, 5},
{2, 0, 7}
};
먼저, 타입 추론이란 변수 선언시 타입이 선언되어 있지 않아도, 컴파일러가 해당 데이터의 타입을 유추하는 것을 말함. var
은 키워드 같이 보이지만 키워드가 아니다. 예로 변수 선언시 var로 네이밍이 가능하다. 이것이 가능한 이유는 컴파일러가 변수에 대입된 리터럴 값을 통해 추론을 하기 때문에 가능하다. 마지막으로 var
은 런타임 오버헤드가 없다. 이것이 무슨 이야기인가 하면 타입 추론은 컴파일 시점에서 변수의 리터럴 값을 보고 바이트코드로 변환 시 타입을 명시하고 해당 변수를 읽을 때 마다 타입을 알아내기 위한 연산을 하지 않는다. 따라서 var
변수는 코드 중간에 타입이 절대 변경되지 않는다.
Java 10 later 지원
자바 10버전 부터 var
를 통해 변수 선언을 하면 타입 추론이 가능해졌다. 단, 타입추론은 지역 변수이면서 선언과 동시에 초기화가 필수적이다.
타입추론의 특징을 정리해보자
//var a; <- 컴파일 에러 발생, 반드시 초기화가 필요하다
//var b = null; <- null 값 또한 올 수 없다
var test = 10; // 정수형
var test2 = new String[] {"A", "B"}; // 문자열 배열
//var test3 = {"A", "B"}; <- 컴파일 에러, 초기화를 해주긴 했으나 배열은 위와 같이 타입 명시가 필요