Возможный дубликат:
Является ли Java "сквозной ссылкой" ?
Сегодня я нашел необычный Java-метод:
private void addShortenedName(ArrayList<String> voiceSetList, String vsName)
{
if (null == vsName)
vsName = "";
else
vsName = vsName.trim();
String shortenedVoiceSetName = vsName.substring(0, Math.min(8, vsName.length()));
//SCR10638 - Prevent export of empty rows.
if (shortenedVoiceSetName.length() > 0)
{
if (!voiceSetList.contains("#" + shortenedVoiceSetName))
voiceSetList.add("#" + shortenedVoiceSetName);
}
}
В соответствии со всем, что я прочитал о Java-поведении для передачи переменных, сложных объектов или нет, этот код ничего не должен делать. Так что... я что-то упустил? Есть ли какая-то тонкость, которая была потеряна для меня, или этот код принадлежит на dailywtf?
Ответ 1
Как сказал Ритмис, Java передает ссылки по значению. Это означает, что вы можете законно называть методы mutating по параметрам метода, но вы не можете переназначить их и ожидать, что значение будет распространено.
Пример:
private void goodChangeDog(Dog dog) {
dog.setColor(Color.BLACK); // works as expected!
}
private void badChangeDog(Dog dog) {
dog = new StBernard(); // compiles, but has no effect outside the method
}
Изменить: В этом случае это означает, что хотя voiceSetList
может измениться в результате этого метода (у него может быть добавлен новый элемент), изменения в vsName
не будет видно за пределами метода. Чтобы предотвратить путаницу, я часто отмечаю параметры моего метода final
, которые не позволяют им переназначить (случайно или нет) внутри метода. Это позволит вообще не компилировать второй пример.
Ответ 2
Java передает ссылки по значению, поэтому вы получаете копию ссылки, но ссылочный объект тот же. Следовательно, этот метод модифицирует список ввода.
Ответ 3
Сами ссылки передаются по значению.
Из Java Как программировать, 4-е издание от Deitel и Deitel: (стр. 329)
В отличие от других языков, Java не позволяет программисту выбирать, проходить ли каждый аргумент по значению или по ссылке. Первичные переменные типа данных всегда передаются по значению. Объекты не передаются методам; скорее, ссылки на объекты передаются методы. Сами ссылки передаются по значению - копия ссылки передается к методу. Когда метод получает ссылку на объект, метод может манипулировать объект напрямую.
Использовал эту книгу, изучая Java в колледже. Прекрасная ссылка.
Вот хорошая статья, объясняющая это.
http://www.javaworld.com/javaworld/javaqa/2000-05/03-qa-0526-pass.html
Ответ 4
Ну, он может манипулировать ArrayList
- который является объектом... если вы передаете ссылку на объект вокруг (даже пройденный значением), изменения этого объекта будут отражены на вызывающем. Это вопрос?
Ответ 5
Я думаю, вы сбиты с толку, потому что vsName изменен. Но в этом контексте это всего лишь локальная переменная на том же уровне, что и shortenedVoiceSetName.
Ответ 6
Мне непонятно, какой именно вопрос в коде есть. Java имеет значение pass-by-value, но массивы являются pass-by-reference, поскольку они не передают объект, а только указатели! Массивы состоят из указателей, а не реальных объектов. Это делает их очень быстрыми, но также делает их опасными для обработки. Чтобы решить эту проблему, вам нужно клонировать их, чтобы получить копию, и даже тогда она будет только клонировать первое измерение массива.
Более подробно см. Мой ответ здесь: на Java, что такое мелкая копия? (также см. мои другие ответы)
Кстати, есть некоторые преимущества, поскольку массивы - это только указатели: вы можете (ab) использовать их как синхронизированные объекты!