[Java] Type Safe란?

자바[Java] 2017. 10. 30. 20:25

 

 

Type Safe(타입 세이프) 란 말그대로 타입에 안정적인 것을 의미합니다.


타입에 불안정적이다 라고 하는것은 타입을 판별(Type Check) 하지 못해 Runtime 시 타입으로 인한 문제가 발생하는 것입니다.
Type Safe 하다 라는 것은 그 반대로 타입을 판별(Type Check) 할 수 있어 Runtime시가 아닌 컴파일시 문제를 잡을 수 있는 것입니다.

예를 들어보겠습니다.
다음과 같은 상속 관계의 클래스들이 있습니다.
물론 실제로 이렇게 클래스들을 설계하는 것은 매우 무의미한 행동이지만 여기서는 예를 들기 위함임을 감안해 주세요.

저희 동물원을 객체지향적으로 표현했을 때 최상위 클래스(Object 제외)로 Animal이 있고 그 하위에 Lion과 Duck이 있습니다.

Lion 클래스에는 hunt() 라는 사냥 메서드가 있고
Duck 클래스에는 ggack() 이라는 "꽥!" 하고 울 수 있는 메서드가 있습니다.


이 밖에도 수 많은 동물들이 있겠지만 소개는 이정도로 하겠습니다.
또한 동물들을 사람으로부터 격리시킬 수 있는 Cage(동물우리) 클래스가 있습니다.

Cage에는 우습긴 하지만 모든 동물을 넣을 수 있는 Animal 형 animal 멤버변수가 있고

 

동물들을 넣고 뺄 수 있는 put(), get() 메서드가 있습니다.

 

 

 

Animal.java

1
2
3
public class Animal {
 
}
cs

 

Lion.java

1
2
3
4
5
6
7
public class Lion extends Animal{
 
     public void hunt(){
           System.out.println("사냥한다!");
     }
 
}
cs

 

Duck.java

1
2
3
4
5
public class Duck extends Animal{
     public void ggack(){
           System.out.println("꽥!");
     }
}
cs

 

Cage.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Cage {
 
     private Animal animal;
 
     //동물 넣음
     public void put(Animal animal){
           this.animal = animal;
     }
 
     //동물 꺼냄
     public Animal get(){
           return this.animal;
     }
 
}
cs

 

TypeSafeTest.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class TypeSafeTest {
 
     public static void main(String[] args) {
 
           Lion jerry = new Lion();
 
           Cage cage = new Cage();
           cage.put(jerry);
 
           Duck ashi = (Duck)cage.get(); //ClassCastException
           ashi.ggack();
 
     }
 
}
cs

 

 

금요일 저녁이 되어 사육사는 사자 제리를 우리에 넣었습니다.
그리고 퇴근 후 불금을 즐기며 술을 진탕 마셨죠.

다시 주말이 지나고 월요일이 되어 사육사는 동물원에 옵니다.
그런데 술 때문인지 우리에 넣었던 동물이 무엇인지 기억이 나지 않았고
꺼림칙하긴 했지만  오리일것이라고 기대하며 그 알 수 없는 동물을 꺼냈습니다.

사육하는 "꽥!" 하며 우는 모습의 오리는 생각했지만 결과는 참담했습니다.

ClassCastException... 형변환 시에 타입이 맞지 않아 발생하는 예외입니다.
예외란 예기치 못한 흐름입니다.
그렇습니다. "꽥!" 하며 우는 오리의 모습을 기대했지만 사육사가 그 소리를 대신 내게 되었죠..

최대한 여러가지 동물을 넣을 수 있는 Cage(우리) 를 만들고 싶었고 다형성을 이용해 상위 클래스를 멤버변수로 넣은 후
하위 클래스의 인스턴스들을 담았습니다.

객체는 우리에 넣는 시점에는 객체가 무슨 타입인지 알 수 있으나 꺼내는 시점에는 그 객체가 어떤 동물인지 알 수 없습니다.

 

 

 

 


저기 저렇게 코드에 Lion을 넣는게 나와있는데 왜 모르나요???
물론 그런 의문을 갖을 수 있습니다.
그러나 컴파일러는 알파고가 아닙니다.

저 우리(Cage)는 개발자 한 두명만 쓰는것이 아니고 저 Lion을 집어 넣는 코드가 전체 프로그램중 어디에 들어갈 지 모르며, 프로그램은 혼자 개발하는 것도 아니고 A개발자가 넣은 사자, 호랑이 우리를 B 개발자의 코드에서 초식동물인 줄 알고 꺼내 사용할 수 있습니다.

컴파일 시점에서 컴파일러가 다형성이 적용된 모든 코드를 분석하고 참조변수의 타입과 실제 인스턴스 변수의 타입을 모두 체크하여
자동으로 분석 한다는 것은 그리 쉽게 생각할 수 있는 일이 아닙니다.

이렇게 타입을 체크하지 못하여  문제가 발생하는 것을 타입에 안정적이지 못하다 라고 하는 것입니다.
이 경우 다음과 같은 지저분한 로직이 나타납니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class TypeSafeTest {
 
     public static void main(String[] args) {
 
           Lion jerry = new Lion();
 
           Cage cage = new Cage();
           cage.put(jerry);
 
 
           Animal whatAnimal = cage.get();
 
           if(whatAnimal instanceof Duck){
                Duck ashi = (Duck)whatAnimal;
                ashi.ggack();
           }else{
                System.out.println("오리가 아니에요!");
           }
 
     }
 
}
cs

 

 

instanceof 연산자를 통해 Duck 객체인지 확인 후 캐스팅을 하는 로직이 추가 되었습니다.
이런 로직이 반복된다면 매우 귀찮고 보기에도 안 좋아질 것입니다.

이 밖에도 여러가지 문제점이 있겠으나 자바 1.5에서 도입된 Generic(제네릭)을 사용한다면 무슨 동물이든 담을 수 있지만
타입에 훨씬 안정적인 Cage(우리)를 만들 수 있습니다.

제네릭은 따로 포스팅 하도록 하겠습니다.

 

 

 

 

 

블로그 이미지

도로락

IT, 프로그래밍, 컴퓨터 활용 정보 등을 위한 블로그

,