[혼공자] 02-3. 타입 변환

Benjamin·2023년 2월 10일
0

혼공자

목록 보기
6/27

02-3. 타입 변환

데이터 타입을 다른 데이터 타입으로 변환하는 것

두 변수의 타입이 동일 : 한 쪽 변수값을 다른 쪽 변수에 복사 저장 가능
두 변수의 타입이 불일치 : 값의 복사 저장이 가능할 수도 있고 그렇지 않을 수도 있음

byte a = 10;
int b = a;

위 코드에서 원래 10은 byte 타입의 값이었으나, 복사 저장할 때 int타입의 값으로 변환되었다.

자동 타입 변환

값의 허용 범위가 작은 타입이 허용 범위가 큰 타입으로 저장될 때 발생
프로그램 실행 도중 자동으로 발생

큰 허용 범위 타입 = 작은 허용 범위 타입

  • 기본타입의 허용범위 크기순
    byte < short < int < long < float < double

정수 타입이 실수 타입으로 저장될 경우에는 무조건 자동 타입 변환이 발생!
실수 타입은 정수 타입보다 허용 범위가 더 크기 때문이다.

Long var1 = 5000000000L;
float var2 = var1; // 5.0E9f 로 저장됨, double형에 해도 마찬가지

char 타입의 경우 int타입으로 자동 타입변환되면 유니코드 값이 int 타입에 저장된다.

자동 타입 변환에서의 예외!
char타입보다 허용 범위가 작은 byte타입은 char 타입으로 자동변환 될 수 없다.
char타입의 허용범위는 음수를 포함하지 않는데, byte타입은 음수를 포함하기 때문이다.
-> byte타입의 변수를 char 변수에 대입하면, 컴파일에러가 발생한다.

강제 타입 변환

큰 허용 범위 타입은 작은 허용 범위 타입으로 자동 타입 변환될 수 없다.
마치 큰 그릇에 가득 채운 물을 작은 그릇 안에 모두 넣을 수 없는것과 동일한 이치이다.
하지만 큰 그릇의 물을 작은 그릇 크기로 나눠서 한 부분만 작은 그릇에 넣는 것은 가능하다.

이와같이 큰 허용범위 타입을 작은 허용 범위 타입으로 강제로 나눠서 저장하는 것을 강제 타입 변환(캐스팅)이라고 한다.

캐스팅 연산자 괄호 () 를 사용하는데, 괄호안에 들어가는 타입은 나누는 단위이다.

작은 허용 범위 타입 = (작은 허용 범위 타입) 큰 허용 범위 타입

int var = 10;
byte value = (byte)var; //강제 타입 변환

int 타입은 char타입보다 더 큰 허용 범위를 가진다.
따라서 int는 char로 자동 변환 되지않지만, (char) 캐스팅 연산자를 사용해서 char타입으로 강제 변환할 수 있다.
이렇게 변환하는 이유는 문자를 출력할 수 있기 때문이다.

int var = 65;
char ch = (char)var;
System.out.println(ch); //A

실수 타입은 정수 타입으로 자동변환 되지 않기때문에, 강제 타입 변환을 사용해야한다.
이 경우 소수점 이하 부분은 버려지고 정수 부분만 저장된다.

double var = 3.14;
int val = (int)var; //3만 저장됨

정수 연산에서의 자동 타입 변환

정수 타입 변수가 산술 연산에서 피연산자로 사용되면 int 타입보다 작은 byte, short, char 타입의 변수는 int타입으로 자동 타입 변환되어 연산을 수행한다!

각각 타입이 int로 바뀐 후(선), 연산 수행(후)

byte x = 10;
byte y = 20;

byte result = x + y //컴파일에러! (Type mismatch : cannot convert from int to byte)
int result = x + y

타입변환을 줄이면 성능이 향상된다.

  • 컴파일 단계에서의 정수 연산
    자바는 실행 성능을 향상시키기 위해 컴파일 단계에서 연산을 수행할 수 있다.
    예를 들어 byte result = 10 + 20;과 같은 코드가 있을 때 자바 컴파일러는 컴파일 단계에서 10+20을 미리 연산해서 30을 만들고, result 변수에 이를 저장하도록 바이트 코드를 생성한다.
    따라서 이 경우에는 피연산자가 변수가 아니므로 int타입으로 변환을하지 않는다.

컴파일 단계에서의 정수 연산 파헤치기

자바가 실행성능 향상을 위해 컴파일 단계에서 수행하는 내용에 대해 실제로 살펴보자.

우선, byte 변수를 덧셈연산해서 결과변수에 집어넣는 코드를 보자.
핵심은 변수의 연산이다.

아래 코드는 .java 파일이다.

public class HelloApplication {
    public static void main(String[] args) {
        byte x = 10;
        byte y = 20;

        int result = x + y;
    }
}

위 코드를 실행하고 build폴더의 해당 .class 파일을 보면 아래 이미지와 같다.

이번에는 아래코드처럼 정수 리터럴을 연산하도록 해보자.

public class HelloApplication {
    public static void main(String[] args) {

        int result = 10 + 20;
    }
}

위 코드를 실행하고 build폴더의 해당 .class 파일을 보면 아래 이미지와 같다.

result에 왜 true가 들어가는지는 알 수 없으나, 10+20같은 정수 연산 코드는 보이지않는다.

--

이렇게 마무리하고, 책 내용을 이어서 보자.

정수 연산식에서 모든 변수가 int 타입으로 변환되는 것은 아니다.
두 피연산자 중 허용 범위가 큰 타입으로 변환되어 연산을 수행한다.

