본문 바로가기
java-liveStudy

2주차 과제. 자바의 프리미티브 타입, 변수 그리고 배열

by 에드박 2020. 11. 21.

학습할 것


  • 프리미티브 타입 종류와 값의 범위 그리고 기본 값
  • 프리미티브 타입과 레퍼런스 타입
  • 리터럴
  • 변수 선언 및 초기화하는 방법
  • 변수의 스코프와 라이프타임
  • 타입 변환, 캐스팅 그리고 타입 프로모션
  • 1차 및 2차 배열 선언하기
  • 타입 추론, var

 

1. 프리미티브 타입 종류와 값의 범위 그리고 기본 값


프리미티브 타입(기본형)은 논리형(boolean), 문자형(char), 정수형(byte, short, int, long), 실수형(float, double) 모두 8개의 타입이 있습니다. 계산을 위한 실제 값을 저장합니다.

 

자바는 C언어와 달리 참조형 변수간의 연산을 할 수 없으므로 실제 연산에 사용되는것은 모두 기본형 변수입니다.

 

기본형 크기 저장 가능한 범위 기본값
bit byte
boolean 8 1 false, true false
char 16 2 '\u0000' ~ '\uffff' (0 ~ 65535) '\u0000'
byte 8 1 -128 ~ 127 0
short 16 2 -32,768 ~ 32767 0
int 32 4 -2,147,483,648 ~ 2,147,483,647 0
long 64 8 -9,223,372,036,854,775,828 ~ 9,223,372,036,854,775,807 0L
float 32 4 1.4E-45 ~ 3.4E38 (1.4 x 10^-45 ~ 3.4 x 10^38) 0F
double 64 8 4.9E-324 ~ 1.8E308 (4.9 x 10^-324 ~ 1.8 x 10^308) 0

 

논리형은 true와 false 두 가지의 값만 표현하면 돼서 1bit 만으로 충분합니다. 하지만 최소단위가 1byte 이기 때문에 boolean의 크기는 1byte입니다.

문자형에는 char 한가지만 있으며 단 하나의 문자만 저장이 가능합니다.

 

char ch = 'A';
// char ch = 65

 

위의 문장은 변수에 A문자가 저장되는것 같지만 실제로는 문자의 유니코드 즉, 정수가 저장됩니다. 컴퓨터가 숫자밖에 모르기 때문에 유니코드를 기준으로 문자를 정수로 변환하여(인코딩) 저장하고, 문자를 읽어올 때는 정수를 문자로 변환합니다.(디코딩)

 

  크기 저장 가능한 범위 기본값
bit byte
boolean 8 1 false, true false
char 16 2 '\u0000' ~ '\uffff' (0 ~ 65535) '\u0000'

 

 

정수형은 변수에 저장하면 2진수로 바뀌어 다음과 같은 형식으로 저장됩니다.

 

첫번째 비트는 부호표현을 의미합니다. (0이면 양수, 1이면 음수)

n은 타입의 크기를 의미하며 단위는 bit입니다.

따라서 부호를 표현하는 첫번째 비트를 제외한 n-1개의 비트를 가지고 숫자를 표현합니다. 양의 정수는 0을 포함하기 때문에 최대값에서 1을 빼야합니다. 정수의 표현 범위는 2^(n-1) ~ 2^(n-1) -1 입니다.

 

정수형 크기 저장 가능한 범위 기본값
bit byte
byte 8 1 -128 ~ 127 0
short 16 2 -32,768 ~ 32767 0
int 32 4 -2,147,483,648 ~ 2,147,483,647 0
long 64 8 -9,223,372,036,854,775,828 ~ 9,223,372,036,854,775,807 0L

 

실수형은 같은 크기라도 정수형보다 저장 가능한 범위가 훨씬 큰데 이는 실수형의 값을 저장하는 형식이 부호, 지수, 가수로 되어있어서 그렇습니다. 하지만 실수형은 오차가 발생할 수 있다는 단점이 있습니다. 따라서 실수형에서는 표현할 수 있는 값의 범위 뿐만아니라 '정밀도'도 중요한 요소입니다. 

 

 

