Backend/Java

[Java] 변수(Variable) - TIL 221209

짜잉이 2022. 12. 10. 00:00

📖 자바의 정석 Chapter 02 참고


2. 변수의 타입

기본형과 참조형

자료형은 크게 '기본형', '참조형' 두 가지로 나눌 수 있다.

 

기본형(primitive type): 계산을 위한 실제 값(data)를 저장한다. 모두 8개

e.g. 논리형(boolean), 문자형(char), 정수형(byte, short, int, long), 실수형(float, double)

 

참조형(reference type): 객체의 주소(address)를 저장한다.

e.g. 기본형 8개를 제외한 나머지 타입.

 

=> 기본형의 종류를 얘기할 때는 '자료형(data type)', 참조형 변수의 종류를 구분할 때는 '타입(type)'이라는 용어를 사용한다. '타입(type)'은 '자료형(data type)'을 포함하는 넓은 의미의 개념이다. 두 용어는 굳이 구분하지 않아도 된다.

 

참조형 변수(참조변수) 선언과 초기화

//변수이름 앞에 타입을 적는데 참조변수의 타입은 클래스의 이름이다.
클래스이름 변수이름; //변수의 타입이 기본형이 아닌 것들은 모두 참조변수이다.

//Date클래스 타입의 참조변수 today를 선언.
//참조변수는 null 또는 객체의 주소를 값으로 갖는다.
Date today = new Date(); //Date객체를 생성해서, 그 주소를 today에 저장
  • 참조형 변수(참조변수)를 선언할 때는 변수의 타입으로 클래스 이름을 사용한다. 그래서 클래스 이름이 참조변수의 타입이 된다. 새로운 클래스를 작성한다는 것은 곧 새로운 참조형을 추가하는 것이라고 할 수 있다.

 

2.1 기본형(primitive type)

종류 \ 크기 1 byte 2 byte 4 byte 8 byte
논리형 boolean      
문자형   char    
정수형 byte short int long
실수형     float double
  • 정수형 중에서는 int형이 기본 자료형(default data type), 실수형 중에서는 double이 기본자료형이다.
  • boolean은 true와 false 두 가지 값만 표현하므로 가장 작은 크기인 1 byte이다.
  • char은 자바에서 유니코드(2 byte 문자체계)를 사용하므로 2 byte이다.
  • byte는 크기가 1 byte라서 byte이다.
  • int(4 byte)를 기준으로 짧아서 short(2 byte), 길어서 long(8 byte)이다.
  • float는 실수값을 부동소수점(floating-point)방식으로 저장하기 때문에 float이다.
  • double은 float보다 두 배의 크기(8 byte)를 갖기 때문에 double이다.

 

2.2 상수와 리터럴(constant & literal)

상수(constant): 값을 저장할 수 있는 공간. 한 번 값을 저장하면 다른 값으로 변경할 수 없다.

final int MAX_SPEED = 10; //상수 MAX_SPPED를 선언 & 초기화

final int MAX_SPPED;         //에러. 상수는 선언과 동시에 초기화 해야함.
final int = MAX_VALUE = 100; //OK. 선언과 동시에 초기화 했음.
MAX_VALUE = 200;             //에러. 상수의 값은 변경할 수 없음.
  • 상수를 선언하는 방법은 변수와 동일하며, 변수의 타입 앞'final' 키워드를 붙여주면 된다.
  • 상수는 반드시 선언과 동시에 초기화 해야 하고, 그 이후에는 상수의 값을 변경할 수 없다.
  • 상수의 이름은 모두 대문자로 하는 것이 관례이며, 여러 단어로 이루어진 경우 '_'로 구분한다.
  • 상수는 리터럴에 '의미있는 이름'을 붙여서 코드의 이해와 수정을 쉽게 만든다. 수정할 때 상수의 초기화만 다른 값으로 변경해주면 된다.

 

리터럴(literal): '상수'의 다른 이름. 그 자체로 값을 의미한다.

//변수타입 변수이름 = 리터럴;
int year = 2014;

//final키워드 변수타입 상수 = 리터럴;
final int MAX_VALUE = 100;

 

리터럴의 타입과 접미사

