Java의 정석(2) - 변수 variable

Chapter 02 변수 variable
김주혁's avatar
Mar 31, 2024
Java의 정석(2) - 변수 variable

1. 변수

 

1.1 변수란?

값을 저장할 수 있는 메모리상의 공간이다. 하나의 변수에 하나의 값만 저장할 수 있기 때문에, 새로운 값을 저장하면 기존 값은 사라진다.

1.2. 변수의 선언과 초기화

변수를 사용하려면, 먼저 변수를 선언해야 한다.
 
int age 변수타입 변수이름
 
  • 변수타입 ⇒ 저장될 값의 타입 지정
  • 변수이름 ⇒ 변수에 붙인 네이밍, 메모리상의 공간에 이름을 붙이고 그 메모리를 사용하는 이름
 
변수를 선언하면 메모리 빈 공간에 ‘변수 타입’에 걸맞는 저장공간이 확보된다. 이 저장공간은 변수이름을 통해 사용할 수 있다.
 
변수의 초기화
변수를 선언한 이후부터 변수를 사용할 수 있지만, 반드시 초기화해야 한다. 메모리는 여러 프로그램이 공유하는 자원이기 때문에 프로그램에 저장된 알 수 없는 garbage value가 남아있을 수 있다.
 
결국 변수의 초기화란, 변수를 사용하기 전 임의의 메모리 값을 새롭게 비워주고 저장하는 것이다.
int year = 24; int age = 29; System.out.println(year); // 24 System.out.println(age); // 29 year = age + 2000; age = age + 1; System.out.println(year); // 2029 System.out.println(age); // 30
 
두 변수의 값 교환하기
int x = 10; int y = 20; x = y; y = x; int temp; // 임시변수
x에 이미 y를 할당해버려서, x의 값이 20으로 초기화 됐기 때문에 10이란 값은 이제 참조할 수 없다. x값을 다시 사용하고 싶다면 임시변수를 활용해야 한다.
 

1.3. 변수의 명명규칙

자바 프로그래밍에서 모든 이름은 식별자로 불린다. 식별자는 같은 영역에서 구분되야 한다. 식별자를 만들 때는 다음과 같은 규칙을 지켜야 한다.
  • 대소문자가 구분되며 길이에 제한이 없다. ⇒ True와 true는 서로 다른 것으로 간주된다.
  • 예약어를 사용해서는 안된다. ⇒ true는 예약어라 사용할 수 없지만, True는 가능하다.
  • 숫자로 시작해서는 안된다. ⇒ top10은 가능하지만, 10top은 불가능 하다.
  • 특수문자는 ‘_’와 ‘$’만 허용한다. ⇒ $sharp는 허용되지만, S#arp는 허용되지 않는다.
 
이런 가장 기본적인 규칙외에도
 
  • 클래스 이름의 첫 글자는 언제나 대문자로 시작한다. ⇒ 변수와 메서드의 이름의 첫 글자는 항상 소문자로 시작한다.
  • 여러 단어로 이루어진 이름은 단어의 첫 글자를 대문자로 한다.
  • 상수의 이름은 모두 대문자로 한다. 여러 단어로 이루어진 경우 ‘_’로 구분한다.
 

2. 변수의 타입

값의 종류에 따라 값이 저장될 공간의 크기와 저장형식을 정의한 것이 자료형이다.
 
기본형과 참조형
 
자료형은 크게 ‘기본형’과 ‘참조형’으로 나눌 수 있다.
  • 기본형 ⇒ 실제 값을 저장한다.
    • 논리형(boolean)
    • 문자형(char)
    • 정수형(byte, short, int, long)
    • 실수형(float, double)
    • 계산을 위한 실제 값을 모두 8개로 가지고 있다.
  • 참조형 ⇒ 어떤 값이 저장되어 있는 주소를 값으로 갖는다. 기본형 변수와 같이 변수이름 앞에 타입을 적어준다.
    • Date today = new Date(); // Date 객체를 생성해서, 그 주소를 today에 저장한 것으로 Date 클래스를 타입으로 갖는다.
       
자바는 C와 달리 참조형 변수 간의 연산을 할 수 없으므로 실제 연산은 기본형 변수로 사용된다.
💡
메모리에는 1byte 단위로 일련번호가 붙어있는데, 이 번호를 메모리 주소라고 한다.
 
 
 

