Всегда ли параметры функции Java передаются по значению?

Просто быстрый вопрос о том, как параметры передаются в Java...

...
            if ((index = stdout.indexOf(pattern)) != -1) {
                tidy(stdout, index + pattern.length());
                return true;
            } else if ((index = stderr.indexOf(pattern)) != -1) {
                tidy(stderr, index + pattern.length());
                return true;
...

    private void tidy(StringBuffer buffer, int i) {
        logger.info("Truncating buffer: " + buffer);
        buffer = new StringBuffer(buffer.substring(i));
        logger.info("Buffer now: " + buffer);
    }

В этом случае stdout и stderr (используемые в качестве параметров в tidy()) имеют свои значения, измененные на новый StringBuffer (buffer.substring(i))? Мое предположение заключается в том, что они будут, поскольку объектные переменные (указатели объектов) всегда передаются по значению?

Ответы

Ответ 1

Вы неверно понимаете, что здесь происходит - ссылки на объекты передаются по значению (копия ссылки сделана), поэтому stdout и stderr не изменяются, когда вы вызываете tidy. Копии, которые сделаны из них, изменяются при выполнении строки 2 из tidy.

Передача параметров в Java является источником путаницы для многих людей. Здесь хорошее объяснение.

Ответ 2

От Джеймса Гослинга в "Язык программирования Java":

"... В Java существует ровно один режим передачи параметров - передается по значению - и это упрощает задачу..."

Я думаю, что окончательный авторитет в этом.

Ответ 3

Параметры Java всегда имеют значение pass-by-value, period.

Вот милая статья, объясняющая феномен: http://www.javaranch.com/campfire/StoryPassBy.jsp

В вашем случае не имеет значения, является ли это pbr или pbv, потому что вы повторно назначаете sb новому объекту (вызывая buffer = new StringBuffer(...) и buffer.subString(...) не мутирует сам объект).

Ответ 4

Нет, stdout и stderr не будут изменены, и да, параметры передаются по значению.

Переменная "buffer" будет установлена ​​равной stdout, то есть буфер сначала укажет на тот же объект. Когда буфер изменен, чтобы указать на новый объект, старая ссылка stdout будет по-прежнему указывать на старый объект.

Ответ 5

Ваше предположение неверно. Почему?

Поскольку параметры всегда передаются по значению.

Когда вы выполните:

buffer = new StringBuffer(buffer.substring(i));

вы назначаете новый StringBuffer для локальной ссылки, которая была скопирована из ссылки на параметр. Таким образом, исходный буфер не изменяется.