정수형과 실수형에는 여러 타입이 존재하므로, 리터럴에 접미사를 붙여서 타입을 구분한다.

 

정수형

  • long 타입의 리터럴에 접미사 'l' 또는 'L'을 붙인다. 헷갈리기 쉬우므로 대문자 'L'을 사용하는 것이 좋다.
  • 접미사가 없으면 int 타입의 리터럴이다.
  • byte와 short타입의 리터럴은 존재하지 않고 byte와 short타입의 변수에 값을 저장할 때는 int 타입의 리터럴을 사용한다.
  • 정수형 리터럴의 중간에 구분자'_'를 넣어 큰 숫자를 읽기 쉽게 쓸 수도 있다.
  • 10진수 외에도 2, 8, 16진수로 표현된 리터럴을 변수에 저장할 수 있다.
  • 16진수는 리터럴 앞에 접두사 '0x' 또는 '0X'를, 8진수의 경우에는 '0'을 붙인다.
int octNum = 010;  //8진수 10, 10진수로 8
int hexNum = 0x10; //16진수 10, 10진수로 16
int binNum = 0b10; //2진수 10, 10진수로 2

 

실수형

  • float 타입의 리터럴에는 접미사 'f' 또는 'F'를 붙인다.
  • double 타입의 리터럴에는 접미사 'd' 또는 'D'를 붙인다.
float pi = 3.14f;     //접미사 f 대신 F를 사용해도 된다.
double rate = 1.618d; //접미사 d 대신 D를 사용해도 된다.

float pi = 3.14;      //에러. float타입 변수에 double타입 리터럴 저장 불가. 3.14f (o)
double rate = 1.618;  //OK. 접미사 d는 생략할 수 있다.
  • 실수형에서는 double이 기본 자료형이라서 접미사'd'는 생략 가능하다. 실수형 리터럴인데 접미사가 없다면 double 타입 리터럴이다.

 

타입의 불일치

리터럴 타입은 저장될 변수의 타입과 일치하는 것이 보통이지만, 타입이 달라도 저장범위가 넓은 타입에 좁은 타입의 값을 저장하는 것은 허용된다.

int i = 'A'       //OK. 문자 'A'의 유니코드인 65가 변수 i에 저장된다.
long l = 123;     //OK. int(4 byte)보다 long(8 byte)타입이 더 범위가 넓다.
double d = 3.14f; //OK. float(4 byte)보다 double(8 byte)타입이 더 범위가 넓다.

 

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

  • 문자열 리터럴은 " "안에 아무런 문자도 넣지 않는 것을 허용하며, 이를 빈 문자열(empty string)이라고 한다.
  • 그러나 문자 리터럴반드시 ' '안에 하나의 문자가 있어야 한다.
  • 기본형과 참조형의 구별 없이 어떤 타입의 변수도 문자열과 덧셈연산을 수행하면 그 결과는 문자열이 된다.
문자열 + any type → 문자열 + 문자열 → 문자열
any type + 문자열 → 문자열 + 문자열 → 문자열

e.g. 7 + "  " → "7" + "  " → "7  "
       "  " + 7 → "  " + "7" → "  7"
       
       7 + "7" → "7" + "7" → "77"
       
       7 + 7 + " " → 14 + " " → "14" + " " → "14"
       " " + 7 + 7 → "7" + 7 → "7" + "7" → "77"
        
       true + " " → "true" + " " → "true"
       null + " " → "null" + " " → "null"
  • 덧셈 연산자는 왼쪽에서 오른쪽 방향으로 연산을 수행한다. 결합순서에 따라 결과가 달라지는 것에 주의하기!
  • 7과 같은 기본형 타입의 값을 문자열로 변환할 때는 아무런 내용도 없는 빈 문자열(" ")을 더해주면 된다.

 

2.3 형식화된 출력 - printf()

  • println(): 변수의 값을 그대로 화면에 출력한다. 값을 변환하지 않고는 다른 형식으로 출력할 수 없다.
  • printf(): '지시자(specifier)'를 통해 변수의 값을 여러가지 형식으로 변환하여 출력할 수 있다. 같은 값이라도 다른 형식으로 출력하고 싶을 때 사용한다. 
    • println()과 달리 printf()는 출력 후 줄바꿈을 하지 않는다.
    • 줄바꿈을 하려면 지시자 '%n'을 따로 넣어줘야 한다.
    • printf()의 지시자
