2012-03-27 6 views
8

나는 어떤 가치가있는 String을 가지고있다. 특정 메서드를 호출하는 패키지의 모든 클래스를 반복하고, 메서드에서 반환 한 값이 String의 값과 같은 경우 해당 클래스의 개체를 만듭니다.Reflection을 사용하여 패키지 내의 모든 클래스를 반복 할 수 있습니까?

동적 인 방식으로이 작업을 수행하고 싶습니다. 따라서이 패키지에 클래스를 추가하면 자동으로 반복됩니다.

가능합니까? 그렇지 않다면, 내가 원하는 것을 할 수있는 방법이 있습니까?


나는 뭔가를 기대하고 있었다.

for(Class clazz: SomeClass.listClasses("org.package")){ 
    //code here 
} 
+0

"이 패키지에 클래스 추가"란 무엇입니까? 자바 프로세스의 클래스 패스는 어떻게됩니까? –

+0

@Jeffrey 나는 Reflection에 대해 읽고 있었고 이것이 유일한 방법이라고 생각하지만 Reflection에 대해서는 아무것도 모른다. 그 패키지에있는 각 클래스에 대한 검증을 추가하는 "일반적인 방법"을 시도했지만, 확장 할 수 없기 때문에이 방법을 원하지 않습니다. –

+0

@MiserableVariable 개발 시간에는 패키지에 새로운 클래스를 추가합니다 (모든 클래스는 Document라는 추상 클래스를 확장합니다). –

답변

8

아니요, 완전히 신뢰할 수있는 방법은 아닙니다. 그러나 많은 경우에 구현하는 것이 현실적 일 수 있습니다.

Java 클래스 로더의 유연성 때문에 특정 패키지에서 정의 된 클래스는 런타임에 알 수 없을 수도 있습니다 (예 : 네트워크에서 클래스를로드하는 등의 방식으로 클래스를 즉석에서 정의하는 특수 클래스 로더를 고려하거나 ad-hoc으로 컴파일). 따라서 패키지의 클래스를 나열 할 수있는 표준 Java API는 없습니다.

실제로 클래스 패스에서 모든 클래스 및 JAR 파일을 검색하고 정규화 된 클래스 이름 모음을 만들고 원하는대로 검색하여 몇 가지 트릭을 수행 할 수 있습니다. 이 전략은 이전 단락에서 설명한대로 활성 클래스 로더가 작동하지 않는다고 확신하는 경우 제대로 작동합니다. 예를 들어 (Java 의사 코드) :

Map<String, Set<String>> classesInPackage = new HashMap(); 
for (String entry : eachClasspathEntry()) { 
    if (isClassFile(entry)) { 
    String packageName = getPackageName(entry); 
    if (!classesInPackage.containsKey(packageName)) { 
     classesInPackage.put(packageName, new HashSet<String>()); 
    } 
    classesInPackage.get(packageName).add(getClassName(entry)); 
    } else if (isJarOrZipFile(entry)) { 
    // Do the same for each JAR/ZIP file entry... 
    } 
} 
classesInPackage.get("com.foo.bar"); // => Set<String> of each class... 
+0

하지만 맞춤 클래스 로더는 적어도 이론적으로는 가능합니다. –

+0

@MiserableVariable : 주어진 클래스 이름으로 빈 클래스를 정의하는 클래스의 바이트 코드를 반환하여'defineClass (String)'메소드를 구현하는 커스텀 클래스 로더를 작성했다고 상상해보십시오. 이것은 완전히 유효한 클래스 로더이며 정의 할 수있는 모든 클래스를 나열하는 (실용적인) 방법이 없습니다. – maerics

+0

예, 일반적으로 문제는 해결할 수 없습니다. 그러나 특정한 좁은 상황에서는 다릅니다. 폴더 이름'plugins'에있는 모든 .class 파일을 검사하고'register' 메소드를 가진 모든 클래스에 인스턴스를 생성 할 수 있습니다. –

1

예는 있지만 일반적인 경우는 아닙니다. 코드를 패키지화하고 특정 방식으로 JVM을 호출해야합니다. 구체적으로 계측 에이전트를 만들고 java.lang.instrument.Instrumentation.getAllLoadedClasses()으로 전화해야합니다.

패키지 documentation for java.lang.instrument에는 에이전트를 만들고 인스턴스화하는 방법에 대한 자세한 내용이 있습니다.

+0

그는로드 된 클래스 만 원하지는 않지만 클래스 패스에있는 폴더에 떨어 뜨린 (아마도) 새로운 클래스 파일은 제외합니다. –

+0

@MiserableVariable 명확한 것은 알지만로드 할 클래스는 개발 시간에 정의되어 있습니다. 런타임에. –

2

패키지의 모든 클래스에서 진정으로 반복 할 수는 없지만 두 가지 방법으로 문제를 해결할 수 있습니다.

하나는 특정 메서드를 호출해야하는 클래스를 나열하는 별도의 파일을 만드는 것입니다. 이것은 구현하기가 쉽습니다. 파일을 만드는 작업을 할 수도 있지만 자동화 될 수 있습니다.

두 번째 옵션은 잘 알려진 곳 (예 : 단일 폴더 또는 폴더 세트)에서 .class 파일을 찾아 클래스 이름을 추측하여로드하는 것입니다. 단순한 개발 프로세스라면 단일 패키지의 클래스 파일은 아마도 단일 디렉토리에있을 것입니다.

관련 문제