Java НИКОГДА не передается по ссылке, верно?... верно?

Возможный дубликат:
Является ли 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 при передаче переменных, сложных объектов или нет, этот код не должен делать ничего. Так... я что-то здесь упускаю? Есть ли какая-то тонкость, которая была потеряна на мне, или этот код принадлежит thedailywtf?

6 ответов

Решение

Как сказал Ритмис, Java передает ссылки по значению. Это означает, что вы можете законно вызывать изменяющие методы для параметров метода, но вы не можете переназначать их и ожидать, что значение будет распространяться.

Пример:

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, что удерживает их от переназначения (случайно или нет) внутри метода. Это предотвратит компиляцию второго примера.

Java передает ссылки по значению, поэтому вы получаете копию ссылки, но ссылочный объект остается тем же. Следовательно, этот метод изменяет список ввода.

Сами ссылки передаются по значению.

Из Java Как программировать, 4-е издание от Deitel & Deitel: (стр. 329)

В отличие от других языков, Java не позволяет программисту выбирать, передавать ли каждый аргумент по значению или по ссылке. Примитивные переменные типа данных всегда передаются по значению. Объекты не передаются методам; скорее ссылки на объекты передаются методам. Сами ссылки передаются по значению - копия ссылки передается методу. Когда метод получает ссылку на объект, он может напрямую управлять объектом.

Использовал эту книгу при изучении Java в колледже. Блестящая ссылка.

Вот хорошая статья, объясняющая это. http://www.javaworld.com/javaworld/javaqa/2000-05/03-qa-0526-pass.html

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

Я думаю, что вы запутались, потому что vsName изменен. Но в этом контексте, это просто локальная переменная, точно такого же уровня, что и shortptedVoiceSetName.

Мне не ясно, каков точный вопрос в коде. Java передается по значению, но массивы передаются по ссылке, поскольку они не передают объект, а только указатели! Массивы состоят из указателей, а не реальных объектов. Это делает их очень быстрыми, но также и опасными. Чтобы решить эту проблему, вам нужно клонировать их, чтобы получить копию, и даже тогда она будет клонировать только первое измерение массива.

Для получения более подробной информации смотрите мой ответ здесь: что такое мелкая копия на Java? (также см. мои другие ответы)

Кстати, есть некоторые преимущества, поскольку массивы являются только указателями: вы можете (ab) использовать их как синхронизированные объекты!

Другие вопросы по тегам