[Java의 정석] 2장 변수

이정규·2022년 1월 11일
0

Java의 정석

목록 보기
2/7
post-thumbnail

자료형(data type)과 타입(type)의 차이

  • 자료형(data type) : 기본형은 저장할 값(data)의 종류에 따라 얘기하는 것
  • 타입(type) : 참조형으로 객체의 주소(4byte 정수)를 저장한다. 자료형(data type)보다 넓은 범위이다.

기본형(primitive type)

논리형 boolean(1byte)

다른 기본형과의 연산이 불가능하다.
True, False만 나타내려면 1bit로 0, 1을 나타내면 되지 않냐? 하겠지만 Java에서 데이터를 다루는 최소 단위가 byte이기 때문에 1byte이다.

문자형 char(2byte)

내부적으로 정수(유니코드)로 저장하기 때문에 정수형과 벼라반 다르지 않고 정수형, 실수형과 연산이 가능하다.

정수형 byte(1byte) short(2byte) int(4byte) long(8byte)

int형이 주로 쓰인다. 그 이유는 JVM의 피연산자 스택(operand stack)피연산자들을 4byte로 저장하기 때문이다. 이 때 연산을 하기위해서는 모두 4byte로 맞추기 때문에 byte, short형은 다시 형변환을 해야하는 연산이 생긴다. 그러므로 int형이 좀 더 효율적인 계산이 가능하다.
효율적인 실행보다 메모리를 절약하려면 byte나 short를 쓰자.

  • overflow가 발생하면 최댓값 -> 최솟값, 최솟값 -> 최댓값으로 된다.

실수형 float(4byte) double(8byte)

정밀도가 다르다. 정밀도는 10진수로 n자리의 수를 오차없이 저장할 수 있다는 뜻이다.
float는 정밀도 7자리이고 double은 정밀도 15자리이다. 그래서 double형이 주로 쓰인다.

  • overflow가 발생하면 무한대(infinity)가 된다.
  • underflow는 양의 최소값보다 작은 값이 되는 경우에 값이 0이 된다.

상수와 리터럴(constant & literal)

상수

상수는 한 번 저장하면 값을 변경할 수 없다. 상수의 선언 방법은 변수의 타입 앞에 final을 붙이면 된다.
상수의 네이밍은 모두 대문자로 하는 것이 관례이다.

리터럴

12, 3.14 "A"와 같은 값들이 우리가 본래 알던 상수다. 하지만 위처럼 프로그래밍에서는 "상수"라는 이름을 다르게 정의하였기 때문에 다른 이름이 필요했다. 이게 리터럴이다.

리터럴의 타입과 접미사

논리형, 문자형, 문자열

접미사가 따로 존재하지 않는다.

정수형

byte, short, int형은 접미사가 따로 존재하지 않는다.
long형은 "L" or "l"을 붙인다.
2, 8, 16진수를 위해서는 "0b", "0", "0x"의 접두사를 붙이면 된다.

실수형

float형은 "F", "f"
double형은 "D", "d"를 붙인다. 여기서 double은 실수형의 기본 자료형이라 생략이 가능하다.

문자 리터럴과 문자열 리터럴

char ch = 'J';
String name = "Java"; // String name = new String("Java");

char형은 단 하나의 문자만 저장 가능하다. 빈 문자를 허용하지 않는다.
String형은 여러 문자를 저장 가능하다. 빈 문자열을 허용한다. String은 클래스이다. new 연산자를 써야하지만 다음과 같은 표현도 허용한다.

연산

문자열 + any type => 문자열 + 문자열 = 문자열
any type + 문자열 => 문자열 + 문자열 = 문자열

유니코드

UTF-8

하나의 문자를 1~4byte의 가변크기로 표현한다.
영어와 숫자는 1byte, 한글은 3byte로 표현이 된다. 크기가 가변적이여서 다루기가 어렵다는 단점이 있다.

UTF-16

모든 문자를 2byte의 고정크기로 표현한다.
영어와 숫자가 모두 2byte로 표현이 되어 문서의 크기가 커진다는 단점이 있다.

인터넷에서는 전송속도가 중요하므로 문서의 크기가 작은 UTF-8인코딩으로 작성된 웹문서가 주로 쓰인다.

실수형의 저장방식

부동소수점수의 형태로 저장한다.

(a) : float
(b) : double

값 계산 = ±M×2E\pm M \times 2^E

부호(sign bit)

1bit의 형태로 0이면 양수, 1이면 음수를 나타내는 뜻이다.
정수형과 다르게 2의 보수법을 사용하지 않아 양수 -> 음수, 음수 -> 양수로 가려면 부호비트만 바꾸면 된다.

지수(exponent)

  • float : 8bit
    282^8 = 256 = -127 ~ 128의 값이 저장되지만 -127, 128은 NaN, 양의 무한대, 음의 무한대와 같이 특별한 값의 표현이 예약되어 있다.
    그래서 실제 사용되는 값은 -126 ~ 127이다.

    최댓값 : 21272^{127} = 103810^{38}
    최솟값 : 21262^{-126} * 2232^{-23} = 104510^{-45}
    최솟값에서 2232^{-23} 이 곱해지는 이유는 가수의 경우는 최솟값이 2232^{-23}, 최댓값은 1 이므로 최솟값의 범위가 더 커진다.

가수(Mantissa)

실제 값인 가수를 저장하는 부분이다.

  • float : 23bit
    23bit경우에는 2232^{23} => 약 7자리의 10진수를 나타낼 수 있다.
    이게 바로 float의 정밀도이다.
  • double : 52bit
    52bit = 2522^{52} => 약 16자리의 10진수를 나타낼 수 있다.

형변환

정수형

  • 정수형 -> 정수형
    큰 타입에서 작은 타입으로 변환할 경우에는 값손실(loss of data)이 일어날 수 있다.
    명시적 형변환을 할 경우에는 프로그래머가 의도했다고 생각하고 에러를 띄우지 않는다.

  • 정수형 -> 실수형
    int형은 최대 10자리의 정밀도를 요구하므로 float(정밀도 약 7자리)로 변경하면 정밀도차이에 의한 오차가 발생할 수 있다. 그러므로 double(정밀도 약 15자리)로 변환해야 오차가 발생하지 않는다.

    ex) 9123456 => (float로 변환) 91234568.0
    정밀도가 약 7자리이기 때문에 반올림이 발생한다.

실수형

  • 실수형 -> 실수형
    float타입의 범위가 넘는 값을 형변환 하는 경우에는 무한대, 0의 값을 얻는다.
    double(큰 타입) -> float(작은 타입) 형변환을 하는 경우에는 버려지는 값들은 반올림이 되기 때문에 값이 달라질 수 있다.
  • 실수형 -> 정수형
    소수점이하의 값들은 버린다. 반올림을 하지 않는다.

자동 형변환

  • char : 0 ~ 2162^{16}, short : 215-2^{15} ~ 21512^{15} - 1 이므로 같은 2byte라고 하더라도 범위가 달라 값 손실이 발생할 수 있어 자동 형변환을 수행할 수 없다.

참고
https://devlog-wjdrbs96.tistory.com/254
https://sangwoo0727.github.io/java/JAVA-3_cast/
Java의 정석 3판

profile
강한 백엔드 개발자가 되기 위한 여정

0개의 댓글