왕초보만/기초 왕초보만

JAVA의 데이터 종류

JumBack2 2024. 11. 1. 13:30

오늘은 JAVA의 데이터 종류에 대해서 이야기 해보려고 한다.

 

c#의 데이터 종류 라는 예전 글을 먼저 공유한다.

https://dogfootsleep.tistory.com/17

 

c#의 데이터 종류

데이터의 형식은 기본 데이터 형식과 복합 데이터 형식으로 나뉜다. 복합 데이터 형식은 구조체와 클래스, 배열 등이 있는데 이 부분은 나중에 배웁니다. 그렇다면 기본 데이터 형식에 대해 알

dogfootsleep.tistory.com

 

우리는 데이터는 0과 1로 움직인다고 공부했다.

그러나 0과 1은 컴퓨터의 데이터이며 우리가 고급 레벨의 언어로 이야기 하려면 다양한 데이터의 체계가 필요하다.

예를 들어 문자와 같은 데이터도 존재하며, 숫자와 같은 데이터도 필요하다.

 

그래서 자바는 여러가지 데이터 타입을 지원해준다. 우리는 그 데이터 타입을 통해 데이터를 더 효율적으로 사용하고

프로그래밍한다.

 

내가 쓰고 싶은 x라는 입력 값을 항상 숫자로만 받고 싶다면 x는 숫자다! 라고 먼저 선언을 하는 것이다.

그렇다면 그 이후부턴 그 x는 숫자로 인식할 수 있을 것이다.

java의 경우에는 x를 숫자로 설정하고 쓰려면 아래와 같다.

int x = 3; 

 

여기서 int 는 정수형을 사용한다는 뜻이다.

 

JAVA의 데이터 타입

 

정적데이터 타입

자바(Java)는 타입이 엄격한(statically-typed) 언어로 분류된다. 이는 프로그램 내의 모든 변수, 표현식, 함수 등이 컴파일 시점에 데이터 타입을 명확히 해야 하며, 이 타입은 실행 시간 동안 변경되지 않는다는 것을 의미한다.

 

앞에서 컴퓨터 언어에는 환경과 쓰임에 따라 다양한 언어가 존재한다고 이야기 했다. 반대로 말하면 모두가 JAVA처럼 엄격한 타입을 쓰는 것이 아니라는 말이다. 그래서 Python의 경우나 Java Script의 주로 자유로운 데이터 타입을 사용한다.

 

그래서 python 의 경우 데이터 x를 사용할 때, 기본적으로는 어떤 데이터인지 미리 결정해주는 것을 하지 않고 바로 쓴다.

 

x = 3; 

 

자바 스크립트의 경우에도 주로 var로 데이터 타입을 설정해주고 ES6부턴 let 과 const를 사용하여 데이터를 표현해준다.

 

let x = 3;

 

물론 자바스크립트와 파이썬이 주요 데이터 타입을 지원 안하는 것은 아니다. 지원한다.

Python의 경우나 Java Script의 경우 동적 타입 시스템을 사용한다. 

 

 

동적 데이터 타입

동적 타입 시스템이란 변수 타입이 프로그램이 실행되는 동안 정해진다는 것이다. 동적 타입의 반대로는 정적 타입이 있으며 이는 실행 전 컴파일 단계에서 결정되며 한번 결정되면 런타임 동안은 변경되지 않는다. 

 

물론! 런타임에서 캐스팅이나 다형성으로 타입이 변경될 수 있으나 컴파일에서 결정을 하고 가는 만큼 정적 타입은 타입을 

최대한 엄격하게 유지하려고 한다.

 

JAVA는 다른 언어에 비해 엄격한 이유는 자바의 태생을 생각해보면 된다. 물론 안정성과 유지 보수성 등 타입을 엄격하게 정하면 장점이 있지만 필자가 생각하는 가장 큰 이점은 바로 크로스 플랫폼 호환성이다.

 

자바의 주요 목표 중 하나는 "한 번 작성하면, 어디서나 실행된다(Write Once, Run Anywhere; WORA)"이다. 이를 위해 자바는 자바 가상 머신(JVM) 위에서 실행되며, 엄격한 타입 시스템은 다양한 플랫폼 간의 호환성을 보장하는 데 중요한 역할을 한다. 타입이 엄격하게 관리되므로, 같은 자바 프로그램이 다른 플랫폼의 JVM에서도 동일하게 작동할 것임을 보장할 수 있다.

 

 

