Функция Java обновляет свою входную переменную - PullRequest
0 голосов
/ 31 января 2012

В данный момент я работаю в лаборатории над функциями фитнеса. Проблема в том, что я делаю функцию SmallChange (), которая делает то, что говорит, досадно, что она обновляет переменную, которую вы ей даете, когда этого не должно быть.

Вот копия полного класса: https://gist.github.com/1710367

Строка 38 - это проблемная строка.

А ниже находится функция. Когда я даю ему solution в качестве ввода, он обновляется solution с небольшими изменениями, которые он вносит, но я не могу понять, как и почему.

Кто-нибудь знает, где я иду не так? Это начинает болеть мой мозг.

// Edits either the angle or velocity of our solution
// by a small amount (about 1% of the diffrence between max and min)
public static Double[] SmallChange(Double[] sol) {
    // Pick a 0 or 1
    switch (r.nextInt(2)) {
    case 1: // Changing the angle
        // The angle change amount
        Double angle = (angleLimits[1] - angleLimits[0]) * 0.01;

        // Make the change, either + or -
        if (r.nextInt(2) == 0) {
            sol[0] += angle;
        } else {
            sol[0] -= angle;
        }

        // Check it's within the limits
        if (sol[0] > angleLimits[1]) {
            sol[0] = angleLimits[1];
        } else if (sol[0] < angleLimits[0]) {
            sol[0] = angleLimits[1];
        }
        break;
    case 0: // Changing the velocity
        // The velocity change amount
        Double velocity = (velocityLimits[1] - velocityLimits[0]) * 0.01;

    // Make the change, either + or -
    if (r.nextInt(2) == 0) {
            sol[1] += velocity;
        } else {
            sol[1] -= velocity;
        }

    // Check it's within the limits
        if (sol[1] > velocityLimits[1]) {
            sol[1] = velocityLimits[1];
        } else if (sol[1] < velocityLimits[0]) {
            sol[1] = velocityLimits[1];
        }
        break;
    }

    return sol;
    }

1 Ответ

8 голосов
/ 31 января 2012

В Java все передается по значению - но это значение всегда является либо примитивом, либо ссылкой.

Таким образом, значение любой переменной массива является ссылкой на массивобъект.Когда вы используете эту переменную в качестве аргумента, значение (ссылка) заканчивается как начальное значение параметра.Он по-прежнему ссылается на тот же массив объект , что и переменная вызывающего - поэтому любые изменения, внесенные в массив, будут видны вызывающим.

Так что просто для пояснения, ваше утверждение здесь неверно:

досадно, что, похоже, обновляет переменную, которую вы ей даете, когда она не должна

Она не изменила значение переменной вообще: эта переменная в вызывающем коде все еще имеет то же значение, что и раньше, ссылку на тот же массив.Просто метод изменяет содержимое массива.

Это похоже на то, как ты копируешь свой адрес на листе бумаги, а потом отдаешь это кому-то: они не могут изменить то, где ты живешь, но они могут изменитьсяцвет вашей входной двери.


Теперь, чтобы решить вашу проблему ...

Если вы хотите клонировать массив, вам придется сделать это явно.Например:

public static Double[] smallChange(Double[] sol) {
    Double[] ret = (Double[]) sol.clone();
    // Now work on ret instead of sol, and return ret at the end

Вы могли бы переназначить на sol, но лично я бы не стал.

Обратите внимание, что вы также можете использовать double[] вместо Double[].

...