본문 바로가기

개발/JAVA

[JAVA] RTTI(Run-Time Type Information)

자바(Java) – Reflection 리플렉션 (RTTI:Run-Time Type Information)


 

1.    RTTI ?

 

-      실행 시간에 객체들의 정보(타입) 얻는 표준화된 방법을 제공

-      런타임에 타입의 정보를 가지고 오류를 검사하는 목적으로 사용

Run Time Type Information의 약자로 "실행시간에 타입정보를 식별" , 실시간으로 현재 사용되고 있는 클래스의 타입이 에 대한 정보를 알아보기 위해서 사용한다. 한글로 풀이하자면 "실시간 형식 정보" 라고 할 수 있겠죠.

정확한 의미는, 실행중에 기반 클래스 타입 객체의 타입에 대한 정보를 얻을 수 있는 기능입니다.

RTTI는 다형성 객체의 동적 타입을 알아내기 위해 만들어진 기능입니다. , base* 타입의 포인터가 포인팅하고 있는 객체가 실제로 derived1 타입의 객체인지, derived2 타입의 객체인지를 알고자 할 때 쓰이는 것이죠.

 

2.    RTTI 는 왜 필요한가?

 

RTTI는 위에서 언급했듯 실행중에 기반 클래스 타입 포인터의 실체를 밝혀내는데 목적으로 하고 있습니다.

정확하게 다형성을 가진 객체에 대해 정확한 타입을 알아내기 위해서 나왔다고 볼 수 있습니다.

RTTI(Run-Time Type Information)을 이용하면 실행중에 타입 정보를 알아내고 사용할 수 있다. 이는 매우 까다롭고 복잡한 문제점들을 쉽고 빠르게 해결 할 수 있고, 굉장히 강력한 프로그램을 작성 할 수 있게 도와준다. 하지만 이는 객체 지향적인 프로그래밍 방법을 위배하고, 코드의 가독성을 떨어트린다는 의견도 있다. 그렇지만 이런 강력한 기능의 유혹을 벗어나긴 힘들다. 그리고 실제 여러 Framework에서 RTTI를 잘 활용 하고 있다. (특히나 Spring Framework)

 

자바에서는 모든 .class 파일 하나당 java.lang.Class 객체 하나씩 생성된다. Class는 모든 .class들의 정보를 가지고 있으며 .class파일에 같이 저장된다. 모든 .class들은 이 클래스를 최초로 사용하는 시점에서 동적으로 ClassLoader을 통해 JVM에 로드된다

 

간단한 예를 들면 Base 클래스가 있고 그것을 상속받은 Child1, Child2 클래스가 존재한다고 가정했을때,

Base* m_Base = new Child1(); 이렇게 할당하였을 경우 기존의 방법으로는 실행중에 m_Base 가 가리키고 있는 객체가

Child1 이라는 것을 알 수가 없습니다. 하지만 RTTI 를 사용하면 Child1 타입이라는 것을 정확하게 알 수 있게 됩니다.

 

이것은 하나의 단편적인 예이며 사실 가상함수를 사용하는 다형성을 통해서 굳이 런타임때 타입을 알필요가 없을지도 모릅니다. 하지만 가상함수로도 해결할 수 없는 문제점을  RTTI 를 통해서 해결 가능한 부분들이 존재합니다.

이에 관해서는 http://blog.naver.com/moodern?Redirect=Log&logNo=80005025903 를 참고하세요 ^^

 

3. 사용 방법

 

RTTI는 언어의 기능, 혹은 컴파일러의 기능을 칭하는 명칭이기도 합니다. 물론, 객체마다 유지되는 동적 타입을 가리키는 C++의 용어이기도 합니다.

RTTI 기능을 켜고 컴파일하면 type_info 클래스의 객체가 각 클래스마다 하나씩 만들어지고 가상함수 테이블에서 참조하게 됩니다. 사용방법은 4의 동작방식을 확인하세요.

 

 

[RTTI는 직접적으로 쓰는 경우는 많이 없다. 이전 회사까지 실무에서는 RTTI를 직접적으로 쓴적은 없었다. 단지 RTTI로 안전성을 확보한 표준 캐스트 연산자는 사용을 한다..]

 

4. RTTI 동작 방식

1.    dynamic_cast

base class 지시하는 포인터로부터 파생클래스를 지시하는 포인터를 생성, 불가하면 NULL 리턴

안전성을 확보하는 과정에서 RTTI로 타입 검사를 거치게 된다.

(상속 관계에 있지만변환이 안되는 경우에 NULL을 리턴)

2.    typeid

- 객체의 정확한 데이터형을 식별하는 값을 리턴

- typeid 연산자를 사용하여  객체의 데이터형이 같은지 결정할  있다.

- sizeof 비슷하게, typeid 연산자는  종류의 전달인자를 받아들인다.(클래스이름, 객체로 평가되는 -

- typeid 연산자는 type_info 객체에 대한 참조를 리턴한다.

3.    type_info

- 반환된 typeid 연산자 형식의 정보를 저장하는데 사용

- RTTI 가상 함수들을 가지고 있는 클래스 계층에 대해서만 사용할  있다. 이유는 그들이 

파생 객체들의 주소를 기초클래스 포인터들에 대입해야 하는 유일한 클래스 계층이기 때문이다.

- ypeinfo 헤더 파일에 정의되어 있는 클래스이다.

- type_info 클래스는 데이터형을 비교하는데 사용할  있도록 ==  != 연산자를 오버로딩한다.

- typeid(classA) == typeid(*classB), classB classA 객체를 지시하는 포인터이면 true,

아니면 false, NULL이면 bad_typeid 예외 발생

 

 

·        dynamic_cast

o   포인터가 지시하는 객체형이 무엇인지 알려주진 않지만,  객체의 주소를 특정형의 포인터에 안전하게 대입할수 있는지 알려준다.

o   데이터형을 알려고 하는 일반적인 이유는, 어떤 특별한 메소드를 호출하는 것이 안전한지 알기 위한 것이다.

o   사용하는 컴파일러가 RTTI 지원한다 하더라도,  기능이 디플트로 꺼져 있을  있다. 기능이 꺼져 있으면proj 속성 페이지를 열고, C/C++ -> 런타임 형식 -> ''  변경

·        typeid

o   typeid 연산자를 사용하여  객체의 데이터형이 같은지 결정할  있다.

o   sizeof 비슷하게, typeid 연산자는  종류의 전달인자를 받아들인다.(클래스이름, 객체로 평가되는 )

o   typeid 연산자는 type_info 객체에 대한 참조를 리턴한다.

·        type_info

o   typeinfo 헤더 파일에 정의되어 있는 클래스이다.

o   type_info 클래스는 데이터형을 비교하는데 사용할  있도록 ==  != 연산자를 오버로딩한다.

o   typeid(classA) == typeid(*classB), classB classA 객체를 지시하는 포인터이면 true, 아니면 false, NULL이면bad_typeid 예외 발생

 

 

5. RTTI의 제약사항

 

1) 상속 관계안에서만 사용할 수 있다.

2) 하나 이상의 가상 함수를 가져야 한다.

3) 컴파일러의 RTTI 설정이 켜저 있어야 한다. 

 

 

 

 

 

 

 

  

'개발 > JAVA' 카테고리의 다른 글

[JAVA] 맥 이클립스 실행 단축키  (0) 2016.02.10