2.1 기본형

  • 논리형(boolean)
    •  
      true와 false를 값으로 갖으며, 조건식과 논리적 계산에 사용된다. boolean은 다른 기본형과 연산이 불가능하다. 즉, boolean을 제외하면 기본형들끼리 연산과 변환이 가능하다.
 
  • 문자형(char)
    •  
      문자를 저장하는데 사용되며, 변수에 하나의 문자만 저장할 수 있다. 문자를 내부적으로 정수(유니코드)로 저장하는 것이기 때문에, 정수형 또는 실수형과도 연산이 가능하다.
 
  • 정수형(byte, short, int, long)
    •  
      정수를 저장하는데 사용되며, 주로 int가 사용된다. int가 CPU가 가장 효율적으로 처리할 수 있는 타입이다. 절약하고 싶다면 byte(이진 데이터)나 short(C언어와의 호환)을 사용하자.
 
  • 자료형의 크기
    •  
    • 1 byte, 8bit ⇒ boolean / byte
    • 2 byte ⇒ chart / short
    • 4 byte ⇒ int / float
    • 8 byte ⇒ long / double
 
  • 추가적인 정보
    • boolean은 true / false만 표현할 수 있기 때문에 1 바이트
    • char은 자바에서 유니코드(2 byte 문자체계)를 사용하므로 2 바이트
    • byte는 크기가 1 byte라서 1 바이트
    • int를 기준으로 짧아서 short, 길어서 long
    • float은 실수 값을 부동소수점방식으로 저장하기 때문에 float
    • double은 float보다 두 배의 크기를 갖기 때문에 double
 
크게 외울 필요는 없지만, 정수형은 -2^n-1 ~ 2^n-1이라는 정도만 기억하면 된다. 예를 들면, int의 경우 bit 32이기 때문에 -2^31 ~ 2^31 -1이다.
 

2.2 상수와 리터럴

상수
상수는 변수와 달리 한 번 값을 저장하면 값을 변경할 수 없다. 상수를 선언하는 방법은 final을 붙여주는 것이다.
final int MAX_SPEED = 10;
상수는 선언과 동시에 초기화해야 한다.
 
리터럴
리터럴은 상수의 다른 이름이다. 굳이 상수와 구분하는 이유는,
int year = 2024; final int MAX_VALUE = 100;
 
2024와 100이 리터럴로서 상수가 곧 리터럴이지만, 리터럴은 그 자체로 값을 의미하기 때문에 리터럴에 의미 있는 변수를 붙이는 것이다.
 
리터럴의 타입과 접미사
자바 17부터 리터럴 중간에 ‘_’ 구분자를 사용할 수 있게 됐다. 정수형의 경우 접미사 L을 붙이기도 하고, 실수형의 경우 float은 f double은 d를 붙이기도 한다.
 
타입의 불일치
리터럴 타입은 저장될 변수의 타입과 일치해야 하지만, 타입이 달라도 저장범위가 넓은 타입에 좁은 타입의 값을 저장하는 것은 허용된다.
 
int i = 'A' // 문자 A의 유니코드인 65를 변수 i에 저장 long l = 123; // int 보다 long이 더 크다
 
하지만, 리터럴 타입이 변수 타입보다 넘어가면 컴파일 에러가 발생한다.
 
byte와 short는 리터럴이 따로 존재하지 않기 때문에 int 타입의 리터럴을 사용한다. 단 , 범위를 포함하는 값에 한 한다.
 
문자 리터럴과 문자열 리터럴
char타입은 단 하나의 문장 예를 들면, Java는 저장하지 못하고 J만 저장할 수 있다. 따라서 두 문자 이상은 String을 사용해야 한다.
 
따라서, 문자 하나를 감싼 것을 문자 리터럴이라 부르고 두 문자 이상을 감싼 경우 문자열 리터럴이라고 하며
String str = ""; // OK, 내용이 없는 빈 문자열 char ch = ''; // X, 문자 리터럴은 빈 문자로 초기화 될 수 없다. char ch = ' '; // O, 공백으로 초기화
 

2.3 형식화된 출력 - printf()

println()은 모든 값을 출력해주기 때문에, 읽는 것은 불편하며 prinf()를 사용하여 지시자를 통해 여러 형식으로 바꿔 출력해줄 수 있다.
System.out.printf("age:%d", age); System.out.printf("age:%d", 14); System.out.printf("age:14"); => 모두 age:14
 
출력하려는 값이 2개라면, 지시자도 2개 3개 이상이라면 그 n개에 맞춰 사용해야 한다.
System.out.printf("age:%d year:%d", 14, 24); // "age:14 year:2024"
 
