자바 변수, 프리미티브 타입, 리터럴

Tina Jeong·2021년 1월 4일
1

Re-자바

목록 보기
2/16

Contents

  • 변수 선언 및 초기화
  • 프리미티브 데이터 타입 종류, 범위, 기본값
  • 리터럴

자바 변수 선언과 초기화

자바는 기본적으로 미리 정해진 데이터 타입에 따라statically typed 변수를 선언하고 활용해야 한다. 아래의 예시로 설명하면 컴퓨터에게 int타입 num이라는 변수가 존재한다는 것과 초기에 저장된 값이 3이라는 것을 알려주는 식이다. num에 담긴 3이라는 값은 프로그래머의 의도에 따라 활용되고, 연산에 이용될 것이다.

int num = 3;

이때, 초기값 3을 넣어주지 않았다면 num에 담긴 기본값은 0이다. 자바의 데이터 타입들은 모두 기본값default value을 가지며, 그 종류에 따라 기본값은 다 다르다. 즉, 변수에 담긴 초기값이 3임을 정확하게 명시하는 과정이 '초기화'이다. 예시에서는 num을 선언함과 동시에 초기화했지만, 선언과 초기화를 분리할 수 도 있다.

int num;
num =3;

Primitive Data Type

프로그래밍 언어가 지원하는 기본적인 데이터 타입basic data type을 원시 데이터 타입primitive data type이라고 부른다. 자바는 사용자를 위해 방대한 reference type을 지원하니 그런 맥락에서 원시 데이터 타입이라는 명칭이 더 와닿는다.

자바는 정수형 4개, 실수형 2개, 문자형 1개, 논리형 1개 총 8개의 원시 데이터 타입을 지원한다. c 언어와 다른 점은 1 byte 정수형 타입 byte와 논리형 타입 boolean을 별도로 지원한다는 것. 자바 byte 타입은 c 언어에선 char 타입으로 대체된다.

정수형

이름값 범위기본값
byte-2^8~2^8-1 / [-128,127]0
short-2^16~2^16-1 / [−32,768, +32,767]0
int-2^31~2^31-1 / [−2,147,483,648, +2,147,483,647]0
long-2^64~2^64-1 / [-9,223,372,036,854,775,808,+9,223,372,036,854,775,807]0L

📌 C/C++의 long long 타입이 Java의 long과 값 범위가 동일하다.
C/C++에서는 대부분 long 타입과 int의 값 범위가 동일하다. 예외적으로 16 bit 플랫폼에서는 int의 크기가 16 bit이다. 여기에서는 long이 int형의 32 bit를 보장하는 형태로 사용된다.

정수형의 기본은 int이다

byte와 short 별다른 형변환이 없다면 int으로 자동형변환이 되어 계산된다. 마찬가지로 long에 대한 연산을 수행하려면 상수뒤에 L을 붙여줘야 한다.

경계값에 유의하기

프로그램 짤 땐 보통 int를 많이 쓰는데, 값이 쁠마 21억 안에서 만족되는지 의식적으로 체크한다. int 경계를 넘는 경우 long으로 바꿔써주면 보통 충분하다. 더 넘으면..String을 쓴다. 경계값을 넘는지 확인할 때는 Integer 클래스의 MAX_VALUE,MIN_VALUE 상수를 참조해서 사용하면 편하다.

int a;
...
if(a==Integer.MAX_VALUE) {
	sout("exceeded");
	break;
}

unsigned 그런 키워드 없다

자바는 unsigned 키워드를 지원하지 않는다.


출처: https://www.journaldev.com/33226/java-keywords

다만, 자바 8 이후 Integer wrapper class의 Integer.parseUnsignedInt(String s),Integer.toUnsignedString(int i)을 통해 unsigned representation이 가능해졌다.

String twoPointwoBillion = "2,200,000,000";
int unsignedint = Integer.parseUnsignedInt(twoPointoneBillion.replaceAll(",",""));
System.out.println(Integer.toUnsignedString(unsignedint)); // 2200000000

또, compareUnsigned(int x, int y),divideUnsigned(int dividend, int divisor) 같은 메소드를 통해 unsigned 연산도 가능하다. 예를 들어 unsigned -1은 compareUnsigned에 인자로 넣어 1과 비교하면 -1이 더 크다고 계산된다.

실수형

이름값 범위기본값
float1.4E–45 ~ 3.4028235E+380.0f
double4.9E–324 ~1.7976931348623157E+3080.0d

E notation은 exponent 즉, 지수 표기이다. 1.4E-45는 1.4*10^-45을 의미한다.

데이터의 근삿값

