是的,这是完全可能的,只要你正确地贯彻ForwardingJavaFileManager
。两种最重要的方法是inferBinaryName()和list()。如果你正确设置了这两个,编译器将能够解析你之前编译的类。
inferBinaryName()
必须返回类'simple name(例如,com.test.Test
的推断二进制名称将只是Test
)。下面是我实现的(我的JavaFileObject
子类被称为InAppJavaFileObject
):
@Override
public String inferBinaryName(Location location, JavaFileObject javaFileObject) {
if(location == StandardLocation.CLASS_PATH && javaFileObject instanceof InAppJavaFileObject) {
return StringUtils.substringBeforeLast(javaFileObject.getName(), ".java");
}
return super.inferBinaryName(location, javaFileObject);
}
注意,我是从年底剥离“的.java”。在构建JavaFileObject
时,文件名必须以“.java”结尾,但如果稍后不去除后缀,编译器将无法找到您的类。
list()
有点复杂,因为你必须小心地与你的委托文件管理器一起玩。在我的实现,我把地图完全限定类名来我的JavaFileObject
子类,我可以遍历:
@Override
public Iterable<JavaFileObject> list(Location action, String pkg, Set<JavaFileObject.Kind> kind, boolean recurse) throws IOException {
Iterable<JavaFileObject> superFiles = super.list(action, pkg, kind, recurse);
// see if there's anything in our cache that matches the criteria.
if(action == StandardLocation.CLASS_PATH && (kind.contains(JavaFileObject.Kind.CLASS) || kind.contains(JavaFileObject.Kind.SOURCE))) {
List<JavaFileObject> ourFiles = new ArrayList<JavaFileObject>();
for(Map.Entry<String,InAppJavaFileObject> entry : files.entrySet()) {
String className = entry.getKey();
if(className.startsWith(pkg) && ("".equals(pkg) || pkg.equals(className.substring(0, className.lastIndexOf('.'))))) {
ourFiles.add(entry.getValue());
}
}
if(ourFiles.size() > 0) {
for(JavaFileObject javaFileObject : superFiles) {
ourFiles.add(javaFileObject);
}
return ourFiles;
}
}
// nothing found in our hash map that matches the criteria... return
// whatever super came up with.
return superFiles;
}
一旦你拥有了这些方法正确实施,其余的只是工作。请享用!
对不起,如果我很慢,但我不明白你发布的链接如何解决这个问题。我自己遇到了同样的问题......如果我可以分别编译类,我的API就会变得更简洁,易于管理。如果您可以将解决方案作为答案发布,我将不胜感激。 :) – stevevls 2011-12-06 14:08:59
实际上,我刚刚解决了这个问题,所以我已经为后人的缘故发布了一个答案。感谢您的好问题! – stevevls 2011-12-07 13:07:50