지시자 설명
%b 불리언(boolean) 형식으로 출력
%d 10진(decimal) 정수의 형식으로 출력
%o 8진(octal) 정수의 형식으로 출력
%x, %X 16진(hexa-decimal) 정수의 형식으로 출력
%f 부동소수점(floating-point)의 형식으로 출력
%e, %E 지수(exponent) 표현식의 형식으로 출력
%c 문자(character)로 출력
%s 문자열(string)으로 출력

~~~~~(p38-39 내용)

 

 

3. 진법

3.1 10진법과 2진법

  • 지금까지 대부분의 컴퓨터는 2진 체계로 설계되었다. 2진법을 알지 못하면 컴퓨터의 동작원리나 데이터 처리 방식을 온전히 이해할 수 없다. 
  • 2진법은 0과 1로만 데이터를 표현한다. 자리수가 많아지긴 해도 2진수는 10진수를 온전히 표현할 수 있고 연산도 10진수와 동일하다.
2진수 10진수
1 + 1 = 10
2진수는 2가 없으므로 자리 올림이 발생해서 10이 된다.
9 + 1 = 10
11 + 1 = 100 99 + 1 = 100

 

3.2 비트(bit)와 바이트(byte)

  • 비트(bit, binary digit): 한 자리의 2진수. 1 비트는 컴퓨터가 값을 저장할 수 있는 최소단위이다.
  • 바이트(byte): 1 비트 8개를 묶은 데이터의 기본 단위. 1 byte(=8 bit)
  • 워드(word): CPU가 한 번에 처리할 수 있는 데이터의 크기. 워드의 크기는 CPU의 성능에 따라 달라진다.
    e.g. 32 비트 CPU에서 1워드는 32 비트(4 바이트)이고, 64 비트 CPU에서는 64 비트(8 바이트)이다.
n비트로 표현할 수 있는 10진수
값의 개수: 2^n
값의 범위: 0 ~ 2^n -1

e.g. 4비트로 16개(2^4)의 값을 표현할 수 있으며, 4비트로 10진수를 표현한다면 범위는 '0 ~ 15(0 ~ 2^4 -1)'이다.

 

3.3 8진법과 16진법

  • 8진수2진수 3자리를, 16진수2진수 4자리를 각각 한자리로 표현할 수 있기 때문에 자리수가 짧아져서 알아보기 쉽고 서로 간의 변환방법 또한 매우 간단하다.
2진수 8진수 10진수 16진수
0 0 0 0
1 1 1 1
10 2 2 2
11 3 3 3
100 4 4 4
101 5 5 5
110 6 6 6
111 7 7 7
1000 10 8 8
1001 11 9 9
1010 12 10 A
1011 13 11 B
1100 14 12 C
1101 15 13 D
1110 16 14 E
1111 17 15 F
10000 20 16 10

 

2진수를 8진수, 16진수로 변환

  • 2진수 → 8진수: 2진수를 뒤에서부터 3자리씩 끊어서 그에 해당하는 8진수로 바꾼다. (8진수 한 자리=2진수 3자리)
  • 2진수 → 16진수: 2진수를 뒤에서부터 4자리씩 끊어서 그에 해당하는 16진수로 바꾼다. (8진수 한 자리=2진수 4자리)
    e.g. 1010101100(2진수) = 1254 (8진수) = 2AC (16진수)

 

3.4 정수의 진법 변환

10진수를 n진수로 변환

10진수를 다른 진수로 변환하려면, 해당 진수로 나누고 나머지 값을 옆에 적는 것을 더 이상 나눌 수 없을 때까지 반복한 다음 마지막 몫과 나머지아래부터 위로 순서대로 적으면 된다. 

⇒ n진수로 변환하려면, n으로 반복해서 나누기만 하면 된다.

~~~~~~(이미지 넣기)

 

n진수를 10진수로 변환

어떤 진법의 수라도 10진수로 변환하는 방법은 똑같다. 각 자리 수에 해당 단위의 값을 곱해서 모두 더하면 된다.