println과 달리 printf는 줄 바꿈을 하지 않는다. 줄 바꿈을 원한다면 따로 %n을 사용해야 한다.
System.out.printf("age:%d%n", 14);
 
printf의 지시자 중 자주 사용되는 것
  • %b ⇒ boolean 형식으로 출력
  • %d ⇒ 10진수 정수로 출력
  • %o ⇒ 8진수 정수로 출력
  • %x, %X ⇒ 16진수 정수로 출력
  • %f ⇒ 부동 소수점 형식으로 출력
  • %e, %E ⇒ 지수 표현식으로 출력
  • %c ⇒ 문자로 출력(char)
  • %s ⇒ 문자열로 출력(string)
    •  
10진수를 2진수로 출력해주는 지시자는 없기 때문에, 정수를 2진 문자열로 변환해주는 Integer.toBinaryString(int i)를 사용해야 한다. 이 메서드는 정수를 2진수로 변환해서 문자열을 반환하므로 지시자 %s를 사용했다.
 
System.out.printf("binNum=%s%n", Integer.toBinaryString(age));
 
C언어에서는 char타입의 값을 지시사 %d로 출력할 수 있지만, 자바에서는 그렇지 않다. 아래와 같이 int 타입으로 형변환해야만 %d로 출력할 수 있다.
 
System.out.printf("c = %c, %d %n", c, (int)c);
 
실수형은 %f가 주로 쓰이고, %e는 지수형태로 출력할 때, %g는 값을 간략하게 표현할 때 사용한다. %f는 기본적으로 소수점 아래 6자리 까지만 출력하기 때문에, 7자리에서 반올림한다.
 

2.4 화면에서 입력받기 - Scanner

Scanner 클래스를 사용하려면, 한 문장을 추가해야 한다.
import java.util.*
 
 

3. 진법

 

3.1 10진법과 2진법

일상에서 주로 사용하는 것은 10진법이다. 그러나 컴퓨터는 2진 체계로 설계 됐다. 2진법은 0과 1로 데이터를 표현하기 때문에 10진법에 비해 많은 자리 수를 필요로 한다.
 
10진법을 2진법으로는 어떻게 바꾸는 걸까?
 
예를들면, 25라는 숫자가 있고 이걸 2진법으로 바꾸려면
25를 2로 나눕니다.나눈 몫을 다시 2로 나눕니다.나눈 나머지를 오른쪽에서부터 차례로 적어줍니다.
25 ÷ 2 = 12 ... 1 12 ÷ 2 = 6 ... 0 6 ÷ 2 = 3 ... 0 3 ÷ 2 = 1 ... 1 1 ÷ 2 = 0 ... 1
대충 이런식이다. 특정 값에서 2로나눴을 때 몫이 0이라면 0 아니라면 1 이런식으로 하나씩 쌓아가면 된다. 그렇다면 9는 2진법으로 몇 일까?
 
정답은 1001이다.
 

3.2 비트와 바이트

한 자리의 2진수를 비트라고 하며, 1비트는 컴퓨터가 값을 저장할 수 있는 최소 단위다. 1비트는 너무 작은 단위라 1비트 8개를 묶어 1바이트라고 한다.
 
이 외에도 워드라는 단어가 있는데, 이는 CPU가 한 번에 처리할 수 있는 데이터의 크기를 의미한다. 워드의 크기는 CPU 성능에 따라 달라진다.
 

3.3 8진법과 16진법

8진수는 2진수 3자리를, 16진수는 2진수 4자리를 각각 한자리로 표현할 수 있기 때문에 자리수가 짧아져서 알아보기 쉽고 서로간 변형도 매우 간단하다.
 
만약 100이라는 10진법의 값을 8진법으로 바꾸면, 100을 8로나눠
100을 8로 나눕니다.나눈 몫을 다시 8로 나눕니다.나눈 나머지를 오른쪽에서부터 차례로 적어줍니다.
100 ÷ 8 = 12 ... 4 12 ÷ 8 = 1 ... 4 1 ÷ 8 = 0 ... 1
이런식으로 100을 8진법으로 바꾸면 144가 된다.
 
그렇다면, 16진수는 어떨까?
 
100을 16으로 나누면, 몫이 6이고 나머지가 4다. 따라서 100의 16진수는 64다.
 
8진법은 값을 표현하는데 8개의 기호가 필요하므로 0~7의 숫자를 기호로 사용하면 되지만, 16진법은 16개의 기호가 필요하기 때문에 0~9로는 부족하다. 그래서 A~F를 추가적으로 사용한다.
 