실수형 크기 저장 가능한 범위 기본값
bit byte
float 32 4 1.4E-45 ~ 3.4E38 (1.4 x 10^-45 ~ 3.4 x 10^38) 0F
double 64 8 4.9E-324 ~ 1.8E308 (4.9 x 10^-324 ~ 1.8 x 10^308) 0

 

2. 프리미티브 타입과 레퍼런스 타입


프리미티브 타입(기본형)은 앞서 살펴본 논리형(boolean), 문자형(char), 정수형(byte, short, int, long), 실수형(float, double) 모두 8개 입니다.

레퍼런스 타입은 class, interface, enum, array 기본형을 제외한 나머지 타입을 의미합니다.

프리미티브 타입은 크기가 정해져있고 실제 값을 저장하는 반면, 레퍼런스 타입은 크기가 정해져있지 않고 값이 저장되어 있는 주소를 값으로 가집니다.

 

 

위와 같이 레퍼런스 타입은 데이터가 저장된 주소를 값으로 가지게 됩니다.

 

 

3. 리터럴


리터럴이란 그 자체로 값을 의미하는 것을 말합니다.

 

변수에 타입이 있는것처럼 리터럴에도 타입이 있습니다. 변수의 타입은 리터럴의 타입에 의해 결정되므로 리터럴에 타입이 없었다면 변수의 타입도 필요하지 않았습니다.

종류 리터럴 접미사
논리형 false, true 없음
정수형 123, 0b0101, 077, 0xFF, 100L L
실수형 3.14, 3.0e8, 1.4f f, d
문자형 'A', '1', '\n' 없음
문자열형 "ABC", "123", "A", "true" 없음
기타 리터럴 null, _ 없음

정수형과 실수형에는 여러 타입(byte, short, int, long, float, double)이 존재하므로 리터럴에 접미사를 붙여서 구분합니다. 정수형의 경우 long타입의 리터럴에 접미사 'l' 또는 'L'을 붙입니다. 접미사가 없다면 int타입의 리터럴이 되며 short나 byte의 리터럴은 별도로 존재하지 않아서 int타입의 리터럴을 사용합니다. 

 

실수형의 경우 float타입의 리터럴에 접미사 'f', 'F'를 붙이고 double타입의 리터럴에 접미사 'd', 'D'를 붙입니다.

실수형에서는 double이 기본타입이므로 접미사를 생략 가능합니다.

 

10진수 이외의 2, 8, 16진수로 표현된 리터럴을 변수에 저장할 수 있습니다.

  • 2진수 : 0b, 0B
  • 8진수 : 0
  • 16진수 : 0x, 0X

 

4. 변수 선언 및 초기화하는 방법


변수를 선언하는 것은 데이터를 저장하기 위해 메모리를 할당하는 것을 말합니다.

그리고 선언한 변수에 값을 넣는걸 초기화라고 합니다.

 

초기화 방법에는 변수 선언을 먼저하고 초기화하는 방법과 변수 선언과 초기화를 동시에 하는 방법이 있습니다.

 

변수 선언을 먼저하고 초기화 하는 방법

 

int a;		// 변수 a 선언
float f;	// 변수 f 선언
char c;		// 변수 c 선언

a = 14;		// a를 14 값으로 초기화
f = 3.14f;	// f를 3.14 값으로 초기화
c = 'a';	// c를 'a' 값으로 초기화

 

변수 선언과 동시에 초기화 하는 방법 (명시적 초기화)

 

int a = 14;			// 변수 a를 선언하고 값을 14로 초기화
float f = 3.14f;	// 변수 f를 선언하고 값을 3.14f로 초기화
char c = 'a';		// 변수 c를 선언하고 값을 'a'로 초기화

 

자바에서 멤버변수는 초기화를 하지않아도 자동적으로 변수의 자료형에 맞는 기본값으로 초기화가 이루어지므로 초기화 하지않고 사용해도 되지만 지역변수는 사용하기 전에 반드시 초기화 해야합니다. 그렇지 않으면 에러가 발생합니다.

멤버변수(클래스 변수와 인스턴스변수)와 배열의 초기화는 선택적이지만, 지역변수의 초기화는 필수적입니다.

 

int a;
String str;

int num = a;	// 정상

public void method1() {
    int b;
    int c = b;	// 에러!
}

 

5. 변수의 스코프와 라이프타임


변수의 스코프란 변수에 대한 접근과 존재할 수 있는 영역을 의미합니다. 

자바에서 스코프에 따른 변수의 종류에는 클래스변수(static 변수), 인스턴스 변수, 지역변수 3가지로 나눌 수 있습니다.

변수의 종류는 변수가 선언된 위치에 따라서 결정됩니다.

 

변수의 종류 선언 위치 초기화 시점 변수의 스코프
클래스 변수 클래스 영역 클래스가 처음 로딩될 때 클래스 전역
인스턴스 변수 클래스 영역 인스턴스가 생성될 때 각각의 인스턴스
지역 변수 메소드 영역 변수 선언문이 수행됐을 때 메소드 안(메소드가 모두 수행되면 접근할 수 없는 상태가됨)

 

각 변수의 라이프 타임은 다음과 같습니다.

 

변수의 종류 라이프 타임
클래스 변수 프로그램 종료시까지
인스턴스 변수 객체가 메모리에 존재하는 동안
지역 변수 메소드 수행 완료시 까지

 

6. 타입 변환, 캐스팅 그리고 타입 프로모션


모든 변수와 리터럴에는 타입이 있는데 프로그램을 작성하다 서로 다른 타입간의 연산을 수행해야하는 경우가 필요합니다. 이때 연산을 수행하기 전에 타입을 일치시켜야 하는데, 변수나 리터럴의 타입을 다른 타입으로 변환하는 것을

형변환 이라고 합니다.

 

프리미티브 타입에서 boolean을 제외한 나머지 타입들은 서로 형변환이 가능합니다. 프리미티브 타입과 레퍼런스 타입은 서로 형변환 할 수 없습니다. 다음은 기본형간의 형변환입니다.

 

변환 수식 결과
int -> char char c = (char)65; 'A'
char -> int int n = 'A'; 65
float -> int int a = (int)1.4f; 1
int -> float float f = 20; 20

 

형변환 하는법은 형변환하고자 하는 변수나 리터럴 앞에 변환하고자 하는 타입을 괄호와 함께 붙여주면 됩니다. 

 

int a = (int)'A'; // (변환 하려는 타입)피연산자

 

형변환의 종류에는 큰 메모리의 타입을 작은 타입으로 변환하는 캐스팅(강제 형변환), 작은 메모리 타입에서 큰 타입으로 변환하는 타입 프로모션(자동 형변환)이 있습니다.

 

위의 기본형간 형변환 예시에서 수식을 보면 형변환이 생략된 경우가 있습니다. 형변환이 이루어지지 않은것이 아니고 컴파일러가 생략된 형변환을 자동적으로 추가합니다. 이것이 타입 프로모션(자동 형변환) 입니다.

 

캐스팅은 강제 형변환, 명시적 형변환이라고도 하며 큰 메모리의 타입에서 작은 타입으로 변환할 때 사용합니다. 큰 메모리에서 작은 메모리로 변환 하기 때문에 경우에 따라 값 손실이 발생할 수 있습니다.

 

만약 2byte의 short 타입을 1byte의 byte타입으로 형변환 하는 예시를 본다면

 

short타입  10진수 -> 300

 

0 0 0 0 0 0 0 1 0 0 1 0 1 1 0 0

 

byte타입 10진수 -> 44

 

X X X X X X X 0 0 1 0 1 1 0 0

 

형변환시 위와같이 크기의 차이만큼 앞에서부터 잘라냅니다. 따라서 작은 메모리 타입의 크기보다 크면 값에 손실이 발생할 수 있는것입니다. 

 

자동 형변환에는 '기존의 값을 최대한 보존할 수 있는 타입으로 자동 현변환한다'는 규칙이 있습니다.

 

 

