티스토리 뷰
자바의 데이터 타입과 변수 그리고 배열에 대해 알아보겠습니다.
프리미티브(Primitive) 타입 종류와 값의 범위 그리고 기본값
Primitive(기본형) 타입의 종류에는 논리형(boolean), 문자형(char), 정수형(byte, short, int, long), 실수형(float, double) 총 8개의 값이 있다.
프리미티브 타입(Primitive Type)과 레퍼런스 타입(Reference Type)
프리미티브 타입(Primitive Type). 기본형 타입, 또는 원시 타입이라고 한다.
프리미티브 타입이란 정수, 실수, 문자, 논리, 리터럴 등의 실제 데이터 값을 저장하는 타입이다.
레퍼런스 타입(Reference Type). 참조 타입이라고도 한다.
레퍼런스 타입이란 객체(Object)의 번지를 참조(주소를 저장)하는 타입으로, 메모리 번지 값을 통해 객체를 참조하는 타입이다.
원시타입을 제외한 타입들(문자열, 배열, 열거, 클래스, 인터페이스)을 말한다.
Java에서 실제 객체는 힙(Heap) 영역에 저장되며 참조 타입 변수는 스택 영역에 실제 객체들의 주소를 저장하여, 객체를 사용할 때마다 참조 변수에 저장된 객체의 주소를 불러와 사용하는 방식이다.
리터럴(literal)
원래 12, 123, 3.14, 'A'와 같은 값들이 '상수'인데 프로그래밍에서는 상수를 '값을 한 번 저장하면 변경할 수 없는 저장공간' 으로 정의하였기 때문에 이와 구분하기 위해 상수를 다른 이름으로 불러야만 했다. 그래서 상수 대신 리터럴이라는 용어를 사용한다. 리터럴은 단지 우리가 기존에 알고 있던 '상수'의 다른 이름이다.
상수(constant) 값을 한번만 저장할 수 있는 공간
리터럴(literal) 그 자체로 값을 의미하는 것
변수 선언 및 초기화 방법
변수(variable)란? 하나의 값을 저장할 수 있는 저장공간
int x; // 정수(integer)를 저장하기 위한 변수 x를 선언
x = 5; // 변수 x에 5를 저장
x = 3; // 변수 x에 3을 저장. 기존 5의 값은 지워진다.
int x = 5; // 변수의 선언과 대입을 한줄로 작성 할 수도 있다.
int b = 10, c = 15 // 같은 타입의 경우 한 줄로 여러 값 선언이 가능하다.
변수 스코프와 라이프타임
💡 변수의 스코프
스코프(scope)는 영역이라는 뜻으로, 변수에 접근하거나 접근할 수 있는 유효 범위/영역을 말한다.
💡 변수의 라이프타임
변수가 메모리에 살아 있는 기간을 말한다.
[ 선언위치에 따른 변수의 종류 ]
class A {
int instanceValue; //인스턴스 변수
static int classValue; //클래스 변수(static, 공유 변수)
void method(){
int localValue = 0; //지역 변수
}
}
변수는 클래스 변수, 인스턴스 변수, 지역변수 모두 세 종류가 있다. 변수의 종류를 결정짓는 중요한 요소는 '변수의 선언 위치' 이므로 변수의 종류를 파악하기 위해서는 변수가 어느 영역에 선언되었는지를 확인하는 것이 중요하다. 멤버변수를 제외한 나머지 변수들은 모두 지역변수이며, 멤버변수 중 static이 붙은 것은 클래스 변수, 붙지 않은 것은 인스턴스 변수이다.
[ 클래스 변수(class variable ]
클래스 변수를 선언하는 방법은 인스턴스 변수 앞에 static을 붙이기만 하면 된다. 인스턴스마다 독립적인 저장공간을 갖는 인스턴스 변수와는 달리, 클래스 변수는 모든 인스턴스마다 독립적인 저장공간(변수)를 공유하게 된다. 한 클래스의 모든 인스턴스들이 공통적인 값을 유지해야하는 속성의 경우, 클래스 변수로 선언해야 한다.
클래스 변수는 인스턴스 변수와 달리 인스턴스를 생성하지 않고 언제라도 바로 사용할 수 있다는 특징이 있다.
스코프: 클래스 전체
라이프타임: 클래스가 초기화되고 프로그램이 종료될 때 까지
[ 인스턴스 변수(instance variable ]
클래스 영역에 선언되며, 인스턴스를 생성할 때 만들어진다. 그래서 인스턴스 변수의 값을 읽어 오거나 저장하려면 먼저 인스턴스를 생성해야한다. 인스턴스마다 별도의 저장공간을 가지므로 서로 다른 값을 가질 수 있다. 인스턴스마다 고유한 상태를 유지해야하는 속성의 경우, 인스턴스 변수로 선언한다.
스코프: static 블럭과 static 메서드를 제외한 클래스 전체
라이프타임: 객체가 생성되고 객체가 메모리에 살아있는 동안
[ 지역변수(local variable ]
메서드 내에 선언되어 메서드 내에서만 사용 가능하며, 메서드가 종료되면 소멸되어 사용할 수 없게 된다. for문 또는 while문의 블럭 내에 선언된 지역변수는 지역변수가 선언된 블럭{} 내에서만 사용 가능하며, 블럭{}을 벗어나면 소멸되어 사용할 수 없게 된다.
스코프: 변수가 선언된 블럭{} 내부
라이프타임: 변수 선언 이후 부터 블럭을 벗어날 때 까지
타입 변환, 캐스팅 그리고 타입 프로모션
서로 다른 타입간의 연산을 수행해야 하는 경우 연산을 수행하기 전 서로의 타입을 일치시켜야하는데. 변수나 리터럴의 타입을 다른 타입으로 변환하는 것을 타입변환(형변환) 이라 한다. 이 때 큰 범위에서 작은 범위로 변환 되는 것을 명시적 형변환 '캐스팅' 이라하며 작은 범위에서 큰 범위로 변환 되는 것을 자동 형변환 '프로모션' 이라 한다.
🚨 형변환 시 바이트 크기 보다는 '표현 가능한 값의 범위'를 고려하자.
1차 및 2차 배열 선언하기
[ 배열이란? ]
배열은 같은 타입의 여러 변수를 하나의 묶음으로 다루는 것
배열은 생성과 동시에 자동적으로 기본값으로 초기화되므로 배열을 사용하기 전에 따로 초기화를 해주지 않아도 된다.
크기 할당 & 초기화 없이 배열 참조변수만 선언
int[] arr;
int arr[];
선언과 동시에 배열 크기 할당
int[] arr = new int[5];
String[] arr = new String[5];
기존 배열의 참조 변수에 초기화 할당하기
int[] arr;
arr = new int[5]; // 5의 크기를 가지고 초기값 0으로 채워진 배열 생성
선언과 동시에 배열의 크기 지정 및 값 초기화
int[] arr = {1,2,3,4,5};
int[] arr = new int[] {1,2,3,4,5};
int[] odds = {1,3,5,7,9};
String[] weeks = {"월", "화", "수", "목", "금", "토", "일"};
[ 2차 배열 선언 ]
3의 크기의 배열을 4개 가질 수 있는 2차 배열 할당
int[][] arr = new int[4][3];
int[][] arr9 = {{1,2,3},{4,5,6},{7,8,9}};
기본타입(Primitive type)의 배열인 경우 초기값을 가지고 있는 반면(int = 0),
참조타입(Reference type)의 배열을 선언했을 경우 배열 내 엘리먼트의 초기값은 null이다.
타입 추론, var
타입추론이란 정적 타이핑을 지원하는 언어에서, 타입이 정해지지 않은 변수에 대해서 컴파일러가 변수의 타입을 스스로 찾아낼 수 있도록 하는 기능이다. 즉, 타입을 명시하지 않아도 되며, 코드량을 줄이고 코드의 가독성을 높일 수 있다는 뜻이다.
Java10부터 var 구문이 생기고 자바11 부터는 이를 통한 람다 타입 지원도 생겼다. 컴파일러는 개발자가 입력한 초기화 값을 통해 타입을 유추하는데 즉 var는 컴파일러가 타입을 유추할 수 있도록 반드시 데이터를 초기화 해야 한다.
🚨 타입 추론은 가독성을 높일 수 있는 경우와 그것을 사용한 것이 유용한 경우에만 선택적으로 사용해야 한다.
이 말의 의미는 편하게 코드를 작성하기 위해 var를 쓰는 것이 아니라, 가독성을 높이는 목적으로 사용해야 한다는 의미이다.
var의 유형을 개발자가 추적할 수 없거나 어려운 경우엔 var를 사용하지 않는 것이 좋다.
public static void main(String p[ args) {
String str = "Hello World";
}
public static void main(String[] args) {
var str2 = "Hello world";
if (str2 instanceof String) {
System.out.println("str2의 타입은 String입니다");
}
}
위 코드와 같이 str2 의 타입을 선언해 주지 않아도 컴파일러가 리터럴을 추론하고 타입을 유추해낸다.
참고
'Java' 카테고리의 다른 글
[Java] 오버라이딩(Overriding) (1) | 2022.08.24 |
---|---|
[Java] 자바는 왜 다중상속을 지원하지 않을까? (0) | 2022.08.24 |
[Java] 6.상속 (0) | 2022.08.24 |
[Java] 3. 연산자 (0) | 2022.08.06 |
[Java] 1. JVM은 무엇이며 자바 코드는 어떻게 실행하는 것인가 (4) | 2022.07.21 |