본문 바로가기

WHITESHIP JAVA LIVE STUDY

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

종류 데이터 형 표현 범위 기본 값 할당되는 메모리 크기
논리형 boolean true 또는 false false 1 byte
문자형 char '\u0000' ~ 'uFFFF' (16비트 유니코드 문자 데이터) '\u0000' 2 byte
정수형 byte -128~127 0 1 byte
short -32768 ~ 32767 0 2 byte 
int -2147483648 ~ 2147483647 (-21억 ~ +21억) 0 4 byte
long 9223372036854775808 ~ 9223372036854775807(-100경 ~ + 100경) 0L 8 byte
실수형 float 1.4E-45 ~ 3.4028235E38 0.0F 4 byte
double 4.9E-324 ~ 1.7976931348623157E308 0.0 8 byte

 

🍕 boolean

Java가 데이터를 다루는 최소 범위가 1 Byte 이기 때문에 낭비적이지만 1 Byte를 사용한다.

🍕 char

동양의 글자의 경우 2 Byte 가 필요하기 때문에 char의 경우 2 Byte를 이용한다.

$$0\sim2^{16}$$

음수의 범위 없이 유니코드(0~65535) 범위를 저장한다.

Java 에서 유일하게 제공되는 unsigned 형태이다.

💡 unsigned - 음수 없이 0부터 시작하여 양수값만 가지는 데이터 형태
  • char의 unsigned
    • 2 Byte = (16진수) 0x00 = (2진수) 0000 0000 0000 0000
    • 하지만 char 형은 unsigned 형식이기 때문에 맨 앞 비트를 음수 양수 형식으로 사용하지 않는다.
    • short 형이 1111 1111 1111 1111 의 Bit를 가지고 있을 때 10진수의 값 -1
    • char 형이 1111 1111 1111 1111 의 Bit 를 가지고 있을 때 10진수의 값 65535
    • 맨 앞 1 Bit 를 가지고 음수나 양수를 나타낸다.
  • char의 대소 비교
    • char a = 'A'; b = B; 일 때 if (a > b) 가 가능한 이유는,
    • char 형은 유니코드 정수 형태로 저장되기 때문에 a 변수에는 A의 정수값인 65가 들어간다.
    • C 언어와 C++에서는 아스키코드를 이용하여 문자를 표현하지만,
      자바에서는 유니코드를 이용해 문자를 표현한다.정수로 저장할 경우, 출력 시 정수값에 해당되는 유니코드 문자가 출력된다.
    • char 차입에는 문자를 직접 저장할 뿐만 아니라 10진수, 16진수 정수도 저장이 가능하다.

ex)

public class CharExam {
    public static void main(String[] args) {
        char C1 = 'A';    //문자를 직접 저장 가능
        char C2 = '65';   //10 진수 문자로 저장
        char C3 = `\u0041`;  // 16 진수 문자로 저장

        char C4 = '가';  // 문자 저장
        char C5 = 44032;  // 10 진수 정수 저장
        char C6 = 
        `
        int uniCode = c1;  // 유니코드 정수값을 저장하기 위한 변수
        `
        System.out.println(c1);   // A
        System.out.println(c2);   // A
        System.out.println(c3);   // A
        System.out.println(c4);   // 가
        System.out.println(c5);   // 가
        System.out.println(c6);   // 가
        System.out.println(uniCode);   // 65
        }
}

🚨 주의

char 타입 변수에 문자를 대입하지 않고 초기화할 목적으로 문자를 대입할 경우 공백을 입력해야한다.
⭕ : char c = ' ';
❌ : char c = ''; (유니코드 32가 없으면 컴파일 에러 발생)

문자열을 저장하려면 큰 따옴표로 감싸는 String 참조 변수를 사용해야한다.
ex) String name = "두지";

String 변수는 큰 따옴표를 연달아 붙인 빈 문자가 가능하다.
ex) String str = "";

🍕 byte