데이터 타입의 종류

자바의 데이터 타입의 종류는 크게 2가지로 나뉜다.

하나는 기본 데이터 타입과 또 다른 하나는 참조 데이터 타입이다.

이 타입은 메모리에 저장되는 방식과 사용 방법으로 나뉘는데, 메모리에서 Stack (스택) 영역에 실제 값이 직접 저장되는 방법으로 기본 데이터 타입, Heap(힙) 메모리 영역에 가변적으로 값이 저장되고 그 주소 값을 참조하는 참조 변수가 Stack에 저장되어 관리된다.

 

참조... 힙, 스택 무슨말인지 어렵다면 일단 아래로 내려가보자.

 

기본 데이터 타입이란?

기본 데이터 타입(Primitive Data Types)은 사전에 정의된, 가장 기본적인 데이터 타입을 의미한다. 이러한 타입들은 객체가 아니며, 직접 값을 저장한다. 자바에서는 총 8가지의 기본 데이터 타입을 제공하며, 이들은 숫자, 문자, 그리고 논리 값을 저장하는 데 사용된다.

 

기본 데이터 타입 종류

  1. byte: 8비트 정수 데이터 타입으로, 값의 범위는 -128에서 127까지이다.
  2. short: 16비트 정수 데이터 타입으로, 값의 범위는 -32,768에서 32,767까지이다.
  3. int: 32비트 정수 데이터 타입으로, 값의 범위는 약 -2.1억에서 2.1억까지입니다. 자바에서 가장 일반적으로 사용되는 정수 타입이다.
  4. long: 64비트 정수 데이터 타입으로, 매우 큰 정수 값을 저장할 때 사용된다.
  5. float: 32비트 부동 소수점 수를 저장할 때 사용되며, 소수점 이하의 정밀도가 높지 않은 실수를 다룰 때 사용된다.
  6. double: 64비트 부동 소수점 수를 저장할 때 사용되며, float보다 더 큰 수와 더 높은 정밀도를 필요로 하는 실수를 다룰 때 사용된다.
  7. char: 단일 16비트 유니코드 문자를 저장할 때 사용된다.
  8. boolean: true 또는 false 두 가지 값만을 가지는 데이터 타입이다.

 

데이터 타입의 크기

타입 비트 크기 값 범위
byte 8 -128 to 127
short 16 -32,768 to 32,767
int 32 -2^31 to 2^31-1
long 64 -2^63 to 2^63-1
float 32 -3.4E38 to 3.4E38
double 64 -1.7E308 to 1.7E308
char 16 0 to 65,535
boolean N/A true/false

 boolean은 언어의 구현에 따라 달라질 수 있다.

 

참조 데이터 타입이란?

 

참조 데이터 타입은 객체의 주소를 저장하는데, 이 주소를 통해 객체에 접근할 수 있다. 참조 타입은 기본 타입과 달리 데이터의 크기에 제한이 없으며, 다양한 형태의 복잡한 데이터를 다룰 수 있다. 

 

참조 데이터 타입 종류

  • 클래스(Class): 사용자 정의 데이터 타입으로, 필드(속성)와 메서드(함수)를 포함할 수 있다.
  • 인터페이스(Interface): 모든 메서드가 추상 메서드(구현되지 않은 메서드)인 참조 타입이다. 클래스가 인터페이스를 구현할 때는 인터페이스의 모든 메서드를 구현해야 한다.
  • 배열(Array): 동일 타입의 여러 변수를 하나의 집합으로 관리할 수 있게 해주는 데이터 구조이다. 기본 데이터 타입이나 참조 데이터 타입 모두 배열의 형태로 사용될 수 있다.

 

데이터의 접근

자바와 같은 프로그래밍 언어에서, 메모리는 크게 스택(stack) 영역과 힙(heap) 영역으로 구분된다.

 

스택 영역 (Stack)

