我将一些代码分发给我的第一学期编程学生,他们在Eclipse中创建了他们的家庭作业的ZIP存档。对于赋值N,我在类hwN.Submitter中创建一个main方法,它调用库方法foo.Submit.zip()。我将main和库分发到可执行的JAR中。 foo相当稳定,但偶尔会发生变化。该库捆绑在每个作业的JAR文件中。
现在,假设学生将hw1的JAR添加到Eclipse的Build Path中。然后我为hw2更改了foo.Submit的API并分发了它的JAR。由于它稍后在构建路径中添加,因此hw2.Submitter最终从hw1的JAR加载foo.Submit,因为API已更改,所以它不包含该方法。
现在,我似乎有几个选择:A)告诉我的学生删除旧的JAR,B)告诉我的学生重新排序构建路径,或者C)编写我自己的类加载器。我不喜欢A,因为它们对旧作业中运行JAR很有用。我不喜欢B,因为他们是第一学期的程序员。我不能让C工作。
我玩过URLClassLoader,但是父类加载器首先在旧JAR中查找类。我怎样才能取代这些旧的JAR或覆盖父类加载器?
答案 0 :(得分:2)
好的,再多一点,我找到了解决方案。这是我提出的类加载器:
package speccheck;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
/**
* Create a class loader which favors speccheck.* classes from the JAR
* associated with the homework.
*/
public class LatestSpecCheckClassLoader extends URLClassLoader {
/**
* Create a loader which checks $(pwd)/bin/speccheck_TAG_DO_NOT_SUBMIT.jar
* first for speccheck.* classes
*
* @param tag
* Homework tag, like "hw4" or "pre2".
* @throws MalformedURLException
*/
public LatestSpecCheckClassLoader(String tag) throws MalformedURLException {
super(new URL[]{new URL("file://" + System.getProperty("user.dir") + "/bin/" + tag + "/speccheck_" + tag + "_DO_NOT_SUBMIT.jar")});
}
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
// Check for cached.
Class<?> loadedClass = findLoadedClass(name);
if (loadedClass != null) {
return loadedClass;
}
// If the class is in the speccheck package, do not delegate to parent
// loader. Check in the URLs registered with this loader instead.
try {
if (name.startsWith("speccheck.")) {
loadedClass = findClass(name);
}
} catch (ClassNotFoundException e) {
}
// If still not found, then let's defer.
if (loadedClass == null) {
return super.loadClass(name);
}
return loadedClass;
}
}
以Alex Miller作为工作示例。