Java Generic - 도입 전 Object 다형성 사용하기
이전에 NumberBox, StringBox 객체를 만들어 저장하고 꺼내는 클래스를 생성하였다.
개발자에게 추가로 다양한 타입으로 받을 수 있다는 추가 요청사항이 도착하였다.
그렇다면 NumberBox, StringBox 타입만 다르므로 Object 객체를 사용한 다형성으로 도입하는 방법이 떠올랐다.
Object는 객체의 부모이므로 잘 작동할 거라 생각하고 코드를 작성해보자.
ObjBox.class
public class ObjBox {
private Object value;
public Object get() {
return value;
}
public void set(Object value) {
this.value = value;
}
}
Main.class
public class Main {
public static void main(String[] args) {
ObjBox objBox = new ObjBox();
objBox.set(100);
Object integer = objBox.get();
Integer ant = (Integer) integer;
System.out.println("integer = " + ant);
ObjBox stringBox = new ObjBox();
stringBox.set("Hello Java");
Object str = (String) stringBox.get();
System.out.println("str = " + str);
}
}
integer = 100
str = Hello Java
Object 다형성으로 클래스의 중복을 제거하였으니 추후에 문제가 발생할 수 있다.
Object 객체로 미숙하게 다룰 경우 다음 코드처럼 문제의 소지가 발생할 수 있다.
반환 타입 불일치
ObjBox objBox = new ObjBox();
objBox.set("L100");
Object integer = objBox.get();
Integer ant = (Integer) integer;
System.out.println("integer = " + ant);
- set 메소드로 L100 이라는 값을 넣었다. 이 때 들어간 타입은 String 형이다.
Integer ant = (Integer) integer;
코드에서 String 형을 Integer 형으로 다운캐스팅을 시도할 경우 오류가 발생한다.
개발자 의도는 set 메소드로 숫자 타입으로 기입하고 싶으나, 잘못된 타입의 인수로 전달되었다. 매개변수가 Object 이므로 모든 객체를 다 받아 일어난 문제다.
앞서 말한 내용을 정리하면 Object를 이용한 다형성으로 클래스의 중복을 제거하였고, 재사용할 수 있도록 하였으나 입력에 원하지 않는 타입이 들어가 타입 안전성 문제가 발생하였다. integer 변수에는 숫자만 넣으려 시도했으나 실수로 String 형으로 기입하게 되었다. 하지만 set 메소드는 매개변수가 Object 이므로 문제 없이 기입할 수 있으므로 의도와 다른 String 타입으로 정상적으로 기입되었다. 그리고 반환에도 Object 타입으로 반환한다. 타입 안전성 문제가 발생한 것인데 지나치게 된 것이다. Object 변수는 이제 Integer 타입으로 다운캐스팅 시도할 것이므로 컴파일 오류를 발생시켰다.
그럼 String 타입으로 다운캐스팅하면 되는게 아닌가 싶겠지만, 변수명이 integer이다. 이름만 봐도 Integer 타입으로 지정하고 싶을 것이다. 적어도 set 메소드 인자로 넣는 타이밍에 실수를 바로 잡았어야 했다.
트레이드 오프
코드를 살펴보았겠지만 개발한 코드의 재사용을 높이고 타입 안전성을 한꺼번에 잡을 수 없다. 재사용에는 Object 타입을 사용 시 타입 안전성은 현저히 떨어진다.