타입 변환 문서의 구현 코드다.
// 실행: docker run --rm -v "$PWD":/w -w /w eclipse-temurin:21-jdk java 03_java-type-conversion_impl.java
// 타입 변환 문서의 출력과 값을 확인한다.
class TypeConversionImpl {
static void check(boolean ok, String what) {
if (!ok) throw new AssertionError(what);
}
public static void main(String[] args) {
// 1. 자동 변환 (문서의 첫 예제)
int i = 100;
long l = i;
float f = l;
check(("Int value " + i).equals("Int value 100"), "int");
check(("Long value " + l).equals("Long value 100"), "long");
check(("Float value " + f).equals("Float value 100.0"), "float");
// 2. 강제 변환 (문서의 둘째 예제)
double d = 100.04;
long l2 = (long) d;
int i2 = (int) l2;
check(("Double value " + d).equals("Double value 100.04"), "double");
check(("Long value " + l2).equals("Long value 100"), "long으로 자르기");
check(("Int value " + i2).equals("Int value 100"), "int로 자르기");
// 3. int -> char는 강제 변환이 필요하다
int num = 88;
char ch = (char) num;
check(ch == 'X', "88번 글자는 X");
// 4. 강제 변환은 값을 바꿀 수 있다
check((byte) 300 == 44, "(byte)300 = 44");
check((byte) 128 == -128, "(byte)128 = -128");
check((byte) 200 == -56, "(byte)200 = -56");
check((int) 3.99 == 3, "(int)3.99 = 3");
check((int) -3.99 == -3, "(int)-3.99 = -3");
check((int) 1e20 == Integer.MAX_VALUE, "너무 큰 실수는 int 최댓값이 된다");
check((int) Double.NaN == 0, "NaN은 0이 된다");
// 5. 자동 변환도 정밀도를 잃을 수 있다 (long, int -> float)
int big = 16777217; // 2^24 + 1
float bf = big;
check((int) bf == 16777216, "int 16777217 -> float -> int 16777216");
long big2 = 123456789L;
float bf2 = big2;
check((long) bf2 == 123456792L, "long 123456789 -> float -> long 123456792: " + (long) bf2);
// 6. 연산 중 변환: byte끼리 더해도 결과는 int
byte x = 10;
byte y = 20;
int result = x + y;
check(result == 30, "byte + byte = int 30");
byte sum = (byte) (x + y);
check(sum == 30, "강제 변환하면 byte에 담을 수 있다");
char a = 'A';
check(a + 1 == 66, "'A' + 1 = 66 (int)");
check((char) (a + 1) == 'B', "(char)('A'+1) = 'B'");
// 크기가 다른 타입끼리는 큰 쪽으로 맞춘다
check(10 / 4 == 2, "int / int = 2");
check(10 / 4.0 == 2.5, "int / double = 2.5");
check((double) 10 / 4 == 2.5, "(double)10 / 4 = 2.5");
check((double) (10 / 4) == 2.0, "(double)(10/4) = 2.0");
Object o = 1 + 2L;
check(o instanceof Long, "int + long = long");
Object o2 = 1 + 2.0f;
check(o2 instanceof Float, "int + float = float");
Object o3 = 1L + 2.0f;
check(o3 instanceof Float, "long + float = float");
// 7. + 의 두 가지 일 (문서의 여덟 줄 예제)
check(3 + 7 == 10, "3 + 7");
check(("3" + 7).equals("37"), "\"3\" + 7");
check((3 + "7").equals("37"), "3 + \"7\"");
check(1 + 2 + 3 == 6, "1 + 2 + 3");
check((1 + 2 + "3").equals("33"), "1 + 2 + \"3\"");
check((1 + "2" + 3).equals("123"), "1 + \"2\" + 3");
check(("1" + 2 + 3).equals("123"), "\"1\" + 2 + 3");
check(("1" + (2 + 3)).equals("15"), "\"1\" + (2 + 3)");
// 카드
check(("" + 1 + 2).equals("12"), "\"\" + 1 + 2");
check((1 + 2 + "" + 1 + 2).equals("312"), "1 + 2 + \"\" + 1 + 2");
check(('A' + 1 + "B").equals("66B"), "'A' + 1 + \"B\"");
check(("B" + 'A' + 1).equals("BA1"), "\"B\" + 'A' + 1");
// 8. 문자열 <-> 기본 타입
check(Byte.parseByte("10") == 10, "parseByte");
check(Short.parseShort("200") == 200, "parseShort");
check(Integer.parseInt("300000") == 300000, "parseInt");
check(Long.parseLong("40000000000") == 40000000000L, "parseLong");
check(Float.parseFloat("12.345") == 12.345f, "parseFloat");
check(Double.parseDouble("12.345") == 12.345, "parseDouble");
check(Boolean.parseBoolean("true") == true, "parseBoolean");
check(String.valueOf(10).equals("10"), "valueOf(int)");
check(String.valueOf(12.5).equals("12.5"), "valueOf(double)");
check(String.valueOf(true).equals("true"), "valueOf(boolean)");
check(("10" + "20").equals("1020"), "글자끼리는 붙는다");
check(Integer.parseInt("10") + Integer.parseInt("20") == 30, "숫자로 바꾸면 더해진다");
boolean threw = false;
try {
Integer.parseInt("12a");
} catch (NumberFormatException e) {
threw = true;
}
check(threw, "숫자가 아닌 글자는 NumberFormatException");
threw = false;
try {
Byte.parseByte("200");
} catch (NumberFormatException e) {
threw = true;
}
check(threw, "범위를 넘는 글자도 NumberFormatException");
System.out.println("ALL CHECKS PASSED");
}
}