예를들어, int타입보다 허용 범위가 더 큰 long타입이 피연산자로 사용되면(결과 변수 타입x) 다른 피연산자는 무조건 long타입으로 변환하고 연산을 수행한다.
따라서 연산 결과를 long타입 변수에 저장해야 한다.

byte var1 = 10;
int var2 = 100;
long var3 = 1000L;
long result = var1 + var2 + var3;

자바에서 정수연산의 결과는 정수가 된다.

실수 연산에서의 자동 타입 변환

실수 타입 변수가 산술 연산식에서 피연산자로 사용될 경우 두 피연산가 동일한 타입이라면 해당 타입으로 연산되지만, 피연산자 중 하나가 double타입이라면 다른 피연산자도 double 타입으로 자동 타입변환되어 연산을 수행한다.
따라서 연산결과는 double타입이 된다.

선 변환, 후 수행!

int타입과 double 타입을 연산해도 동일한 과정을 거친다. int타입 피연산자가 double타입으로 자동 변환되고 연산을 수행한다.

만약, double타입의 피연산자를 int타입으로 연산을 수행하고싶으면, 강제 변환하고 연산하면된다.

int var = 10;
double val = 5.5;
int result = var + (int)val;

실수 리터럴 연산
자바에서 f 또는 F가 없는 실수 리터럴은 double타입으로 해석
따라서 연산 결과는 double 타입 변수에 저장해야함
-> 그렇지않고 float에 저장하면 컴파일에러 발생!
결과를 float 타입에 꼭 저장하고싶다면, 실수 리터럴 뒤에 f나 F를 붙여 컴파일러가 float타입임을 알도록 해야함
float result = 1.5f + 2.3f;

수학에서 1을 2로 나누면 0.5가 된다. 아래 코드는 어떨까?

int x = 1;
int y = 2;
double result = x/y; //0.0

코드에서는 0.5가 아닌, 0.0이 된다.
그 이유는 자바에서는 정수 연산의 결과는 정수이기 때문이다.
x/y의 연산 결과는 0이되고, 이를 double 타입 변수에 저장하기때문에 0.0이 되는것이다.

결과를 0.5로 내고싶다면, x/y를 정수연산이 아닌 실수연산으로 바꾸어야한다.
그 방법은 x,y 둘 중 하나 또는 둘 모두를 double 타입으로 변환하는것이다.
(float) 정수 (double) 정수

만약 (double)(x/y)로 잘못수정하면, 0.0을 얻는데 그 이유는 x/y가 먼저 연산되어 0이되고 여기에 double을 적용하기떄문이다.

+ 연산에서의 문자열 자동 타입 변환

자바에서 +연산을 두가지 기능을 갖고있다.

  • 피연산자가 모두 숫자일 경우에는 덧셈 연산
  • 피연산자 중 하나가 문자열일 경우에는 나머지 피연산자도 문자열로 자동 변환되어 문자열 결합 연산 수행

"문자열" + 숫자 -> "문자열" + "숫자" -> 결합연산 -> "문자열숫자"
String str = "3" + 7; //37

연산식에서 + 연산자가 연이어 나오면 앞에서부터 순차적으로 +연산 수행
먼저 수행된 연산이 덧셈연산이면 덧셈 결과를 가지고 그 다음 + 연산 수행
만약 먼저 수행된 연산이 결합연산이면 이후 + 연산은 모두 결합 연산

String str = 1 + 2 + "3" // "33"
String str1 = "1" + 2 + 3 // "123"
  • 특정 부분을 우선 연산하고 싶을 경우
    순차적으로 연산을 수행하지 않고, 우선 연산하고싶은 부분이 있다면 해당 부분을 괄호 ()로 감싸준다.
    괄호는 최우선으로 연산을 수행한다.
    String str = "1" + (2 + 3); //"15"

문자열을 기본 타입으로 강제 타입 변환

변환 타입변환 메소드
String -> byteByte.parseByte()
String -> shortShort.parseShort()
String -> intInteger.parseInt()
String -> longLong.parseLong()
String -> floatFloat.parseFloat()
String -> doubleDouble.parseDouble()
String -> booleanBoolean.parseBoolean()

문자열이 숫자가 아닌 알파벳이나 특수 문자, 한글 등을 포함하고 있을 경우 숫자 타입으로 변환을 시도하면 숫자 형식 예외(NumberFormatException)가 발생

String var = "3.9";
int a = Integer.parseInt(var); // NumberFormatException
int a = (int)Double.parseDouble(var); //3.0

아래와 같은 경우는 발생하지않는다.

public static void main(String[] args) {
    String var = "3.9";
    double a = Double.parseDouble(var);
}

.이 있지만, 이를 실수타입으로 변환하기때문에 가능하다.
위 예제 같은경우에 Integer.parseInt()를 사용하면 에러나니 주의하자!

Boolean 타입은 숫자 타입이 아니므로 숫자형식예외 발생안함

boolean t = Boolean.parseBoolean("2");
System.out.println(t); // false

boolean t = Boolean.parseBoolean("1");
System.out.println(t); // false

boolean t = Boolean.parseBoolean("dg");
System.out.println(t); // false

boolean t = Boolean.parseBoolean("false");
System.out.println(t); // false

boolean t = Boolean.parseBoolean("true");
System.out.println(t); // true

반대로 기본 타입(byte,short,int,long,float,double,boolean)의 값을 문자열로 변경하는 경우도 있는데, 이 경우는 간단히 String.valueOf() 메소드를 이용한다.

  • 문자열을 char 타입으로 캐스팅 할 수 없음 : 컴파일에러 발생
String str = "A";
char var = (char)str; // 컴파일 에러 발생! 

출처
혼자 공부하는 자바

0개의 댓글