인스턴스를 동적인 코드로부터 생성하기

자바와 같은 확정적 언어에서 사실 동적인 인스턴스 생성을 하기란 여간 어려운게 아닙니다. 보통은 팩토리 함수를 미리 정의해두는 것이 맞습니다만 클래스가 지속적으로 확장되거나 유지보수가 빈번하게 발생하는 경우는 팩토리 함수 자체를 관리하기도 귀찮은 일이죠. 이런 문제는 간단한 리플렉션(reflection)을 통해 단순화 시킬 수 있습니다.

생성자 해시맵 생성하기

우선 생성자를 리플렉션하기 전에 생성자함수를 모아둘 공간을 만들어둡니다.

@SuppressWarnings( "rawtypes" )
HashMap<String, Constructor> _constuctors = new HashMap<String, Constructor>();

위의 어노테이션은 기저타입을 사용하니 경고를 띄우지 말라는 뜻입니다.

클래스명을 배열에 저장하기

일단 Constructor를 담을 그릇은 나왔으니 대상이 될 클래스 이름을 배열에 넣을 차례입니다. 예에서 간단히 위젯을 감싼 래핑 클래스가 있다고 가정해보죠. 그 클래스들이 다음과 같이 존재한다고 합시다.

  • com.bsidesoft.widget / bsButton.java
  • com.bsidesoft.widget / bsCheckbox.java
  • com.bsidesoft.widget / bsText.java

그럼 간단히 클래스 이름만 배열에 담습니다.

String[] t0 = {"bsButton", "bsCheckbox", "bsText"};

배열을 통해 해시맵 채우기

이제 배열을 루프돌며 해시맵에 생성자를 저장할 차례입니다.

try{
	for( int i = 0, j = t0.length ; i < j ; i++ )
	_constuctors.put(
		t0[i],
		Class.forName( "com.bsidesoft.widget." + t0[i] ).getConstructor()
	);
}catch( ClassNotFoundException $e ){
}catch( NoSuchMethodException $e ){
}

해시맵으로부터 인스턴스 생성하기

_constructor를 이용하면 간단히 인스턴스를 생성할 수 있습니다.

_instance = _constructor.get( "bsText" ).newInstance();

결론

위와 같은 리플렉션으로 배열만 관리하면 동적인 인스턴스 생성자를 쉽게 처리할 수 있게 됩니다(여타 문제도 발생하고 컴파일타임 시의 안정성도 약해지지만 알까보냐)

%d 블로거가 이것을 좋아합니다: