我正在使用遗传算法为我的大学设计一组时间表来完成我的最后一年项目。
我遇到了一个阻止我前进的错误。我收到以下错误。
Exception in thread "main" java.lang.NullPointerException
at LunchTimeFree.calculateViolations(LunchTimeFree.java:36)
at FitnessFunction.calculateFitnesScore(FitnessFunction.java:34)
at Main.main(Main.java:19)
这对我来说没有任何意义:在这一行是这行代码:
int time = c.genes[i].time;
它将可变时间设置为染色体内某个基因的时间值。 我已经调试了它并在打印了我的时间变量和c.genes [i] .time变量之后插入了println语句,它们都被初始化为变量,即time = 1或2等。
我不明白问题是什么。请有人帮帮我吗?!
public class LunchTimeFree extends constraintInterface {
Chromosome c;
public LunchTimeFree(Chromosome chromo){
c = chromo;
}
@Override
public double calculateViolations() {
double violations=0;
int i = 0;
int y = c.getLength();
while(i <= y-1 )
{
int time = c.genes[i].time;
if (time >= 16 && time <= 25) {
violations = violations + 1;
}
i++;
}
return violations*this.weight;
}
}
public class ChromosomeFactory
{
Chromosome c;
public ChromosomeFactory(int l)
{
c = new Chromosome(l);
DummyDatabase da = new DummyDatabase();
int numOfLectures = da.GetNumLectures();
int i=0;
while(i<=numOfLectures-1)
{
int lecture = da.getLecture(i);
int r = da.Rooms[(int)(Math.random() * da.Rooms.length)];
int t = da.TimeSlots[(int)(Math.random() * da.TimeSlots.length)];
Gene g = new Gene(lecture,lecture,r,t);
c.genes[i] = g;
System.out.println(""+this.c.genes[i].teacher+","+this.c.genes[i].lecture+","+this.c.genes[i].room+","+this.c.genes[i].time+"");
i++;
}
}
}
public class FitnessFunction
{
Chromosome c;
public FitnessFunction(Chromosome newChromo) {
c = newChromo;
}
public double calculateFitnesScore() {
LunchTimeFree ltf = new LunchTimeFree(c);
ltf.setWeight(0.01);
double violationScore =ltf.calculateViolations();
double score = (1/(1 + violationScore));
return score;
}
public class Chromosome
{
Gene[] genes;
public Chromosome(int l)
{
genes = new Gene[l];
}
public int getLength()
{
return genes.length;
}
}
public class Gene
{
public int teacher;
public int lecture;
public int room;
public int time;
public Gene(int t,int l, int r, int time)
{
this.teacher=t;
this.lecture=l;
this.room=r;
this.time=time;
}
}
public class DummyDatabase implements DatabaseAccessor
{
int[] Lecturers = { 1,2,3,4,5,6,7,8,9 };
int[] Lectures = { 1,2,3,4,5,6,7,8,10,11,12,13,14,15,16,17,18,19} ;
int[] TimeSlots = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55};
int[] Rooms = {1,2,3,4,5,6,7,8,9,10};
@Override
public int GetRoom(int entry) {
return this.Rooms[entry];
}
@Override
public int GetNumLectures() {
return this.Lectures.length;
}
@Override
public int getTeacher(int entry) {
return this.Lecturers[entry];
}
@Override
public int getLecture(int entry) {
return this.Lectures[entry];
}
@Override
public int getNumRooms() {
return this.Rooms.length;
}
}
答案 0 :(得分:2)
c
或c.genes[i]
中的某个值为空。
您正在尝试执行操作或请求null属性。所以你得到了NullPointerException
。如果你正在使用Eclipse或你选择的其他IDE,你可以调试它,看看是什么null或发布相关代码,以便我们可以猜测。也许你的i
循环存在缺陷。
答案 1 :(得分:0)
首先:分裂
int time = c.genes[i].time;
到
final Gene[] allGenes = c.genes;
final Gene aGene = allGenes[i];
final int time = aGene.time;
应该在堆栈跟踪中准确显示哪些引用为null。这可能有助于缩小错误的位置。
除此之外,可能需要很长时间的通话,但您发布的代码中的所有内容都可以正常显示:
Chromosome类中的getLength
是否返回genes
数组的长度?或阵列中的基因数量?如果基因数组未完全填充且getLength
表示填充数组槽的(不正确)数量,则while循环可能会过冲并在阵列中命中空值。请注意,您使用int变量l
作为ChromosomeFactory中Chromosome的构造函数参数,但将基因数组填充到numOfLectures
。如果l
用于设置染色体中基因数组的大小,并且l
和numOfLectures
不同,则可能会出现问题。差异将在数组中填充空值。
int y = c.getLength();
while(i <= y-1 )
{
int time = c.genes[i].time;
if (time >= 16 && time <= 25) {
violations = violations + 1;
}
i++;
}
还可以考虑用类似
的for循环替换它for (int i = 0; i < c.getLength(); i++) {
int time = c.genes[i].time;
if (time >= 16 && time <= 25) {
violations++;
}
}
对于循环应该是首选,因为它们最小化循环变量的范围,处理循环变量的增加并且更容易掌握。还可以考虑使用Collection类之一而不是数组。并且强烈考虑使用getter / setter将所有实例变量更改为私有可见性。
如果这不是您必须向我们展示更多代码的原因,例如Chromoson类以及基因阵列的结构。