3.4 정수의 진법 변환

10진수를 n진수로 변환
다른 진수로 변환하려면, 해당 진수로 나누고 나머지 값을 옆에 적는 것을 더 이상 나눌 수 없을 때 까지 반복한 다음 마지막 몫과 나머지를 아래부터 위로 순서대로 적으면 된다.
 
n진수를 10진수로 변환
어떤 진법의 수건 각 자리의 수에 해당 단위의 값을 모두 곱해서 모두 더하면 된다. 예를 들어 10진수 123은 다음과 같이 풀어쓸 수 있다.
 
1 * 10^2 + 2*10^1 + 3*10^0 = 123
 
마찬가지로 2진수 또한 다음과 같다.
 
101110이라면,
 
1 * 2^5 + 0 * 2^4 + 1 * 2^3 + … 0 * 2^0 = 46이다.
 

3.5 실수의 진법 변환

10진 소수점수를 2진 소수점수로 변환하는 방법
10진 소수점을 2진 소수점으로 바꾸는 방법은 정수와 반대로 10진 소수점수에 2를 계속 곱한다.
 
0.625를 2진법으로 바꾸는 방법은 다음과 같다.
 
  1. 10진 소수에 2를 곱한다. ⇒ 0.625 * 2 = 1.25
  1. 위 결과부터 소수부만 가져와 다시 2를 곱한다. ⇒ 0.25 * 2 = 0.5
  1. 1과 2의 과정을 소수부가 0이 될 때 까지 반복한다. 0.5 * 2 ⇒ 1.0
 
따라서 0.625를 2진법으로 바꾸면, 0.101이다.
 
2진 소수점수를 10진 소수점수로 변환하는 방법
정수와 반대로 10^-n을 곱하면 된다.
 

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

2의 보수법
어떤 수의 n의 보수는 더했을 때 n이 되는 수를 말한다. 7의 ‘10의 보수’는 3이다. 3의 ‘10의 보수’는 7이다. 10진수의 2는 2진수로 ‘10’이다. 2진수로 ‘10은 자리올림이 발생하고 0이 되는 수를 의미한다.
 
2의 보수 관계에 있는 두 2진수를 더하면 0이 된다.
 
음수를 2진수로 표현하기
보수 관계에 있는 값을 구하는 것으로 된다. 1의 보수를 구한 다음 1을 더해주면 2의 보수를 구할 수 있다.
예를 들면, 0101이라는 2진수가 있을 때 0은 +1을 해주고 1은 -1을 해주면, 1010이되고 여기에 +1을 더하면 1011이 된다. 1011이 0101의 2의 보수다.
 

4. 기본형

 

4.1 논리형 - boolean

true / false로 이루어진 논리 자료형이다.
 

4.2 문자형 - char

단 하나의 문자만을 저장할 수 있다.
char ch = "A";
 
위 문장은 변수에 문자가 저장되는 것 같지만 사실은 문자의 유니코드인 int(정수)가 저장된다. 그래서 문자 대신 유니코드를 저장해도 같은 결과를 변환을 통해 얻을 수 있다.
 
특수문자 다루기
tab이나 backspace 등의 특수문자를 사용하려면, 특별한 방법을 사용한다.
특수문자
문자 리터럴
tab
\t
backspace
\b
form feed
\f
new line
\n
carriage return
\r
역슬래쉬
\\
작은 따옴표
\’
큰 따옴표
\”
유니코드 16진수 문자
\u유니코드(char a=”\u0041”)
 
char 타입의 표현형식
char눈 2 byte이며, 16자리 2진수로 표현할 수 있는 정수의 개수인 65536개의 코드를 사용할 수 있고 char형 변수는 이 범위 내의 코드 중 하나를 저장할 수 있다.예를 들어, 문자 “A”를 저장하면 2진수 00000000010000001로 저장된다.
char ch = "A"; short s = 65; System.out.println(ch); // A System.out.println(s); // 65
 
인코딩과 디코딩
문자를 코드로 변환하는 것을 인코딩, 반대로 코드를 문자로 변환하는 것을 디코딩이라고 한다.
 
 

4.3 정수형 - byte, short, int, long

단위는 byte로서 다음과 같다.
 
byte(1) < short(2) < int(4) < long(8)
 
기본 자료형은 int다.
 
정수형의 표현형식과 범위
어떤 진법의 리터럴을 변수에 저장해도 실제로는 2진수로 변경되어 저장된다. 이 2진수는 정수형과 실수형이 있다.
 