스택 영역은 메소드 내에서 생성되는 기본 데이터 타입의 변수와 객체 참조 변수들을 저장하는 공간이다. 스택은 메소드 호출과 함께 할당되며, 메소드가 종료되면 사용하던 스택 메모리도 해제된다.

  • 특징:
    • 스택은 후입선출(LIFO, Last In First Out) 구조를 가진다. 가장 마지막에 추가된 데이터가 가장 먼저 제거된다.
    • 각 스레드에는 독립적인 스택 메모리가 할당된다.
    • 스택 영역에 저장되는 변수의 크기는 컴파일 시점에 결정된다.
    • 스택 오버플로우는 스택 영역이 넘치는 상황을 말하며, 이는 대개 재귀 호출이 과도하게 발생했을 때 일어난다.
  • 용도:
    • 기본 데이터 타입의 변수 (예: int, double) 저장
    • 객체 참조 변수 저장 (실제 객체는 힙에 저장됨)
    • 메소드 호출 시의 매개변수, 지역 변수, 반환 값 등

힙 영역 (Heap)

힙 영역은 동적으로 할당되는 데이터(주로 객체와 배열)를 저장하는 공간이다. 힙에 저장된 데이터는 프로그램 코드 어디서든 접근할 수 있으며, 가비지 컬렉터에 의해 관리된다.

  • 특징:
    • 힙은 메모리가 동적으로 할당되고 해제된다.
    • 힙에 저장된 데이터는 프로그램의 여러 부분에서 공유될 수 있다.
    • 가비지 컬렉터(Garbage Collector)가 더 이상 참조되지 않는 객체를 정기적으로 제거하여 메모리를 관리한다.
    • 힙 오버플로우는 힙 영역이 가득 차서 더 이상 객체를 할당할 수 없는 상황을 말한다.
  • 용도:
    • new 키워드로 생성된 객체와 배열 저장
    • 프로그램 실행 도중 생성되어 동적으로 관리되는 데이터

스택과 힙의 차이점

  • 생명 주기: 스택에 저장된 데이터는 메소드가 종료될 때 해제되는 반면, 힙 영역의 데이터는 가비지 컬렉터가 명시적으로 메모리를 해제할 때까지 남아 있다.
  • 접근 속도: 스택은 데이터에 대한 접근 속도가 빠르지만, 힙은 상대적으로 접근 속도가 느리다.
  • 메모리 할당: 스택은 컴 파일 시점에 메모리 크기가 결정되는 반면, 힙은 런타임에 필요에 따라 메모리가 할당된다.

 

래퍼 클래스

래퍼클래스란?

Java의 래퍼 클래스(wrapper class)는 기본 데이터 타입을 객체로 표현하기 위한 클래스이다. 이 클래스들은 java.lang 패키지에 정의되어 있으며, 각각의 기본 데이터 타입을 객체로 다룰 수 있게 해준다. 래퍼 클래스를 사용하면 기본 데이터 타입에 대한 객체 지향적인 기능을 사용할 수 있다. 기본적으로 객체 타입이기 때문에 

래퍼클래스 종류

  • Boolean: boolean 데이터 타입의 래퍼 클래스
  • Byte: byte 데이터 타입의 래퍼 클래스
  • Character: char 데이터 타입의 래퍼 클래스
  • Double: double 데이터 타입의 래퍼 클래스
  • Float: float 데이터 타입의 래퍼 클래스
  • Integer: int 데이터 타입의 래퍼 클래스
  • Long: long 데이터 타입의 래퍼 클래스
  • Short: short 데이터 타입의 래퍼 클래스

등이 있다. 보면 기본 데이터 타입에 앞 문자가 대문자인 것을 볼 수있다.

Java에선 클래스의 이름은 대문자로 하기로 약속했다. 필수는 아니지만

 

