有一个抽象类Resource, 以及直接继承自该类的多个子类,ResourceA,ResourceB, ResourceC, 这三个类都重定义了hashcode和equals函数,
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (obj == this) {
return true;
}
ResourceA resourceA = (ResourceA ) obj;
if (.....) {
return true;
}
return false;
}
以及Job类,内含一个对Resource的list变量,来表示在该Job使用了哪些resource,
public class Job {
private List<Resource> resourcesUsedInjob = new ArrayList<Resource>();
}
同时还有一个JobContainer类,包含下列函数,
public Job getJobByResource(Resource resource) {
synchronized (jobsInQueue) {
for (Job job : jobsInQueue) {
for (Resource resourceInJob : job.getResourcesUsedInjob()) {
if (resource.equals(resourceInJob)) {
return job;
}
}
}
return null;
}
}
该函数的本意是要根据传入的resource来获得包含该resource的Job,事实上,在这里
if (resource.equals(resourceInJob)) 调用equals时,存在一个bug。具体在equals函数中的下列语句 ResourceA resourceA = (ResourceA ) obj;
假设传入的Resource 为ResourceA,而当前迭代的job中包含的Resource为ResourceB, 那就会发生cast exception。
解决的办法是先在每次Resource的迭代中,对两个Resource 的Class进行一次比较和过滤。
public Job getJobByResource(Resource resource) {
synchronized (jobsInQueue) {
for (Job job : jobsInQueue) {
for (Resource resourceInJob : job.getResourcesUsedInjob()) {
if(resourceInJob.getClass().equals(resource.getClass())){
if (resource.equals(resourceInJob)) {
return job;
}
}
}
}
return null;
}
}