정수형은 다음과 같은 형식으로 저장된다.
S > n-1 bit
 
  • S : 부호 비트(양수는 0, 음수는 1)
  • n : 타입의 크기(단위 bit)
 
n비트로 표현할 수 있는 값의 개수인 2^n개에서 절반인 0으로 시작하는 2^n-1개의 값을 양수의 표현에 사용하고 나머지 절반인 1로 시작하는 2^n-1개의 값은 음수 표현에 사용된다.
 
따라서 정수형은 타입의 크기만 알면, 최대값과 최소값을 쉽게 계산할 수 있다.
 
  • n비트로 표현할 수 있는 정수의 개수: 2^n개(= 2^n-1개 + 2^n-1개)
    • ⇒ 8 비트로 표현할 수 있는 정수의 개수 : 2^8개(2^7 + 2^7)
  • n비트로 표현할 수 있는 부호있는 정수의 범위: -2^n-1 ~ 2^n-1 - 1
    • ⇒ 8 비트로 표현할 수 있는 부호있는 정수의 범위 : -2^7 ~ 2^7 - 1
정수형의 선택기준
JVM에서는 피연산자 스택이 피연산자를 4 byte 단위로 저장하기 때문에 4byte 보다 작은 자료형을 계산 할 때는 4byte로 변경되어 계산된다. 따라서 int를 사용하는 것이 대부분은 효율적이다.
 
정수형을 다룰 때는 int, int를 넘어설 때는 long을 사용하는 것이 기본이다. short은 성능 보다 저장공간의 효율을 따질 때 사용하자
 
정수형의 오버플로우
타입이 표현할 수 있는 값의 범위를 넘어서는 것을 오버플로우라고 한다. 따라서 정수형 타입의 최대값에 +1을 더하면 최소값이 되고, -1을 빼면 최대값이 된다.
 
부호있는 정수의 오버플로우
부호있는 정수는 부호비트가 0에서 1이 될 때 오버플로우가 발생한다. 예를 들어 부호 있는 8비트 정수는
-128 ~ 127의 값을 가지지만, 127에 +1을 더하면 128이 아닌 -128이 된다.
 

4.4 실수형 - float, double

실수형의 범위와 정밀도
정수형과 달리, 실수형에서는 오버플로우가 발생하면 변수의 값은 무한대가 된다. 정수형과 달리 실수형은 오차가 발생할 수 있다는 단점이 있고, float형이 정밀도가 7이고 7이란 건 7자리의 10진수를 오차없이 저장할 수 있다는 뜻과 같다. 만약 7자리 이상의 정밀도가 필요하다면, 변수의 타입을 double로 해야 한다.
연산 속도나 메모리 성능 향상을 위해서는 float이고 정밀도를 높이고 싶다면 double을 선택해야 한다.
 
실수형의 저장형식
실수형은 값을 부동소수점수의 형태로 저장한다. 부동소수점수는 부호 S (Sign), 지수 E (Exponent), 가수 M (Mantissa) 모두 세 부분으로 이루어져 있다.
 
float: 1 + 8 + 23 = 32bit (4 byte) S(1) + E(8) + M(23)
 
  1. 부호(S)
    1.  
      부호비트를 의미하며 1bit이다. 0이면 양수를 1이면 음수를 의미한다.
 
  1. 지수(E)
    1.  
      float의 경우, 8 bit의 저장공간을 가진다. 지수의 최대 값이 8비트인 -127 ~ 128이기 때문에 float 타입으로 표현할 수 있는 최대값은 2^127이고 10진수로 10^38이다.
       
      그러나 float의 최소 값은 가수의 마지막 자리가 2^-23이므로 지수의 최소 값보다 20^-23배나 더 작은 값 약 10^-45다.
 
  1. 가수(M)
M은 실제 값인 가수를 저장하는 부분이다. float의 경우 2진수 23자리를 저장할 수 있다. 2진수 23자리로 약 7자리의 10진수를 저장할 수 있는데 이것이 바로 float의 정밀도이다.
 
 

5. 형변환

 

5.1 형변환(캐스팅, casting)이란?

변수나 리터럴의 타입을 다른 타입으로 변경하는 것을 형변환이라고 한다.
 
예를 들어, int와 float의 값을 합쳐야 하는 경우, 두 값을 같은 타입 즉 둘 다 float으로 변환한 다음 더해야 한다.
 

5.2 형변환 방법

