열거 enum
public enum Size { SMALL, MEDIUM, LARGE, EXTRA_LARGE };
* 열거 타입 값을 비교할 때는 간단히 ==를 사용하라 equals를 호출해도 결국 ==로 검사함.
* Size notMySize = Size.valueOf("SMALL");
-> notMySize를 Size.SMALL로 설정한다.
* Size[] allValues = Size.values();
-> values() 함수를 쓰면 모든 인스턴스를 배열로 리턴해줌.
Class 클래스
어떤 객체의 참조를 저장하는 Object타입 변수가 있는 상태에서 해당 객체의 더 많은 정보를 얻고 싶다면?
Object obj = ...;
Class<?> cl = obj.getClass(); // <?>를 빠뜨리면 IDE가 경고를 준다.
Class 객체를 얻고 나면 클래스의 이름을 알 수 있다.
Class.forName을 사용해서 Class 객체를 얻는 방법도 있다.
Class.forName 메서드의 용도는 컴파일 시간에 알려지지 않은 클래스의 Class 객체를 생성하는 것이다.
* 자바에서 배열은 클래스지만 인터페이스, 기본타입, void는 클래스가 아니다.
리소스 로드하기
Class 클래스의 유용한 서비스 중 하나는 설정파일이나 이미지처럼 프로그램 리소스를 찾아오는 일이다.
InputStream stream = MyClass.class.getResourceAsStream("config.txt");
Scanner in = new Scanner(stream);
getResource메서드는 해당 리소스에 대응하는 URL을 반환한다.
리소스에는 서브디렉터리가 포함될 수 있으며, 해당 서브디렉터리를 상대경로나 절대경로로 지정할 수 있다.
MyClass.class.getResourceAsStream("/config/menus.txt")는 MyClass가 속한 패키지의 루트를 담고있는 디렉터리에서 config.menus.txt를 찾아온다.
클래스 로더
자신마의 URLClassLoader 인스턴스를 생성하면 클래스 패스에 없는 디렉터리나 JAR 파일에서 클래스를 로드할 수 있다. (플러그인 로드)
URL[] urls = {
new URL("file:///path/to/directory/");
new URL("file://path/to/jarfile.jar");
};
String className = "com.mycompany.plugin.Entry";
try(URLClassLoader loader = new URLClassLoader(urls)){
Class<?> cl = Class.forName(className,true,loader);
// cl의 인스턴스 생성
}
이름으로 클래스를 로드하는 메서드를 작성할 때는 단순히 해당 메서드가 속한 클래스의 클래스 로더를 사용하면 안된다. 메서드를 호출하는 쪽에서 명시적인 클래스 로더를 전달하거나 컨텍스트 클래스 로더를 사용하는 방법 중에서 선택할 수 있게 하는게 좋다.
서비스 로더
ServiceLoader 클래스를 이용하면 공통 인터페이스를 준수하는 플러그인을 손쉽게 로드할 수 있다.
프로그램에서 서비스 로더 초기화는 한번만 수행해야한다.