위의 표는 왼쪽부터 오른쪽으로 표현할 수 있는 값의 범위가 넓은 쪽으로 나열한 것입니다. 화살표 방향으로 형변환을 하면 자동 형변환이 가능합니다.

char와 short의 경우에는 char의 범위는 (0 ~ 65535) 이고 short는 (-32768 ~ 32767) 로 서로 범위가 달라서 어느 쪽으로 형변환을 하더라도 값에 손실이 발생할 수 있기 때문에 자동 형변환은 수행할 수 없고 반드시 형변환할 타입을 명시해 줘야 합니다.

 

7. 1차 및 2차 배열 선언하기


배열은 같은 타입의 여러 변수를 하나의 묶음으로 다루는 것입니다. 중요한것은 '같은 타입'이어야 한다는 것입니다.

 

만약 5명의 성적을 변수에 저장해야하면 코드는 다음과 같아 집니다.

 

int score1 = 100;
int score2 = 95;
int score3 = 90;
int score4 = 85;
int score5 = 80;

 

이것을 배열에 저장하면 다음과 같습니다.

 

int[] score = new int[5];

score[0] = 100;
score[1] = 95;
score[2] = 90;
score[3] = 85;
score[4] = 80;

 

5명의 성적이라 5개의 변수만 생성하면 되지만 만약 1만명의 성적을 저장하려면 1만개의 변수를 따로 만들어야합니다.

배열 score는 값이 담겨있는 메모리 주소를 가지고 있는 참조변수일 뿐 값이 저장되어 있는 공간은 아닙니다.

 

 

1차 배열의 선언은 원하는 타입의 변수를 선언하고 변수 또는 타입의 뒤에 배열임을 의미하는 대괄호("[]")를 붙이면 됩니다.

 

int[] score;
int score[];
// 타입의 뒤, 변수이름의 뒤  둘다 가능

 

이렇게 배열을 생성하면 아직 초기화 하지않았기 때문에 null 값이 들어가있습니다. 배열을 초기화하기 위해서는 연산자 'new'와 함께 배열의 타입과 길이를 지정해주면 됩니다.

 

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

 

1차원 배열을 초기화하는 방법은 다음과 같습니다.

 

int[] score;

score = new int[5];
// 또는
score = {1, 2, 3, 4, 5};

int[] arr = {6,7,8,9,10}; // 배열을 선언함과 동시에 초기화하는것도 가능
int[] arr2 = new int[5];

 

2차원 배열을 선언하고 초기화 하는 방법은 간단합니다. 대괄호를 하나더 추가하면 됩니다.

 

int[][] arr = new int[5][5];
int arr[][] = new int[5][5];

int[][] score = {{100, 200, 300}, {50, 10, 90}, {300, 320, 310}};

 

8. 타입 추론, var


 

타입 추론이란 코드 작성 당시에는 타입이 정해지지 않았지만 컴파일러 스스로가 타입을 유추하는 기능입니다.

자바 10 이전에는 Generic와 Lambda에서 이 기능을 사용해왔지만 자바 10에서는 var이라는 키워드가 생겼습니다.

 

var 키워드는 초기화한 값을 보고 타입을 유추하는데 이를 위해서는 반드시 선언과 동시에 데이터를 초기화 해야합니다.

 

// 자바 10 이전
String name = "My name is Park";

// 자바 10 이후
var name = "My name is Park";
// name 은 String 타입이 됩니다.

 

또한 자바 7의 다이아몬드 연산자는 var과 함께 쓰일 수 없습니다. 그 이유는 컴파일러가 타입을 유추할 단서가 없기 때문입니다.

 

var list = new ArrayList<>();
// 컴파일러가 타입을 유추할 수 있는 단서가 없습니다.

 

'java-liveStudy' 카테고리의 다른 글

6주차 과제. 상속  (0) 2020.12.25
5주차. 과제  (0) 2020.12.17
5주차. 클래스  (0) 2020.12.16
4주차 과제. 제어문 + 과제  (0) 2020.12.04
3주차 과제. 연산자  (0) 2020.11.26

댓글