JAVA 에서 정수 연산은 기본적으로 int 타입으로 처리한다
정수 타입은 n 비트 크기일 때 아래와 같은 범위를 갖는다.
$$-2^{n-1} \sim 2^{n-1}-1$$

 

1 Byte (8 bit) 크기를 가진다.

$$-2^{8-1}-2^{8-1}-1= -2^7 \sim 2^7-1$$

최상위 비트(MSB : Most Significant Bit)는 정수 부호 값을 결정한다.

예)

2 = 0000 0000

-2 = 1111 11110

🍕 short

2 bye (16 bit) 크기를 가진다.

-32,768~32,767 범위까지 표현 가능하다.

$$-2^{16-1}\sim2^{16-1}-1 = -2^{15}\sim2^{15}-1$$

C 언어와 호환을 위해 사용되며 자바에서는 잘 사용하지 않는 타입이다.

🍕 int

4 byte (32 Bit) 크기를 가진다.

(-2,147,483,648~2,147,483,647) 범위까지 저장 및 표현이 가능하다

$$-2^{32-1}\simㅡ2^{32-1}-1=-2^{31}\sim2^{31}-1$$

정수 연산의 기본 타입으로 사용된다.

byte, short 타입을 연산할 시 int 타입으로 변환되고, 연산 결과 역시 int 타입으로 변환되어 저장된다. (자동 타입 변환)

어떠한 진수로 입력하더라고 모두 2진수로 변환되어 비트에 저장된다.

ex)

public class IntExam {
    public static void main(String[] args) {
        int var1 = 10;    // 10 진수로 저장
        int var2 = 012;   // 8 진수로 저장
        int var3 = 0xA;   // 16 진수로 저장

        System.out.println(var1);    // 10 출력
        System.out.println(var2);    // 10 출력
        System.out.println(var3);    // 10 출력
    }
}

🍕 long

8 byte (64 Bit) 크기를 가진다.

(-9,223,372,036,854,775,808 ~ -9,223,372,036,854,775,807) 범위까지 저장 및 표현이 가능하다.

$$-2^{64-1}\sim2^{64-1}-1=-2^{63}\sim2^{63}-1$$

큰 수치를 다루는 프로그램에서 이용된다.

초기화 시 int 값 범위보다 큰 정수를 입력할 때는 소문자 l 또는 대문자 L을 뒤에 붙여야한다.

(정수 연산 시 int로 변환되어 연산이 진행되기 때문)

따라서 컴파일러에게 long 타입 리터럴임을 알려주기 위해 붙여야한다.

ex)

public class LongExam {
    public static void main(String[] args) {
        long var1 = 10;
        long var2 = 20L;
        // long var3 = 1000000000000 컴파일 에러 (int 범위 초과)
        long var4 = 1000000000000L // int 범위가 넘어가는 long 타입 변수는 L 을 꼭 붙여야한다.

        System.out.println(var1);    // 10
        System.out.println(var2);    // 20
        System.out.println(var3);    // 1000000000000
    }
}

🍕 float

4 byte (32 Bit) 크기를 가진다

부호 (1 Bit) + 지수 (8 Bit) + 가수 (23 Bit)

💡 부동 소수점 방식
위와같이 하나의 실수를 가수와 지수 부분으로 나누어 소수점을 움직이면서 표현하는 방식이다.
(대부분의 시스템에서는 실수를 IEEE 754 표준 부동 소수점 방식으로 표현하고 있다.)

자바의 실수 타입의 기본 처리는 double 타입이므로,

float 타입에 값을 저장하려면 실수 리터럴 뒤에 f 또는 F를 붙여야한다.

ex)

float flovar1= 3.14;     // f 를 붙이지 않고 저장하면 컴파일 에러 발생!
float flovar2= 3.14f;    // 3.14 실수 리터럴이 저장된다.

🍕 double

8 byte (64 bit) 크기를 가진다.

부호 (1 Bit) + 지수 (11 Bit) + 가수 (52 Bit)

float 타입은 소수점 아래 9자리까지만 표현할 수 있는 반면, double 타입은 소수점 아래 18자리 까지도 표현할 수 있다.

