상수는 변하지 않는 수로 앞에 파이널이란 키워드를 사용하여 선언합니다.
리터럴은 프로그램내에서 사용되는 모든 숫자, 값, 논리 값을 나타내는 말입니다.
ex) 10, 3.15, 'A', ture 등 우리가 사용하는 모든 '값'
그림과 같이 모든 리터럴은 상수 풀에 저장 되어있습니다. 리터럴이 상수풀에 저장 될 때 정수는 int, 실수는 double로 저장되고 그범위를 넘어가는 수는 따로 식별하여 다른 자료형으로 저장합니다. 그 후 프로그램에서 값이 필요 할 때 상수풀에서 꺼내서 사용합니다. 이것을 통해서 우리가 정수 혹은 실수형 변수를 선언할때 int혹은 double이 아닌 경우 추가 부호를 붙여야 하는 이유가 알 수 있습니다.(리터럴이 상수 풀에 그런 형태로 저장되어 있는걸 변수에서 복사해서 사용하는 것이기에)
변수마다 자료형이 다르고 자료형마다 서로 사용하는 메모리 방식도 다르기 때문에 프로그램내에서 서로 다른 자료형의 값이 대입되는 경우 형변환이 일어납니다.
묵시적인 형변환(implicit type conversion)은 작은수 => 큰수, 덜 정밀한 수 => 더 정밀한 수 로 대입되는 경우에 일어나는 형변환으로 자동으로 형변환이 됩니다. 아래 그림에서 화살표 방향으로 일어나는 형변환들이 묵시적 형변환 입니다.
명시적인 형변환(explicit type conversion)은 작은수 <= 큰수, 덜 정밀한 수 <= 더 정밀한 수 로 대입되는 경우에 일어나는 형변환으로 묵시적인 형변환과 다르게 타입 캐스팅을 표시해주어 프로그래머가 자료의 손실이 발생할 수 있다는것을 인지하고 있음을 알려주어야 일어나는 형변환 입니다.(명시적인 형변환은 자료의 손실이 일어날 수 있다는 뜻을 내포합니다.) 위에 그림에서 화살표 반대방향으로 일어나는 형변환 입니다.
public class ImplicitConversion {
public static void main(String[] args) {
byte bNum = 10;
int iNum = bNum;
System.out.println(bNum); // 10
System.out.println(iNum); // 10
int iNum2 = 20;
float fNum = iNum2;
System.out.println(iNum2); //20
System.out.println(fNum); //20.0
double dNum;
dNum = fNum + iNum;
System.out.println(dNum); //30.0
}
}
byte => int 로 대입될때 자동으로 형변환 되어 10이라는 값이 출력되었습니다.
int => float으로 대입될때 정수에서 실수라는 자료형 차이가 있지만 덜 정밀한 수에서 더 정밀한 수로 대입되는 개념으로 묵시적인 형변환이 일어나서 20.0이라는 값이 출력되었습니다.
dNum = fNum + iNum; 부분에서 대입연산자는 가장 나중에 연산이 되기 때문에 먼저 iNum(int)이 float 으로 형변환되어서 fNum과 합연산이 일어나고 그다음 합쳐진 float값이 double로 형변환되서 dNum에 대입됩니다.(2번의 묵시적 형변환이 일어났습니다.)
public class ExplicitConversion {
public static void main(String[] args) {
int i = 1000;
byte bNum = (byte)i;
System.out.println(bNum); // -24
double dNum1 = 1.2;
float fNum = 0.9F;
int iNum1 = (int)(dNum1 +fNum);
int iNum2 = (int)dNum1 +(int)fNum;
System.out.println(iNum1); // 2
System.out.println(iNum2); // 1
}
}
int 값에 byte를 캐스팅( (byte)i 와 같이 값 앞에 괄호안에 자료형을 써주는것을 타입 캐스팅이라고 합니다.)해서 byte 값으로 명시적 형변환을 했더니 byte의 범위를 넘어선 값이 대입되어 데이터 유실이 발생하여 -24라는 음수가 나왔습니다. 이런 데이터 유실의 발생을 프로그래머가 인지 한다는 뜻에서 명시적인 형변환을 하는 것 입니다.
iNum1은 먼저 실수 값을 더한후 int로 형변환을 한것이기에 1.2 + 0.9 = 2.1에 정수로 형변환하면서 소수점을 버리는 효과가 일어나 정수 2라는 결과가 나왔습니다. 이와 다르게 iNum2에서는 두 실수를 먼저 정수로 형변환하여 소수점을 버리고 이후에 더했기 때문에 1.0 + 0 = 1라는 다른 결과가 나오게 됩니다. 이를 통해 우리는 형변환을 언제 하느냐에 따라 결과 값이 다를 수 있다는 것을 알 수 있습니다.
public class BinaryTest {
public static void main(String[] args) {
int num = 10;
int bNum = 0B1010;
int oNum = 012;
int xNum = 0XA;
System.out.println(num); //10
System.out.println(bNum); //10
System.out.println(oNum); //10
System.out.println(xNum); //10
}
}
위에 예제처럼 10진수 외에 다른 진수도 앞에 각 진수에 해당하는 부호를 넣음으로 사용할 수 있음을 알 수 있습니다.