Java 변수와 타입(2)

개발자가 되고 싶어요·2023년 2월 23일
0
post-thumbnail

타입 변환

자동 타입 변환

자동 타입 변환은 타입 변환이 자동으로 일어나는 것을 말한다. 자동 타입 변환은 값의 허용 범위가 작은 타입이 허용 범위가 큰 타입으로 대입될 때 발생한다.

기본 터입 허용 범위 순으로 나열

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 타입보다 큰 허용 범위를 가진다. 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 타입 보다 큰 허용 범위를 가진다. 따라서 long 타입은 int 타입으로 자동 변환되지 않고 캐스팅해서 강제변환 시켜야한다

300을 갖는 long 타입 변수는 8byte 중에 끝 4byte로 300을 표현할 수 있다. int 타입으로 강제 변환하면 앞 4byte는 버려지고 끝 4byte만 int 타입 변수에 저장되므로 300이 그대로 유지된다.

long longValue = 10;
int intValue = (int) intValue // 강제 타입 후에 300 그대로 유지

int → char

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;
byte 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 = 2int y = 2int y = 2;
double result = (double) x / ydouble result = x / (double) ydouble 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);
	};
};
profile
I want to be a Backend Developer

0개의 댓글