ex)

public class FloatDoubleVarExam {
    public static void main(String[] args) {
        // 실수 저장
        double var1 = 3.14;
        float var2 = 3.14f;

        // 정밀도 테스트
        double var3 = 0.1234567890123456789;
        float var4 = 0.1234567890123456789F;

        System.out.println("var1 : "+var1); //var1 : 3.14
        System.out.println("var2 : "+var2); //var2 : 3.14
        System.out.println("var3 : "+var3); //var3 : 0.123456789012345678 
        System.out.println("var4 : "+var4); //var4 : 0.123456789  

        //e 사용해서 저장
        int var5 = 3000000; 
        double var6 = 3e6; 
        float var7 = 3e6F; 
        double var8 = 2e-3;

        System.out.println("var5 : "+var5); //var5 : 3000000 
        System.out.println("var6 : "+var6); //var6 : 3000000.0 
        System.out.println("var7 : "+var7); //var7 : 3000000.0 
        System.out.println("var8 : "+var8); //var8 : 0.002
    }
}
💡 정수 리터럴에 10의 지수를 나타내는 e 또는 E가 포함되어 있다면 (BigDecimal)
실수 타입 변수(float, double)에 저장해야한다.

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

프리미티브 타입(Primitive Type). 기본형 타입, 또는 원시 타입이라고 한다.

프리미티브 타입이란 정수, 실수, 문자, 논리, 리터럴 등의 실제 데이터 값을 저장하는 타입이다.

 

레퍼런스 타입(Reference Type). 참조 타입이라고도 한다.

레퍼런스 타입이란 객체(Object)의 번지를 참조(주소를 저장)하는 타입으로, 메모리 번지 값을 통해 객체를 참조하는 타입이다.

원시타입을 제외한 타입들(문자열, 배열, 열거, 클래스, 인터페이스)을 말한다.

Java에서 실제 객체는 힙(Heap) 영역에 저장되며 참조 타입 변수는 스택 영역에 실제 객체들의 주소를 저장하여, 객체를 사용할 때마다 참조 변수에 저장된 객체의 주소를 불러와 사용하는 방식이다.

리터럴

소스 코드 내에 직접 입력된 값(데이터)를 의미한다.

변수 초기화 시 저장할 값에 해당되기도 한다.

💡 상수
값을 한 번 저장하면 변경할 수 없는 변수를 의미

🍟 정수 리터럴

정수 형태의 값으로 byte, char, shorrt, int, long 의 정수 타입 기본 데이터 타입에 저장될 수 있다.

  • 10진수
    • 소수점이 없는 정수 리터럴
  • 8진수
    • 0으로 시작하는 리터럴
  • 16진수
    • 0x 또는 0X로 시작하고 0~9 숫자, A, B, C, D, E, F 또는 a, b, c, d, e, f, 로 구성된 리터럴

🍟 실수 리터럴

실수 형태의 값으로 float, double 의 실수 타입을 기본 데이터 타입에 저장될 수 있다.

  • 10진수 실수
    • 소수점이 있는 리터럴
  • 10진수 지수와 가수 표현
    • E 또는 e 가 숫자 뒤에 존재하는 리터럴

🍟 문자 리터럴

작은 따옴표 ' ' 로 묶인 하나의 텍스트

🦎 이스케이프 문자

이스케이프 문자 용도 유니코드
\t 수평 탭 0x0009
\n 줄 바꿈 0x000a
\r 리턴 0x000d
\" 큰 따옴표 표시 0x0022
\' 작은 따옴표 표시 0x0027
\\ \ 역슬래쉬 표시 0x005c
\u16진수 16진수에 해당하는 유니코드 0x0000 ~ 0xffff

역슬레쉬 가 붙은 문자 리터럴로 특수한 용도로 사용된다.

🍟 논리 리터럴

boolean 논리 기본 데이터 타입에 저장될 수 있고, true, false 값을 가진다.

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

