JS Star 블로그

기억보다는 기록을✏️ 머신러닝, 웹개발, 물리학을 공부했고 계속 배워가고 있습니다.
📌 기존에 포스팅하던 블로그에서 포스트를 옮기는 중입니다.

변수, 상수와 리터럴

05 Dec 2020 » java

변수

변수 는 값이 변할 수 있는 공간을 의미한다. 변수에 값을 할당해보자.

package java_basic;

public class variable {

	public static void main(String[] args) {
		int a;
		a = 10;
		a = 20;
		System.out.println(a+1);	// 21
	}
  
}

a 라는 메모리 공간에 숫자 10을 담았다가 20을 다시 담았고 +1을 해서 출력했다. 자바는 변수를 선언할 때 데이터 타입에 따라 다르게 선언해야 한다.

  • byte : 1 byte가 표현할 수 있는 정수 (-128~127)
  • short : 2 byte가 표현할 수 있는 정수
  • int : 4 byte가 표현할 수 있는 정수
  • long : 8 byte가 표현할 수 있는 정수
  • float : 4 byte가 표현할 수 있는 실수
  • double : 8 byte가 표현할 수 있는 실수
  • char : 2 byte가 표현할 수 있는 문자
  • boolean : True / False

1byte는 8bit이고 8bit는 True/False로 표현할 수 있는 칸이 8개라는 의미이므로 2의 8승의 경우의 수를 가질 수 있어 256개의 숫자를 표현할 수 있다. 그렇기 때문에 int는 -128~127 범위의 256개의 숫자를 나타낼 수 있다.

String 은 아래와 같이 선언할 수 있다.

String a = "Hello world!";

상수

상수 는 변수와 다르게 값이 변하지 않는 공간을 의미한다. 자바에서 final 을 통해 값을 할당할 수 있다. 다만 다음과 같은 규칙으로 값을 할당해야 한다.

final int a = 0;		// 선언과 동시에 할당

final int a;		// **에러발생!**
a = 0;		// **에러발생!**

상수는 값이 변할 수 없는 공간이기 때문에 선언과 동시에 값을 할당해야 하고 나중에 그 값을 바꿀 수 없다. 값이 변하지 않거나 변경하지 못하게 하고 싶을 때 상수를 사용한다.

리터럴

리터럴 은 실제 공간 (변수나 상수)에 들어가는 값을 의미한다. 변수나 상수 뿐만 아니라 변수에 대입하는 리터럴도 데이터 타입이 있다.

int 은 양수 최대 2,147,483,647까지 표현할 수 있다. 2147483648를 넣어보자.

int a = 2147483648;

// Error: Type mismatch: cannot convert from int to byte

int 가 표현할 수 있는 범위를 넘어섰으므로 long 을 사용하면 에러를 없앨 수 있을까?

long a = 2147483648;

// The literal 2147483648 of type int is out of range

이번에는 숫자 부분 (리터럴)의 타입이 int 범위를 넘어섰다고 나온다. 기본적으로 리터럴의 데이터 타입은 정수의 경우 int, 실수의 경우 double default로 지정되어 있다. 그래서 만약 위의 경우처럼 int가 표현할 수 있는 숫자의 범위를 넘어섰기 때문에 왼쪽에 있는 변수를 long으로 선언하면, 오른쪽에 있는 리터럴도 long 자료형이라는 것을 명시해줘야 한다.

오른쪽에 있는 리터럴의 데이터 타입을 바꾸기 위해서는 다음과 같이 할 수 있다.

long a = 2147483648L;	// long
float b = 3.14F;	// float

연산을 하는데 데이터 타입이 다른 경우는 2 + 2.0 과 같은 경우다. 앞에 있는 수는 int이지만 뒤에 있는 수는 float이다. 이 두 경우는 값은 같지만 bit code로 보면 전혀 다른 숫자이다. 그렇기 때문에 데이터 타입을 일치 시켜주는 것이다.

암시적 형변환

변수에 리터럴을 대입하려면 변수와 리터럴의 데이터 타입이 같아야 하는데 이를 자동으로 변형해주는 것을 암시적 (자동) 형변환이라고 한다.

double a = 3.14F;
// 3.140000104904175

위와 같이 표현하는 것은 에러가 발생하지 않고 3.14가 자동으로 double 형이 되어있다. 왜냐면 double이 더 많은 수를 담을 수 있기 때문이다. 즉 데이터 타입의 크기가 왼쪽 > 오른쪽 의 경우만 허용된다. 하지만 반대의 경우는 에러가 발생한다. 자동 형변환이 가능한 순서는 아래와 같다.

byte - short - char - int - long - float - double

연산의 경우는 아래와 같이 이루어진다.

int a = 3;
float b = 1.0F;
System.out.println(a+b);

// 4.0

명시적 형변환

명시적 형변환은 수동으로 데이터 타입을 변환시켜주는 것을 의미한다.

int a = (int)3.14F;
System.out.println(a);

// 3

데이터 타입의 의미

이렇게 데이터 타입을 나누는 이유는 메모리 관리를 효율적으로 하기 위해서다. byte 는 양수 중 127까지만 표현할 수 있다. 아래와 같이 변수에 값을 할당해보자.

byte c = 128;
System.out.println(c);

// Error: Type mismatch: cannot convert from int to byte

위와 같이 에러가 나오게 된다. 이는 127까지만 표현할 수 있는 byte 자료형에서 128을 할당했기 때문이다. 그래서 보통 정수타입에서는 int 를 사용한다. int 는 4byte = 2^(8*4) = 4,294,967,296개의 숫자를 포현할 수 있기 때문에 왠만한 수는 다 표현할 수 있다. 정말 큰 수가 필요한 경우는 다르겠지만…

기본적으로 이렇게 int 변수를 선언하게 되면 우리가 흔히 알고 있는 RAM 에 4byte만큼의 공간이 확보된다. 이 부분이 중요하다. 데이터 타입을 제대로 사용하는 것은 코드를 최적화하는데 중요한 작업이다. RAM은 값비싼 메모리이고 제한적이기 때문에, 빠른 속도를 요구하는 분야에서는 번거럽더라도 직접 자료형을 선언하는 언어를 사용하는 것이다. 이를 정적언어 (반대의 경우 동적언어)라고 한다.

Related Posts