사이먼's 코딩노트
[Java] 형변환(래퍼클래스 / Object) 본문
[형변환 (캐스팅)]
- 이번에는 형변환 또는 캐스팅에 대해서 알아봅시다.
- Java에는 정수 타입, 실수 타입, 문자 타입, 논리 타입, 객체 등 여러가지 기본 타입이 있다.
- 바이트가 작은 순서로 정수 타입은 byte < short < int < long, 실수 타입은 float < double, 문자 타입은 char < String, 논리 타입은 boolean 그리고 각 class를 이용한 객체가 있다.
- 여기선 char 타입은 준정수 형태로써 문자이자 정수 타입의 성격도 가지고 있다.
- 형변환이란 코드를 작성할 때 같은 타입뿐만 아니라 서로 다른 타입간의 연산을 수행해야 하는 경우도 있는데, 이 때 연산을 수행하기 전에 타입을 일치시켜야 한다.
- 이처럼 변수나 리터럴의 타입을 다른 타입으로 변환하는 것을 형변환이라고 한다.
- 아래의 예시 코드를 통해 형변환의 역할을 자세히 살펴봅시다.
public class Main {
public static void main(String[] args) {
int i = 1;
long l = i;
i = (int)l;
float f = 10.5f;
double d = f;
f = (float)d;
동물 a동물 = new 사람();
a동물 = new 원숭이();
원숭이 a원숭이 = (원숭이)a동물;
}
}
class 동물 {
}
class 사람 extends 동물 {
}
class 원숭이 extends 동물 {
}
- 먼저 변수 i와 l를 살펴보자
- 변수 i는 int 타입이고 변수 l은 long 타입이다. 두 타입의 크기를 비교하자면 long 타입의 바이트 수가 더 크다.
- long 타입의 변수 l은 크기가 int 타입보다 크기 때문에 1이라는 값을 따로 형변환 없이 저장할 수 있다.
- 그치만 long 타입의 변수 l의 값 10을 다시 int 타입의 변수 i에 저장하려면 (int)와 같은 강제 형변환이 필요하다.
- 쉽게 말해서 물 그릇을 떠올렸을 때 int는 300ml 용량이고 long은 1L 용량이라고 생각하면 된다.
- 작은 물 그릇에 있는 물을 큰 물 그릇에 옮기는 것은 쉽지만, 반대는 물이 넘쳐 흐르게 된다.
- 이 떄 물이 넘쳐 흐르지 않도록 방지해주는 것을 강제 형변환이라고 생각하면 된다.
- double과 float의 경우도 마찬가지다.
- 타입의 크기를 비교하자면 double 타입이 float 타입보다 바이트 수가 더 크다.
- 그렇기 때문에 double 타입의 변수 d에는 float 타입의 변수 f의 값을 저장할 수 있고, 반대로 다시 float 타입 변수 f에 double 타입 변수 d를 저장하기 위해서는 (double)과 같은 강제 형변환이 필요하다.
- 일반 객체의 경우도 마찬가지다.
- 현재 선언된 클래스 동물, 사람, 원숭이 중에서 동물 클래스가 부모 클래스인 것을 알 수 있다.
- 사람과 원숭이 두 클래스는 동물 클래스를 상속 받지만, 두 클래스 간의 관계는 상속의 관계가 아니다.
- 그렇기 때문에 서로 타입에 맞게 (원숭이)과 같은 강제 형변환을 사용한다.
[래퍼클래스]
- 래퍼클래스의 의미는 간단하다.
- Java에서 모든 타입들은 각 타입의 래퍼클래스와 연결되어 있다.
- 예를 들어 byte 타입은 Byte, int 타입은 Integer, char 타입은 Character, float 타입은 Float, boolean 타입은 Boolean 등과 같이 타입 고유의 클래스를 래퍼클래스라고 한다.
- 다시 말해 기본 자료타입을 객체로 다루기 위해서 사용하는 클래스를 래퍼클래스(wrapper class) 라고 한다.
[Object]
- Object 클래스는 Java 패키지에 속한 클래스로, 모든 클래스들의 최상위 클래스이다.
- 즉, Java에서 만들어지는 모든 클래스는 별다른 정의를 하지 않아도 기본적으로 Object 클래스를 상속받게 되며, Object 클래스에 속한 메서드들을 사용할 수 있다.
- 아래의 예시 코드를 통해 Object의 역할을 자세히 살펴봅시다.
public class Main {
public static void main(String[] args) {
저장소.저장(10);
저장소.저장("안녕");
저장소.저장(new 사람());
저장소.저장(new 사과());
저장소.저장(5.5);
저장소.저장(false);
저장소.저장('a');
}
}
class 저장소 {
static void 저장(Object v) {
System.out.println("object 값 : " + v);
}
}
class 사람 {
}
class 사과 {
}
- Main 메서드를 살펴보면 현재 저장소라는 클래스에서 직접 저장() 메서드를 호출하고 있다.
- 그렇기 때문에 저장소 클래스를 생성하고 저장() 메서드는 static을 작성하여 생성한다.
- Main 메서드에서는 저장() 메서드를 통해 인자 값으로 정수, 문자열, 객체, 실수, 논리, 문자 형태의 값을 넘겨주고 있다.
- 가장 기초적인 생각으로는 위와 같은 Main 메서드가 실행하려면 저장소 클래스에서 각 타입에 맞게 저장() 메서드를 오버로딩하여 총 6개의 메서드를 생성하는 것이 일반적이다.
- 하지만 우리는 이제 모든 타입의 부모 클래스가 Object 클래스라는 것을 아는 이상, 저장() 메서드에 매개변수를 Object 타입으로 받는다면 오버로딩을 할 필요가 없다는 것을 알 수 있다.
반응형
'Java > Java' 카테고리의 다른 글
[Java] 배열 / toString / equals / StringBuilder (2) | 2024.03.14 |
---|---|
[Java] 형변환 문제풀이 (0) | 2024.03.13 |
[Java] 문자열을 다루는 String 클래스 메서드 (2) | 2024.03.13 |
[Java] static (0) | 2024.03.12 |
[Java] super / final / switch (0) | 2024.03.12 |