💡 변수란?
하나의 값을 저장하기 위해 프로그ㅐㅁ에 의해 이름을 할당 받은 메모리 공간이다.
변수의 값은 변경 가능하다
💡 초기화란?
변수에 초기값을 주는 행위 또는 수에 값을 저장하는 행위
  1. 변수의 선언과 초기화를 따로하는 방법
  2. 변수의 선언과 동시에 초기화 하는 방법

1. 변수의 선언과 초기화를 따로하는 방법

// 데이터타입 변수이름;
int num;

선언된 변수는 초기화되지 않았으므로 쓰레기 값이 들어가 있다.

자바에서는 초기화 되지 않은 변수는 프로그램 안전성을 위해 사용할 수 없다.

초기화되지 않은 변수를 사용하려고하면, 컴파일 에러가 발생한다.

 

이후 초기화는 변수 내에 값을 넣어주기만 하면된다.

num = 10;

2. 변수의 선언과 동시에 초기화하는 방법

// 데이터 타입 변수이름 = 저장할 값;
int num1 = 10;

변수를 선언과 동시에 초기화 한다.

 

선언하고자하는 변수들이 같은 타입일 경우, 아래처럼 한 줄로 동시에 선언이 가능하다.

서로 다른 타입들은 동시 초기화 불가능

// 데이터타입 변수이름 = 초기값, 변수이름 = 초기값, . . . ;
int num1 = 10, num2 = 15;
🚨 주의
이미 선언된 변수를 동시에 초기화할 수 없다.

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

💡 변수의 스코프
스코프(scope)는 영역이라는 뜻으로,
변수에 접근하거나 접근할 수 있는 유효 범위/영역을 말한다.
💡 변수의 라이프타임
변수가 메모리에 살아있는 기간을 말한다.
class Test {
    int x, y; // 인스턴스 변수
    static int result; // 클래스 변수

    void add(int a, int b) { // a, b : 로컬 변수
    x = a;
    y = b;
    int sum = x + y;
    Systme.out.println("Sum = " + sum);

    public static void main(String args[]) {
        Sample obj = new Sample();
        obj.add(10, 20);
    }
}

인스턴스 변수(Instance Variables)

  • 정의
    • 클래스 내부와 모든 메소드 및 블록 외부에서 선언된 변수
  • 스코프
    • 정적 메서드를 제외한 클래스 전체
  • 라이프타임
    • 객체가 메모리에 남아 있을 때까지

클래스 변수(Class Variables)

  • 정의
    • 클래스 내부, 모든 블록 외부에서 선언되고 static으로 표시된 변수
  • 스코프
    • 클래스 전체
  • 라이프타임
    • 프로그램이 끝날 때까지 또는 클래스가 메모리에 로드되는 동안

지역변수(Local Variables)

  • 정의
    • 인스턴스 및 클래스 변수가 아닌 모든 변수
  • 스코프
    • 선언된 블록({})내에 있음
  • 라이프타임
    • 컨트롤이 선언된 블록을 떠날 때까지

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

타입 변환

  • 선언된 하나의 타입을 다른 타입으로 변환한다.(boolean 제외)
  • 다른 타입끼리 연산할 경우, 피연산자들을 모두 같은 타입으로 변환한 후 연산이 진행된다.
  • 메모리에서 할당 받은 크기가 작은 타입에서 큰 타입으로의 타입 변환은 자동으로 이루어진다.
  • 메모리에서 할당 받은 크기가 큰 타입에서 작은 타입으로의 타입 변환은 데이터 손실이 발생하여 컴파일 에러가 발생할 수 있다.(큰타입 ⇒ 작은 타입)
  • 데이터 손실을 감수하고 변환하려면 강제 타입 변환을 해야한다.
  • 종류
    1. 자동 타입 변환 (묵시적 타입 변환)
    2. 강제 타입 변환(명시적 타입 변환)

자동 타입 변환

대입 연산이나 산술 연산 등을 수행할 때 컴파일러가 자동으로 수행하는 타입 변환

메모리 크기가 작은 타입에서 큰 타입으로 변환

byte(1) < short, char(2) < int(4) < long(8) < float(4) < double(8)
(실수형은 표현 범위가 더 넓기 때문에 더 큰 타입으로 들어간다)