변환하고자 하는 변수나 리터럴 앞에 변환하고자 하는 타입을 괄호와 함께 붙여주면 된다.
(타입)피연산자 => (int)age
 
저 괄호를 캐스팅이라고 한다.
 
형변환 연산자는 그저 피연산자의 값을 읽어 지정 타입으로 변환하고 반환할 뿐, 피연산자인 변수의 값은 옇ㅇ변환 후에도 동일하다. 즉 메모리를 참조할 뿐이지 변경하는 것은 아니다.
 
기본형과 참조형간의 형변환은 불가능하다.
(char) 65 => "A"; (int) "A" => 65 (int) 1.6f => 1 (float) 10 => 10.0f
 

5.3 정수형간의 형변환

큰 타입에서 작은 타입으로 변환한다면 크기의 차이만큼 잘려나간다. 따라서 값 손실이 발생할 수 있다. 작은 타입에서 큰 타입으로 변화는 값 손실이 발생하지 않고 나머지는 0이나 1로 채워진다. 보통은 0이지만, 변환 값이 음수인 경우 빈 공간을 1로 채운다.
 

5.4 실수형 간의 형변혼

실수형에서도 정수형처럼 작은 타입에서 큰 타입으로 변환하는 경우, 빈 공간을 0으로 채운다.
 
만약, float 타입의 범위를 넘는 값을 float으로 형변환하는 경우 +- 무한대 또는 +-0을 결과로 얻는다.
 

5.5 정수형과 실수형 간의 형변환

좀 더 복잡하다.
 
정수형을 실수형으로 변환
정수는 소수점이하의 값이 없으므로 비교적 간단하다. 그저 정수를 2진수로 변환한 다음 정규화를 거쳐 실수의 저장형식으로 변경될 뿐이다.
 
실수형을 정수형으로 변경하는 경우 훨씬 큰 저장범위기 때문에 별 무리가 없다. 다만 한 가지 주의할 점은 실수형의 정밀도의 제한으로 오차가 발생할 수도 있다는 것이다.
 
예를 들면, int의 최대값은 20억으로 최대 10자리의 정밀도를 요구한다. 하지만 float은 7자리의 정밀도만 제공하기 때문에 오차가 발생할 수 있어, double을 사용해야 한다.
 
실수형을 정수형으로 변환
실수형을 정수형으로 바꾼다면, 실수형의 소수점이하 값은 버려진다. 정수형의 표현 형식으로 소수점 이하의 값은 표현할 수 없기 때문이다. 그래서 실수형을 정수형으로 형변환할 때 반올림이 발생하지 않는다.
 
1.666을 int로 변환하면 1이된다. 만일 실수의 소수점을 버리고 남은 정수가 정수형의 저장범위를 넘는 경우 오버플로우한 결과를 얻을 수도 있다.
 

5.6 자동 형변환

컴파일러가 형편좋게 자동 형변환을 시켜줄 수도 있다. 그러나, 변수가 저장할 수 있는 값의 범위보다 더 큰 값을 형변환하려고 하면 에러가 발생한다. 그러나 명시적으로 형변환 해준 경우 형변환이 프로그래머의 실수가 아닌 의도적으러 간주하고 컴파일러는 에러를 발생시키지 않는다.
 
char ch = (char)1000; // 명시적 형변환
 
다음과 같은 계산식에서 형변환이 자주 생략된다.
int i = 3; double d = 1.0 + i; // double d = 1.0 + (double)i;
 
서로 다른 두 타입간의 덧셈에서 표현범위가 넓은 쪽으로 형변환되어 타입을 일치시킨 다음 연산을 수행한다.
 
컴파일러는
 
기존의 값을 최대한 보존할 수 있는 타입으로 자동 형변환한다.
 
다음은 형변환의 우열을 나타낸다.
 
byte ⇒ short ⇒ int = char ⇒ long ⇒ float ⇒ double
 
char와 short는 둘 다 2바이트지만 char와 short의 범위가 서로 달라 어느 쪽으로도 형변환도 값 손실이 발생할 수 있기 때문에 자동 형변환이 수행될 수 없다.
 
  • boolean을 제외한 나머지 7개의 기본형은 서로 형변환이 가능하다.
  • 기본형과 참조형은 서로 형변환할 수 없다.
  • 서로 다른 타입의 변수간의 연산은 형변환을 하는 것이 원칙이지만, 값의 범위가 작은 타입에서 큰 타입으로의 형변환은 생략할 수 있다.
 
Share article

vlogue