Почему некоторые методы в Java изменяют исходное значение, а некоторые нет? - PullRequest
2 голосов
/ 09 февраля 2009

Метод Concat () не изменяет исходное значение. Возвращает новое значение.
как это:

String str = "good";
str.concat("ness");
System.out.println(str);   //"good"

Но какой-то метод изменяет исходное значение. Почему?

В Groovy:

def languages = ["Java", "Groovy", "JRuby"]
languages.reverse()
===> [JRuby, Groovy, Java]
println languages
===> [Java, Groovy, JRuby]


languages.sort()
===> [Groovy, JRuby, Java]
println languages
===> [Groovy, JRuby, Java]

Ответы [ 5 ]

11 голосов
/ 09 февраля 2009

String является неизменяемым в Java. Любой метод, который "модифицирует" String, должен возвращать новый экземпляр String.

Из Java API Спецификации для String класса :

Строки являются постоянными; их ценности нельзя изменить после того, как они создано.

Спецификации языка Java определяют это поведение в Раздел 4.3.3: Строка класса .


Ответ на редактирование:

Похоже, что был добавлен пример в Groovy. (Я раньше не использовал Groovy, поэтому моё понимание этого может быть неверным.)

Из того, что я понимаю из приведенного примера, кажется, что существует список languages, который * reverse и sort - сами эти операции не изменяют содержащиеся в нем объекты String. в списке, но действуют по самому списку.

То, как список возвращает новый список, или то, как он изменяет или не изменяет список, не связано с поведением самих объектов String.

3 голосов
/ 09 февраля 2009

Java API был разработан многими разными людьми, поэтому сложно поддерживать целостность. Я полагаю, что люди обычно признают, что неизменность (то есть внутренние состояния не должны меняться) - это хорошая вещь сейчас, по крайней мере, когда речь идет о ценностных объектах.

Другой похожий вопрос: «Почему индексы иногда основаны на 0 (в большинстве случаев), а иногда - на 1 (JDBC)». Опять же, я считаю, что это еще одна ситуация, когда API слишком широк, и разработчики различных API не координируют свои действия (хотя я могу ошибаться, хотя, если кто-то знает реальную причину, по которой JDBC основан на 1, сообщите мне) *

2 голосов
/ 09 февраля 2009

Я думаю, что вы имеете в виду str.concat("ness") вместо этого. В этом конкретном примере с String s ни один метод не может изменить объект, потому что String s спроектирован так, чтобы быть неизменным . В библиотеке вы найдете множество методов, которые изменяют состояние объекта (например, StringBuffer.replace()), а другие - нет (например, String.replace()). Вам придется внимательно прочитать API , чтобы определить, в чем дело. В конечном счете, это выбор, сделанный разработчиком библиотеки, который должен учитывать функциональность, простоту использования и соглашения, связанные с пакетом, который он или она пишет.

0 голосов
/ 09 февраля 2009

В некоторой степени это также связано со стилем программирования. Не изменять исходный объект и создавать новые копии для отражения изменений - это идиома безопасного программирования. Я полагаю, что Джош Блох упомянул об этом в своей книге «Эффективная Java» (первое издание). Хотя я не могу вспомнить точный термин, который он использовал для этого.

В случае String он возвращает новый объект, потому что String является неизменным. Тем не менее, через Java API вы увидите некоторые места, где исходный объект изменяется, и некоторые места, где возвращается новый объект. Как уже указывалось ранее, причина в том, что над API работали разные люди, и они привносят свои собственные стили программирования.

Относительно другое замечание: сохранение неизменности объектов повышает безопасность кода, а также позволяет нам кодировать определенным образом.

(new Date()).add(new Month(7)).add(new Day(4))

Если каждый метод в Date возвращает новый объект вместо изменения своего собственного состояния, то мы можем написать такой код. Это делает программы очень удобочитаемыми.

Однако сохранение неизменяемости объектов может привести к снижению производительности системы, если у нас есть большие объекты.

0 голосов
/ 09 февраля 2009

Потому что существуют неизменяемые и изменяемые классы.

String, как указывает другой ответ, является неизменным классом. Их значение всегда остается неизменным после создания строки.

Если у вас есть объект ArrayList<Integer>, вы можете использовать его функцию add, чтобы добавить еще одно целое число в список. Функция add изменяет список на месте, а не возвращает новый список. ArrayList является изменяемым.

Ответ на редактирование :

Для вашего отличного примера, вероятно, его дизайнеры сели и заметили, что чаще всего требуется новый список, содержащий обратный результат, и оставить старый список без изменений. (Почему? Я не знаю). С другой стороны, они могли заметить, что есть еще случаи, когда вы не хотите иметь новый список, который содержит отсортированный результат. Так что он делает свою работу на месте. Но я не знаю и раньше не пользовался Groovy, поэтому просто предположение.

В Ruby я слышал, что для этого есть понятие: функции, которые изменяют объекты на месте, после них пишут восклицательный знак, а функции, которые возвращают результат как новый объект, не имеют восклицательного знака:

newObj = obj.sort(); // new sorted list is returned
obj.sort!(); // obj is sorted in-place
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...