  • ⭕ 정수 타입(int 등) ⇒ 실수 타입(double 등)
    • .0 소수점이 붙은 실수값으로 변경된다.
  • ⭕ 문자타입(char) ⇒ 정수타입(int 등)
    • 유니코드 값(정수)이 저장된다.
  • ❌ byte 타입 ⇒ char타입
    • byte타입이 음수가 저장되기 때문에 음수가 저장되지 않는 char 보다 범위가 더 넓으므로 자동 변환 안됨

1차 및 2차 배열 선언하기

배열이란?

배열이란 선형 자료 구조 중 하나로, 동일한 타입의 연관된 데이터를 메모리에 연속적으로 저장하여 하나의 변수에 묶어서 관리하기 위한 자료구조이다.

1차 배열 선언

크기 할당 & 초기화 없이 배열 참조변수만 선언

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

타입 추론

타입 추론은 말 그대로 개발자가 변수의 타입을 명시적으로 적어주지 않고도, 컴파일러가 알아서 이 변수의 타입을 대입된 리터럴로 추론하는 것이다.

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의 타입을 선언해 주지 않으면 컴파일러가 리터럴을 추론하고 str2String 일 것이라고 판단한다.

이게 바로 타입 추론이다

var

위 예제에서 우린 var 라는 것으로 묵시적으로 타입을 선언해줬다.

여기서 var는 무엇인가?

var 는 JAVA 10 부터 도입된 것으로, 지역변수를 선언할 때 초깃값을 통하여 데이터 타입을 추론하게 한다.

 

🚨 var 는 초기값이 있는 지역 변수로만 선언 가능하다.

var 는 멤버 변수, 또는 메소드의 파라미터, 리턴타입으로 사용이 불가능하다.

또한, 무조건 선언할 때 초기화 값이 있어야하는데, 이 조건을 만족하지 못하면 이용하지 못한다.

 

🚨 var 는 키워드(keyword)가 아니다.

어떤 타입도 아니고, 클래스에서 사용할 수 있는 예약어가 아니기 때문이다.

그래서 우린 int 를 변수 이름으로 만들 수 없지만, var 라는 문자를 변수로 사용할 수 있다.

int var = 3;

🚨 var 는 런타임 오버헤드가 없다.

컴파일 시점var 를 초기화 한 값을 보고 추론하기 때문에,

바이트 코드엔(그러니까 컴파일 된 이후에) 명시적으로 intint , stringstring 으로 되어 있다.

결정이 되어 있는 상태라, 타입 추론 변수를 읽을 때 마다 타입을 알아내기 위한 연산을 하지 않는다는 것이다.

그래서 var 로 선언된 변수는 중간에 타입이 절대 변경되지 않는다.

 

JavaScript 같은 언어들은 선언된 변수를 중간에 다른 값으로 변경할 수 있다.

var test = 10;
test = "Hello world";

하지만 자바는 불가능해서 컴파일단에서 바로 에러를 뱉는다.

 

🚨 var 엔 null 값이 들어갈 수 없다.

var i = null; // 에러 남

 

🚨 람타 표현식에선 명시적인 타입을 지정해줘야한다.

var p = (String s) -> System.out.println("s =" + s); // 에러

 

🚨 배열을 선언할 땐 명시적인 타입을 지정해줘야한다.

var arr = {1,2,3}; // 에러 남
💡 var 는 키워드가 아니지만, 키워드 앞에서만 사용할 수 있는 어노테이션을 쓸 수 있다는 장점이 있다.

 

 

 

더보기

Seize the day!

Spring MVC | Spring Boot | Spring Security | Mysql | Oracle | PostgreSQL | Vue.js | Nuxt.js | React.js | TypeScript | JSP | Frontend | Backend | Full Stack | 자기계발 | 미라클 모닝 | 일상