У меня есть класс Path, который, как я думаю, неизменен. В другом классе, называемом Test, у меня есть окончательная ссылка на объект Path.Конечные и неизменные переменные изменения в Java
Тем не менее, между конструктором и методом геттера объект Path изменяется, хотя он является неизменным и ссылка является окончательной. Я знаю это, потому что длина узла массива int в пути изменяется от конструктора к получателю. Кажется, что объект полностью совершенно другой.
Моя программа многопоточная, но я пробовал ее с одним потоком, и это не решило проблему.
Вот неизменное класс Path
public class Path implements Iterable<Point> {
private final int[] nodes;
private final double distance;
public Path(Scenario scenario, int gateway, int sensor){
this.scenario = scenario;
nodes = new int[2];
nodes[1] = -gateway - 1;
nodes[0] = sensor;
distance = scenario.DISTANCE_GATEWAY_SENSOR[gateway][sensor];
}
public Path(Path base, int newSensor){
scenario = base.scenario;
//Copy the old path. These are rigid structures so that we do not need to deep copy
nodes = new int[base.nodes.length + 1];
for(int i = 0; i < base.nodes.length; i++)
nodes[i + 1] = base.nodes[i];
nodes[0] = newSensor;
distance = base.distance + scenario.DISTANCE_SENSOR_SENSOR[newSensor][nodes[1]];
}
public Path(Scenario scenario, int[] nodes, boolean isSensor, double distance){
this.scenario = scenario;
this.distance = distance;
this.nodes = Arrays.copyOf(nodes, nodes.length);
if(!isSensor)
for(int i = 0; i < this.nodes.length; i++)
this.nodes[i] = -this.nodes[i] -1;
}
@Override
public Iterator<Point> iterator() {
return new PointIterator();
}
public class PointIterator implements Iterator<Point>{
private int next = -1;
@Override
public boolean hasNext() {
return next + 1 < nodes.length;
}
@Override
public Point next() {
int p = nodes[++next];
if(p >= 0)
return scenario.SENSOR_LOCATION[p];
return scenario.CS_LOCATION[-p - 1];
}
@Override
public void remove() {
throw new IllegalAccessError("This method is not supported");
}
}
}
и вот класс Test (с конечной ссылкой на класс Path)
public class Test {
private final Path gatewayTour;
public Test(Scenario scenario, boolean[] chosenGateway){
distanceFitness = 0;
Point current = scenario.SINK_LOCATION;
boolean visited[] = new boolean[scenario.CONFIG.NUM_CS];
int nextGateway;
LinkedList<Integer> order = new LinkedList<>();
do {
double minimumDistance = Double.MAX_VALUE;
nextGateway = -1;
for(int i = 0; i < scenario.CONFIG.NUM_CS; i++)
if(!visited[i] && CHOSEN_GATEWAYS[i] && scenario.CS_LOCATION[i].isCloserThan(minimumDistance, current)) {
nextGateway = i;
minimumDistance = scenario.CS_LOCATION[i].distance(current);
}
if(nextGateway >= 0) {
distanceFitness += minimumDistance;
visited[nextGateway] = true;
order.add(nextGateway);
current = scenario.CS_LOCATION[nextGateway];
}
} while(nextGateway >= 0);
int path[] = new int[order.size()];
Iterator<Integer> it = order.iterator();
for(int i = 0; i < order.size(); i++)
path[i] = it.next().intValue();
gatewayTour = new Path(scenario, path, false, distanceFitness);
}
public Path getGatewayTour(){
//Here, the gatewayTour object has changed and does not have the same content as in the constructor
return gatewayTour;
}
}
Есть ли что-нибудь в моей программе, которая позволяет объект изменить? Я уточню: есть ли что-нибудь, что позволило бы «узлам» массива int в классе Path изменить длину? Потому что это настоящая проблема.
[EDIT]: Мое испытание было ошибочным, что заставило меня поверить, что значение моего массива «узлов» изменилось. Спасибо всем, кто указал на недостатки или возможные улучшения в моем коде.
Я согласен с ответом AlexR, потому что он указал, что можно изменить отдельные элементы в конечном массиве; то, чего я не знал, и что помогает решить проблему.
Можете ли вы показать свои '// некоторые конструкторы здесь для инициализации переменных? – fge
BTW, '.remove()' should throw 'UnsupportedOperationException' – fge
Вы можете изменить содержимое конечных контейнеров, но не отменять ссылку или повторно ссылаться на него, можем ли мы увидеть конструкторы и геттеры? – arynaq