래퍼클래스의 중요성

  1. 객체로서의 기능 제공: 래퍼 클래스를 사용하면 기본 데이터 타입을 객체로 취급할 수 있으므로, Java의 객체 지향 프로그래밍 패러다임을 따를 수 있다. 예를 들어, 메서드 호출이 가능하고, 객체를 매개변수로 전달하거나 반환값으로 사용할 수 있다.
  2. 컬렉션 프레임워크와의 호환성: Java의 컬렉션 프레임워크는 객체를 저장하는 구조다. 따라서, 기본 데이터 타입을 직접 사용할 수 없고, 이를 객체로 포장해야만 한다. 예를 들어, ArrayList<int>는 유효하지 않지만, ArrayList<Integer>는 사용할 수 있다.
  3. 유틸리티 메서드 제공: 래퍼 클래스는 기본 데이터 타입과 관련된 유용한 메서드를 제공한다. 예를 들어, Integer 클래스는 parseInt, valueOf 같은 정적 메서드를 제공하여 문자열을 정수로 변환하거나, 정수 값을 Integer 객체로 변환할 수 있다.
  4. 값의 비교와 변환: 래퍼 클래스는 객체 간의 비교, 형 변환, 값을 다루는 다양한 메서드를 제공한다. 이를 통해 개발자는 더 풍부한 기능을 사용하여 데이터를 처리할 수 있다.
  5. null 값을 허용: 기본 데이터 타입은 null 값을 가질 수 없지만, 래퍼 클래스를 사용하면 null 값을 가질 수 있다. 이는 데이터가 없거나 미정의된 상태를 나타내야 할 때 유용하다.

당연히 클래스 객체 타입이기에 여러 장점이 존재하지만 null이 허용된다는 것을 주목하자.

  • null은 변수가 아무런 객체도 참조하지 않고 있음을 나타낸다. 즉, 변수가 메모리 상의 어떤 위치도 가리키고 있지 않다는 것을 의미한다.
  • "empty" 상태의 객체는 유효한 메모리 주소를 가리키고 있으며, 해당 객체의 메소드를 호출할 수 있다(예: 빈 리스트에 대해 .size() 메소드를 호출하면 0을 반환).

 

 

박싱 언박싱이란?

자바에서 박싱(Boxing)과 언박싱(Unboxing)은 자바 같은 객체 지향 프로그래밍 언어에서 기본 데이터 타입과 해당하는 래퍼 클래스(Wrapper Class) 객체 사이의 자동 변환을 의미한다. 이러한 변환은 자바 컴파일러에 의해 자동으로 수행된다.

 

박싱 (Boxing)

박싱은 기본 데이터 타입의 값을 해당하는 래퍼 클래스의 객체로 변환하는 과정을 말한다. 예를 들어, int 타입의 데이터를 Integer 클래스의 객체로 변환하는 것이 박싱이다. 이 과정은 프로그래머가 명시적으로 새로운 객체를 생성할 필요 없이 자동으로 이루어진다.

즉 기본 데이터 타입에서 참조 데이터 타입으로 변환하는 것이다.

 

int num = 100;
Integer numObj = num; // 자동 박싱

 

언박싱 (Unboxing)

언박싱은 박싱의 반대 과정으로, 래퍼 클래스의 객체를 해당하는 기본 데이터 타입의 값으로 변환하는 것을 말한다. 예를 들어, Integer 객체를 int 타입의 값으로 변환하는 것이 언박싱이다. 이 과정 역시 자동으로 이루어진다.

간단히 말해 참조 데이터 타입에서 기본 데이터 타입으로 변환하는 것이다. 

 

Integer numObj = new Integer(100);
int num = numObj; // 자동 언박싱

 

 

자동 박싱과 언박싱의 이점

  • 간결한 코드: 자동 박싱과 언박싱 덕분에, 프로그래머는 기본 데이터 타입과 래퍼 클래스 타입 사이를 명시적으로 변환하는 코드를 작성할 필요가 없어 코드가 더 간결해진다.
  • 편의성: 컬렉션 프레임워크와 같이 객체만을 요소로 받는 데이터 구조를 사용할 때, 기본 데이터 타입을 쉽게 저장하고 검색할 수 있다. 예를 들어, ArrayList<Integer>에 int 값을 직접 추가할 수 있습니다.

주의사항

  • 성능 저하: 박싱과 언박싱 과정에서는 실제로 객체가 생성되고, 메모리 할당이 이루어지기 때문에, 이러한 변환 과정이 빈번하게 발생할 경우 성능 저하를 일으킬 수 있다.
  • null 참조: 언박싱 과정에서 null 값을 가진 래퍼 클래스 객체를 기본 데이터 타입으로 변환하려고 하면 NullPointerException이 발생할 수 있다. 따라서, 언박싱하기 전에 객체가 null이 아닌지 확인하는 것이 좋다.