e.g. 123(10진수) = 1 * 10^2 + 2 * 10^1 + 3 * 10^0

        101110(2진수) = 1 * 2^5 + 0 * 2^4 + 1 * 2^3 + 1 * 2^2 + 1 * 2^1 + 0 * 2^0 = 32 + 8 + 4 + 2 = 46(10진수)

        1460(8진수) = 1 * 8^3 + 4 * 8^2 + 6 * 8^1 + 0 * 8^0 = 512 + 256 + 48 + 0 = 816(10진수)

        64F(16진수) = 6 * 16^2 + 4 * 16^1 + F(15) * 16^0(1) = 1536 + 64 + 15 = 1615(10진수)

 

3.5 실수의 진법변환

10진 소수점수를 2진 소수점수로 변환하는 방법: 10진 소수점수에 2를 계속 곱한다.

e.g. 10진수 0.625를 2진수로 변환하기

 

10진 소수에 2를 곱하고 결과에서 소수부만 가져다가 다시 2를 곱한다. 소수부가 0이 될 때까지 위 과정을 반복한다.

0.625 * 2 = 1.25 → 0.25 * 2 = 0.5 0.5 * 2 = 1.0

 

위의 결과에서 정수부만을 위에서 아래로 순서대로 적고 '0.'을 앞에 붙이면 된다.

0.625(10진수) → 0.101(2진수)

 

2진 소수점수를 10진 소수점수로 변환하는 방법

e.g. 0.625(10진 소수) = 6 * 10^-1 + 2 * 10^-2 + 5 * 10^-3  

       0.101(2진 소수) = 1 * 2^-1 + 0 * 2^-2 + 1 * 2^-3 = 1 * 0.5 + 0 * 0.25 + 1 * 0.125 = 0.625(10진 소수)   

 

3.6 음수의 2진 표현 - 2의 보수법

2의 보수법

  • 어떤 수의 'n의 보수'더했을 때 n이 되는 수를 말한다.
    e.g. 3과 7은 '10의 보수의 관계'에 있다.
           '2의 보수 관계'는 더해서 2가 되는 두 수의 관계를 말한다.
  • 2진수로 '10'은 자리올림이 발생하고 0이 되는 수를 뜻한다.
  • 2의 보수법: 서로 '2의 보수 관계'에 있는 두 2진수로 5와 -5처럼 절대값이 같고 부호가 다른 두 10진수를 표현하는 것.
    (부호가 다르고 절대값이 같은 두 정수의 2진 표현이 서로 '2의 보수'관계에 있다.)

 

음수를 2진수로 표현하기

  • 10진 음의 정수를 2진수로 변환하는 법
    : 10진 음의 정수의 절대값을 2진수로 변환하고 이 2진수의 '2의 보수'를 구하면 된다.
    e.g. -5(10진 음의 정수) → 5(10진수) 0101(2진수) → 1011(2진수)
  • 2의 보수 구하기: 서로 '2의 보수'의 관계에 있는 두 2진수를 더하면 '(자리올림이 발생하고) 0이 된다.'
    e.g. 0101 + 1011 = (1자리올림 발생했지만 4비트라서 버림)0000
    뺄셈보다 '2의 보수'를 더 간단히 구하는 방법은 '1의 보수'를 구한 다음 1을 더하는 방법이다.
2의 보수 = 1의 보수 + 1

('1의 보수'는 0을 1로, 1을 0으로만 바꾸면 된다.)
e.g. 2진수 '0101'의 '1의 보수'는 '1010'이다. 여기에 1을 더한 '1011'이 2의 보수가 된다.

 

음수의 2진 표현을 구하는 방법
1. 음수의 절대값을 2진수로 변환한다.
    : -5의 절대값인 5를 2진수로 변환한다. 10진수 5를 2진수로 변환하면 '0101'이다.
2. 1.에서 구한 2진수의 1을 0으로, 0은 1로 바꾼다. (1의 보수 구하기)
    : '0101'이 '1010'이 된다.
3. 2.의 결과에 1을 더한다. (2의 보수 구하기, 1의 보수 + 1)
    : '1010'에 1을 더하면 '1011'이 되고, 이것이 -5의 2진 표현이다.