Sunday, May 26, 2013

Небольшое java-исследование

    Я тут вырос немного и наткнулся снова на этот пост. Хочу внести в него очень важные правки, но сам текст изменять не буду, напишу перед ним. Строки в джаве передаются по ссылке, в примерах они не поменялись, потому что объект строки immutable (то есть неизменяемый). Вместо старой строки в методе создается новый объект (равносильно тому, что я бы вместо вызова сеттера создал новый объект, когда тестировал объекты Human human = new Human("Polina")), поэтому исходный объект не меняется.

    Всем привет!
    Сегодня будет немного технический пост, так что те, кто ничего не понимает в программировании, могут смело закрыть эту страницу. Те, кто очень хорошо понимают джаву, в принципе, тоже могут закрыть страницу, но если вам интересно почитать наблюдения любителя, можете почитать.
    Итак, что сподвигло написать меня технический пост? Природное любопытство. Ситуация сложилась такая, что к четвергу мне нужно сдать готовый компилятор джавы своему преподавателю, но речь пойдет совсем не о нем. Речь пойдет о том, что, взявшись читать книгу дракона (народное название книги Ахо, Лам, Сети, Ульман - Компиляторы. Принципы, технологии, инструменты) я наткнулся там на фразу "Как уже отмечалось при рассмотрении передачи параметров по значению, языки программирования, такие как Java, решают задачу передачи массивов, строк и других объектов путем копирования ссылок на них. В результате Java ведет себе так, как если бы для всех типов, отличных от базовых (наподобие целых чисел или чисел с плавающей точкой), использовалась передача параметров по ссылке".
    Неужели? - подумал я, и решил проверить.
    Начал я со строк, написал вот такой простенький метод:

    Несложно понять, что он передает строку в метод, где ей присваевается другое значение, а, по завершении метода печатает строку на экран. Если верить книжке, результат должен быть следующим:
    "Ilya wants a chocolate
      Making trick...
      Polina wants a chocolate!"
    Скомпилировав и запустив программу, я увидел следующий результат:
    Кажется, трюк провалился. Все-таки строки джава передает не по ссылке, а по значению, это, я думаю, намного упрощает жизнь, но выглядит немного странно (в связи с дальнейшими эксперементами).
    Одними строками я не ограничился и решил попробовать массивы. Добавив еще один метод и немного переделав основной, я получил такой код:

    Все, практически, то же самое, только вместо строки передается массив, с единственным заполненым элементом. Что же мы видим после компиляции?

    Воаля! Трюк удался, на этот раз книжка нас не обманула. Массивы в джаве действительно передаются по ссылке, а не по значению, поэтому нужно быть предельно аккуратным, используя их.
    Заранее зная результат следующей попытки, я все же решил проверить, на всякий случай, что будет вот с таким кодом:

    Тот же самый трюк со строками, только теперь туда передается элемент массива. Результат оправдал ожидания, ничего удивительного:

    Со строками и массивами все стало более-менее ясно - строки передаются по значению (скорее всего, создатели джавы хотели, чтобы строки были базовым типом, наравне с интами флоатами и прочими булеанами, несмотря на то, что унаследованы от Object), а массивы передаются по ссылке. 
    Что ж, настал черед классов. Давайте посмотрим, как ведут себя объекты, передаваемые в функцию, в качестве параметра. В голове моей, откуда водились мысли о том, что объекты-то, уж точно должны передаваться по ссылке, но, все же, лучше не строить поспешных домыслов, а проверить на деле. Итак, у нас есть следующий класс:

    И его объект будет передаваться вот в такой метод:

    Ничего оригинального, все то же самое. Давайте скомпилируем и посмотрим, что получится.

    Я думаю, объяснять ничего не надо, на картинке все видно. 
  Что меня удивило в это ситуации? String, будучи унаследованным от Object, передается в функцию по значению, а класс, будучи также унаследованным от Object передается по ссылке. Я уже высказал выше свое предположение о том для чего String передается не по ссылке, но все же, почему бы не ввести единообразие? Скорее всего, на то есть свои причины, о которых я не догадываюсь.
    Подведя итоги, можно сказать, что книга дракона немного приврала насчет строк в java, но зато сподвигла меня на небольшое исследование, которое немного пополнило копилку моих знаний об этом языке программирования. Если когда-нибудь буду проводить собеседование по джаве, обязательно помучаю соискателей этими примерами.