자동 타입 변환은 타입 변환이 자동으로 일어나는 것을 말한다. 자동 타입 변환은 값의 허용 범위가 작은 타입이 허용 범위가 큰 타입으로 대입될 때 발생한다.
기본 터입 허용 범위 순으로 나열
byte < short, char < int < long < float < double
int 타입이 byte 타입보다 허용 범위가 크기 때문에 다음 코드는 자동 타입 변환이 된다.
int > btye
byte byteValue = 10;
int intValue = byteValue
정수 타입이 실수 타입으로 대입될 경우에는 무조건 자동 타입 변환된다.
실수타입 > 정수타입
long longValue = 5000000000L;
float floatValue = longValue; // 5.0E9f로 저장됨
double doubleValue = longValue; // 5.0E9로 저장됨
char 타입의 경우 int 타입으로 자동 변환 시 유니코드 값이 int타입에 대입된다.
char charValue = 'A';
int intValue = charValue; //65가 저장됨
char 타입보다 허용범위가 작은 byte 타입은 char타입으로 자동 변환 될 수 없다. char 타입의 허용 범위는 음수를 포함하지 않는데, byte타입은 음수를 포함하기 때문이다.
byte byteValue = 65;
char charValue = byteValue; //컴파일 에러
예제 코드
package hello;
public class PromotionExample {
public static void main(String[] args) {
byte byteValue = 10;
int intValue = byteValue;
System.out.println("intVlue: "+ intValue); //intValue: 10
char charValue = '가';
intValue = charValue;
System.out.println("가의 유니코드: "+intValue); //가의 유니코드: 44032
intValue = 50;
long longValue = intValue;
System.out.println("longValue: " + longValue); // longValue: 50
longValue = 100;
float floatValue = longValue;
System.out.println("floatValue: " + floatValue); // floatValue: 100.0
floatValue = 100.5F;
double doubleValue = floatValue;
System.out.println("doubleValue: " +doubleValue); // doubleValue: 100.5
}
}
큰 허용 범위 타입은 작은 허용 범위 타입으로 자동 타입 변환될 수 없다. 하지만 큰 범위를 쪼개서 작은 범위로 넣는 것은 가능하다. 큰 허용 범위 타입을 작은 허용 범위 타입으로 쪼개어서 저장하는 것을 강제 타입 변환(casting)이라고 한다.
int 타입은 byte 타입보다 큰 허용 범위를 가진다. int 타입은 byte 타입으로 자동변환 되지 않고 (byte)캐스팅을 해서 byte타입으로 강제 변환 시켜야 한다.
int intValue = 10;
byte byteValue = (byte) // intValue 강제 타입 변환
10진수 10은 2진수 1010으로 1byte만 있으면 저장할 수 있다. int타입은 4byte 크기를 가지므로 10은 끝 1byte안에 저장된다. byte 타입 강제 변환 시 앞 3byte는 삭제되고 끝 1byte만 byte변수에 저장된다.
2byte이상이 필요한 int값은 원래 값이 보존되지 않는다.
강제 타입의 목적은 원래 값이 유지되면서 타입만 바꾸는 것이다. 그렇기 때문에 작은 허용범위 타입에 저장 할 수 있는 값을 가지고 타입 변환을 해야한다.
long 타입은 int 타입 보다 큰 허용 범위를 가진다. 따라서 long 타입은 int 타입으로 자동 변환되지 않고 캐스팅해서 강제변환 시켜야한다
300을 갖는 long 타입 변수는 8byte 중에 끝 4byte로 300을 표현할 수 있다. int 타입으로 강제 변환하면 앞 4byte는 버려지고 끝 4byte만 int 타입 변수에 저장되므로 300이 그대로 유지된다.
long longValue = 10;
int intValue = (int) intValue // 강제 타입 후에 300 그대로 유지
int 타입은 char 타입 보다 큰 허용 범위를 가진다. 따라서 int 타입은 char 타입으로 자동 변환되지 않고 캐스팅해서 강제변환 시켜야한다. 주의할 점은 char 타입 허용 범위인 0~65535 사이 값만 원래 값을 유지한다
실수타입(float, double)은 정수 타입(byte, short, int, long)보다 항상 큰 허용 범위를 가진다. 따라서 대상 정수 타입으로 캐스칭해서 강제 변환 시켜야한다. 이때 소수점 이하 부분은 버려지고 정수 부분만 저장된다.
double doubleValue = 3.14;
int intValue = (int) doubleValue; //intValu는 정수 부분인 3만 저장
public class CastingExample {
public static void main(String[] args) {
int var1 = 10;
byte var2 = (byte) var1;
System.out.println(var2); //강제 타입 경 후 그대로 10유
long var3 = 300;
int var4 = (int) var3;
System.out.println(var4); // 강제 타입 변경 후 대로 300 유지
int var5 = 65;
char var6 = (char) var5;
System.out.println(var6); //'A'가 출력
double var7 = 3.14;
int var8 = (int) var7;
System.out.println(var8); // 3이 출력
}
}
정수 연산
자바는 실행 성능 향상을 위해 컴파일 단계에서 연산을 수행한다.
byte result = 10 + 20; //컴파일 byte result = 30;
자바 컴파일러는 컴파일 단계에서 10 + 20을 미리 연산하여 30을 만들고 result 변수에 30을 저장하도록 바이트 코드를 생성한다. 따라서 실행 시 덧셈 연산이 없어 실행 성능이 좋아진다.
하지만 정수 리터럴이 아니라 변수가 피연산자로 사용되면 실행 시 연산을 수행한다. 정수 타입 변수가 산술 연산식에서 피연산자로 사용되면 int 타입보다 작은 byte, short 타입의 변수는 int 타입으로 자동 타입 변환되어 연산을 수행한다.
byte 타입 변수가 피연산자로 사용된 경우 | int 타입 변수가 피연산자로 사용된 경우 |
---|---|
byte x = 10; | int x = 10; |
byte y = 20; | int y = 20; |
int result = x + y; | |
int result = x + y; |
표 왼쪽처럼 byte 변수 x,y가 피연산자로 사용되면 int 타입으로 변환되어 연산되고, 결과도 int 타입으로 생성된다. 따라서 결과값을 byte 변수에 저장할 수 없고, int 변수에 저장해야 한다.
실행 성능을 위해 정수 연산에서 변수를 사용할 경우 int 타입으로 변수를 선언하는 것이 좋다.
정수 연산식에 모든 변수가 int 타입으로 변환되는 것은 아니다. int 범위가 타입보다 큰 long 타입이 피연산자로 사용되면 다른 연산자는 long 타입으로 연산을 수행한다. 따라서 연산결과는 long 타입으로 변수에 저장한다.
실수 연산
피연산자가 동일 실수 타입이라면 결과도 동일 타입이다.
float result = 1.2f + 3.4f; // 컴파일: float result = 4.6f;
하지만 연산자 중 하나가 double 타입으로 변환되어 연산되고, 연산 결과 또한 double 타입이다. int 타입도 마찬가지이다.
만약 int 타입으로 연산을 해야한다면 double 타입을 int 타입으로 강제 변환하고 덧셈 연산을 수행하면 된다.
int intValue = 10;
double doubleValue = 5.5;
int result = intValue + (int) doubleValue // 10.0 + 5
수학 1/2 는 0.5
int x = 1:
int y = 2;
double result = x / y;
System.out.println(result) // 결과는 0.5 일까?
위 코드를 실행하면 0.5가 출력된다. 자바에서 정수 연산의 결과는 항상 정수가 되기 때문이다. 따라서 x/y의 연산결과는 0.5가 아니라 0이 되고 0을 double 타입 변수 result에 저장하므로 0.0이 된다. 위 코드의 결과가 0.5가 되기 위해서는 x/y부분을 정수 연산이 아닌 실수 연산으로 변경해야한다. x, y 둘 중 하나 또는 둘 모두를 double 타입으로 변환하는 것이다.
방법 1 | 방법 2 | 방법 3 |
---|---|---|
int x = 1; | int x = 1; | int x = 1; |
int y = 2 | int y = 2 | int y = 2; |
double result = (double) x / y | double result = x / (double) y | double result = (double) x / (double) y |
만약 (double) (x/y)로 수정하면 0.5가 아닌 0.0을 얻는다. x/y 가 먼저 연산되어 0이되고 double 타입 0.0으로 변환되기 때문이다.
public class OperationPromotionExample {
public static void main(String[] args) {
byte result1 = 10 + 20; // 컴파일 단계에서 연산
System.out.println("result1: " + result1);
byte v1 = 10;
byte v2 = 20;
int result2 = v1 + v2; // int 타입으로 변환 후 연산
System.out.println("result2; " + result2);
byte v3 = 10;
int v4 = 100;
long v5 = 1000L;
long result3 = v3 + v4 + v5; // long 타입으로 변환 후 연산
System.out.println("result3: " + result3);
char v6 = 'A';
char v7 = 1;
int result4 = v6 + v7; //int 타입으로 변환 후 연산
System.out.println("result4: " + result4);
System.out.println("result4: " + (char) result4);
int v8 = 10;
int result5 = v8 / 4; // 정수 연산의 결과는 정수
System.out.println("reslt5: " + result5);
int v9 = 10;
double result6 = v9/ 4.0; //double 타입으로 변환 후 연산
System.out.println("reslt6: " + result6);
int v10 = 1;
int v11 = 2;
double result7 = (double) v10 / v11; //double 타입으로 변환 후 연산
System.out.println("result7: " + result7);
}
}
자바 + 연산자의 두 가지 기능
피연산자가 모두 숫자일 경우에는 덧셈 연산 수행, 피연산자 중 하나가 문자일 경우 나머지 피연산자도 문자열로 자동 변환되어 문자열 결합 연산을 수행한다```
int value = 3 + 7; → int value = 10;
String str = "3" + 7; → String str = "3" + "7"; → String str = "37";
String str = 3 + "7" → String str = "3" + "7"; → String str = "37";
연산식에서 + 연산자가 연이어 나오면 순차적으로 + 연산을 실행한다.
int value = 1 + 2 + 3; → int value = 3 + 3; → int value = 6;
Sting str = 1 + 2 + "3"; → String str = 3 + "3"; → String str = "33"
Sting str = 1 + "2" + 3; → String str = "12" + 3; → String str = "123"
Sting str = "1" + 2 + 3; → String str = "12" + 3; → String str = "123"
순차적으로 + 연산을 수행하고 싶지 않고 특정 부분을 우선 연산하고 싶다면 ()로 감싼다.
String str = "1" + (2 + 3); → String str = "1" + 5; → String str = "15";
자바에서 문자열을 기본 타입으로 변환하는 방법
변환 타입 | 사용 예 |
String → byte | String str = "10"; byte value = Byte.parseByte(str); |
String → byte | String str = "200"; short value = short.parseshort(str); |
String → int | String str = "300000"; int value = Integer.parseInt(str); |
String → long | String str = "40000000000"; long value = Long.parseLong(str); |
String → float | String str = "12.345"; float value = Float.parseFloat(str); |
String → double | String str = "12.345"; double value = Double.parseDouble(str); |
String → boolean | String str = "true"; boolean value = Boolean.parseBoolean(str); |
String str = String.valueOf(기본타입값);
public class PrimitiveAndStringConversionExample {
public static void main(String[] args) {
int value1 = Integer.parseInt("10");
double value2 = Double.parseDouble("3.14");
boolean value3 = Boolean.parseBoolean("true");
System.out.println("value1: " + value1);
System.out.println("value2: " + value2);
System.out.println("value3: " + value3);
String str1 = String.valueOf(10);
String str2 = String.valueOf(3.14);
String str3 = String.valueOf(true);
System.out.println("str1: " + str1);
System.out.println("str2: " + str2);
System.out.println("str3: " + str3);
};
};