실수형은 정확한 표기가 필요한 외화 환율, 돈 표현 등에는 적절하지 않다.(대신 java.math.BigDecimal을 이용한다.) 실수형 데이터 타입은 수의 표현 범위를 확대하기 위한 부동소수점 방식(부호,지수,유효숫자-가수- 부분으로 나누어 세 부분의 조합으로 숫자를 표현)을 사용해 근사값만 나타낼 수 있기 때문이다. 또한, 애초에 유한한 비트로 실수를 완전히 표현할 수 없다. (대부분의 소수는 이진소수로 나타낼 수 없다.) 0.1만해도 이진소수로 나타내면 무한소수가 된다. 자세한 내용은 IEEE 754 format이나 부동소수점으로 구글링하면 된다.

double a =0.0;
for(int i=0;i<10;i++) {
   a +=0.1;
}
System.out.println(a); //0.9999999999999999
System.out.println(0.1+0.2==0.3); // false
BigDecimal b = BigDecimal.ZERO;
for(int j=0;j<10;j++) {
	b = b.add(BigDecimal.valueOf(0.1));
}
System.out.println(b); //1.0

float 말고 double 쓰기

실수형의 default는 double이다. float을 사용하려면 숫자 표현 후위에 fF를 붙여줘야 한다. float은 유효숫자 9자리까지 표현가능하고, double은 18자리까지 표현가능하다. 그러나 float은 유효숫자 6자리까지, double은 유효숫자가 15자리까지 안전하므로 연산 범위가 넘어가지 않도록 주의한다.

float f = 5.3254e3f;
double d = 5.3254e3;

overflow 관련 value

실수형에서는 overflow 관련 exception이 발생하지 않기 때문에, value인 infinity,-infinity,0.0(underflow 발생시),NaN을 통해 exception을 판별할 수 있다.

double inf = 1.0/0.0;
double negInf = -1.0/0.0;
double negzero = 1.0/negInf;
double NaN = 0.0/0.0;

System.out.println(inf); //Infinity
System.out.println(negInf); //-Infinity
System.out.println(negzero); // -0.0
System.out.println(NaN); //NaN
System.out.println(NaN==NaN); //false
System.out.println(Double.isNaN(NaN)); //true

이때, NaN은 Not a Number의 준말로, 숫자가 아니기 때문에 자기 자신과의 동치를 판별해도 false가 된다. 그래서 NaN을 판별할 때는 Double 클래스의 isNaN 메소드를 사용한다.

문자형

이름값 범위기본값
char'\u0000'~'\uffff'/ [0~65,535]'\u0000'

char는 다양한 정수형 데이터 타입간 변환이 가능하다. 이 때, char는 2byte 짜리 unsigned 타입이라는 사실을 염두에 두어야 한다.

char는 Unicode를 나타내는 데이터 타입

자바는 작은 따옴표안에 \u로 시작하는 유니코드 시퀀스를 넣어두면 이를 char 타입으로 인식한다. 이스케이프 문자도 사용가능하다.

char a ='a', tab = '\t', nul = '\000', aleph = '\u05D0', slash = '\\';

논리형

이름값 범위기본값
booleantrue, false 딱 두 개false

자바에서 boolean을 사용할 때 주의할 점은, 숫자값으로 참/거짓을 나타낼 수 없다는 점이다.
참거짓을 정확하게 명시하여 사용해야 한다.

while(1) // syntax error

while(a!=b) 
while(true)

리터럴

Literal은 new 키워드를 활용한 instatiation 과정없이도 constant로서 존재할 수 있는 데이터 자체를 의미한다. 리터럴은 90% 원시 데이터 타입일 경우를 말하지만, 자바는 큰 따옴표로 묶인 String 데이터도 immutable한 문자열이라보고 리터럴을 지원한다. String은 자바 전반적으로 아주 많이 쓰이기 때문도 있는듯. 그 결과 다음과 같은 리터럴들이 존재할 수 있다.

0 true false 0.0 0.0f 5.3254e3 'a' "str" 1L 0x1a 0b11101 1234_5678

실수 리터럴의 기본타입은 double

앞에서도 언급했지만 자바의 실수 리터럴 기본 타입은 double이며, float 변수에 대입될 때도 double이 명시적 타입 변환이 이루어진 후 대입해야 한다. data loss는 감수해야하는 부분.

_로 가독성 높이기

16진수, 2진수를 리터럴로 표현할 수 있고, 숫자 리터럴 중간중간 underscore_를 이용해 가독성을 높여줄 수도 있다. 16진수/2진수 notation 바로 다음, 숫자 처음과 끝에는 underscore 넣을 수 없다.

int num1 = 0x_1b; // error
int num2 = 0b_1110; // error
int num3 = _123; //error
int num3 = _123_; //error

참고
https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html
https://ko.wikipedia.org/wiki/IEEE_754
https://www.secmem.org/blog/2020/05/15/float
Java in a Nutsell, 7th Edition

계속해서 문서를 업데이트하고 있습니다. 언제든지 댓글피드백 남겨주세요. 😉

profile
Keep exploring, 계속 탐색하세요.

0개의 댓글