JavaRush /Курсы /Java Syntax /Типы данных

Типы данных

Java Syntax
2 уровень , 2 лекция
Открыта

— Привет, бесплатный работник.

— Т.е. я хотел сказать «Здорова, Амиго». Хочу рассказать тебе о внутреннем устройстве переменных. Ты уже знаешь, что у каждой переменной есть область памяти, привязанная к ней, где эта переменная хранит своё значение.

— Ага. Ты рассказывал это в прошлый раз.

— Отлично. Хорошо, что ты это помнишь. Тогда продолжу.

— Все сложные типы состоят из более простых. Те, в свою очередь, из ещё более простых. Пока, наконец, дело не доходит до самых примитивных, неделимых типов. Их так и называют – примитивные типы. Например, int – это один из примитивных типов, а String – это уже сложный тип, хранящий свои данные в виде таблицы символов (где каждый символ — это примитивный тип — char).

— Очень интересно. Продолжай.

— Сложные типы образуются из простых путём группировки. Такие типы мы называем классами. Когда мы описываем в программе новый класс – это значит, что мы объявляем новый сложный составной тип, данные которого будут или другими сложными типами, или примитивными типами.

Код на Java Описание
public class Person
{
   String name;
   int age;
}
Объявили новый сложный тип – Person.
Его данные – это переменная name типа String (сложный тип) и переменная age типа int (примитивный тип)
public class Rectangle
{
   int x, y, width, height;
}
Объявили новый сложный тип – Rectangle.
Он состоит из четырёх переменных примитивного типа – int.
public class Cat
{
   Person owner;
   Rectangle territory;
   int age;
   String name;
}
Объявили новый сложный тип – Cat. У него есть переменные:
owner, сложный тип Person
territory, сложный тип Rectangle
age, примитивный тип int
name, сложный тип String

— Всё пока ещё понятно, как ни странно.

— Т.к. большие (сложные) типы содержат в себе много маленьких (примитивных), то их объекты занимают много памяти. Больше, чем обычные переменные примитивных типов. Иногда намного больше. Присваивание таких переменных выполнялось очень долго и требовало копирования больших объёмов памяти. Поэтому переменные сложных типов хранят в себе не сам объект, а всего лишь ссылку на него! Т.е. четырёхбайтовый адрес. Этого хватает, чтобы можно было обращаться к данным этих объектов. Всю сложность, связанную с этим, берет на себя Java-машина.

— Ничего не понял.

— Мы уже говорили, что переменная – это как коробка. Если ты хочешь сохранить в ней число 13, то ты можешь написать его на листе и положить в коробку.

— Но представь, что тебе надо сохранить в коробку (переменную) что-нибудь побольше. Например, собаку, машину или твоего соседа Васю. Чтобы не пихать в коробку невпихиваемое, можно поступить проще: вместо собаки взять ее фото, вместо машины – ее номер, вместо Васи – его номер телефона.

— Вот мы берем лист бумаги и пишем на нем телефонный номер Васи. Это и будет аналогом ссылки на объект. Если мы достанем из коробки лист с номером Васи, отксерим его и положим в несколько коробок, то количество ссылок на Васю увеличится, но Вася как был один, так и остался. Что, в общем-то, логично.

— Особенность такого хранения данных в том, что ссылок может быть много, а объект – один.

— Очень интересно. Почти понял, кстати. Ответь только еще раз: что будет, если я одной переменной сложного типа присвою другую переменную сложного типа?

— Тогда эти две переменные будут содержать одинаковые адреса. И, значит, изменение данных, хранящихся в одной переменой сложного типа, приведёт к изменению данных, хранящихся в другой. Объект-то, на который они хранят ссылки, реально всего один. А переменных, хранящих на него ссылки, может быть очень много.

— А что хранится в переменных сложных (ссылочных/классовых) типов, пока там ещё нет ссылки на объект? Такое вообще может быть?

— Да, Амиго. Ты опередил меня своим вопросом. Такое может быть. Если в переменной ссылочного (сложного) типа ещё нет ссылки на какой-то объект, то она хранит null – специальную «пустую ссылку». На самом деле, она просто хранит адрес объекта равный 0. Но Java-машина никогда не создаёт объекты с таким адресом, и поэтому всегда знает, что если переменная-ссылка содержит 0, то никакого объекта там нет.

Код на Java Описание
String s;
String s = null;
Эквивалентные записи.
Person person;
person = new Person();
person = null;
Создали переменную person, её значение null.
Занесли в неё адрес новосозданного объекта.
Присвоили переменной ссылку null.
Cat cat = new Cat();
cat.owner = new Person();
cat.owner.name = "God";
Создали объект Cat, занесли его ссылку в переменную cat. cat.owner равен null.
Занесли в cat.owner ссылку на новосозданный объект Person.
cat.owner.name пока ещё null.
cat.owner.name присвоили имя – God.

— Я правильно понял? Переменные делятся на два типа: примитивные и ссылочные. Примитивные типы у себя внутри хранят значение, а ссылочные – ссылку на объект. Примитивные типы – это int, char, boolean и ещё немного, а ссылочные типы – это все остальные, и образуются они с помощью классов.

— Абсолютно верно, мальчик мой.

— Раз ты все понял, вот тебе задачи на закрепление материала.

Комментарии (1798)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
vlafriday Уровень 1
28 января 2024
28.01.2024 check, мой уровень 2
Константин Уровень 3
10 октября 2023
С 62го раза решил предпоследнюю. И самое главное, что изучил перевод из инт в дабл, и писал то правильно. Но вот return 0 не пробовал изменить и каждый раз пишет, что 9/5 надо в дабл решать, а не в инт. Голову сломал. А в итоге надо было значение return 0 заменить на return ... (Не буду писать ответ). Но в подсказке упорно пишет, что перевожу неправильно, а не дело в return'е. Зато последнюю задачу с первого раза решил. Ох уж этот return 0 мне нервы поел, в предыдущем примере. И главное, что ни слова о нëм, хотя само решение правильное было. Согласен, что с ретëрном не разобрался и это мой косяк)
Ivan Уровень 7 Expert
6 ноября 2022
Кароч, решил ошибку от платформы просто закомментить и кот прошёл...

//import jdk.internal.org.objectweb.asm.tree.ClassNode;
странно, что такая ошибка от платформы джавараш
Ivan Уровень 7 Expert
6 ноября 2022
про настолки - у меня ошибка компиляции в строке 3..... у кого ещё так? файл com/javarush/task/jdk13/task08/task0831/Solution.java, строка 3, позиция 82
hidden #2252782 Уровень 5
29 апреля 2022
если вместо переменой написать метод который возращает переменую и присвоить сылку на обьект .например Cat cat = new Cat(); cat.getB() = new Cat2(); getB()возращает переменую но оно чето неработает
Роман Уровень 33
17 апреля 2022
Да, задача про игры вообще непонятная, от слова совсем. Что нужно сделать - совсем не ясно(
26 апреля 2022
Нужно скопипастить пример для шахмат 4 раза - только каждый раз для новой настольной игры. Не забыть инкрементировать индекс массива, куда будет сохраняться ссылка на новую игру.
Zhulien Уровень 16
13 марта 2022
Задача топ-5 настольных игр вобще непонятна(((((
Zhulien Уровень 16
15 марта 2022
Как обычно делала усложнение самой себе=) все проще, чем хочется сделать))
Alexey Уровень 15
11 января 2022
Что в комментариях случилась какая то путаница, многие вопросы про другие задачи с других лекций.
Anonymous #2931973 Уровень 24
12 января 2022
Если это про меня, то я просто пытался провести параллели между двумя заданиями из прошлой лекции "Муравейник" и текущей лекции - "Любимы настолки". Не понимаю почему методы по-разному запускаются
Alexey Уровень 15
13 января 2022
Не, я вообще про все задания. Тут и с 8 лвл и с 2 и 3 лвл сидят.
Eugene Уровень 4
20 июля 2022
Это потому, что люди писали комментарии, когда были на 2м, но сейчас они выросли до 8, 3лвл
Lo Уровень 35 Expert
10 марта 2023
Год назад проходила этот квест, тогда эта лекция была на 1 или 2 уровне, сейчас почему-то на 8. Наверно от сюда и путаница, лекции поменяли местами, а коменты привязаны к лелции,не к уровню)
Anonymous #2931973 Уровень 24
11 января 2022
Я не могу ни как понять следующее. В задаче про муравейник, что бы отправить созданных муравьев в атаку (и на работы), необходимо было непосредственно задействовать соответствующие методы: - sendForFood - для работяг (sendForFood); - sendIntoBattle - для солдат (soldiers ). Для этого пришлось использовать циклы (for или for-each): -----------из правильного решения--------------- for (int i = 0; i < workers.length; i++) { Worker worker = workers[i]; worker.sendForFood(); } -----------мой подход--------------------------- for (Soldier elem : soldiers) { elem.sendIntoBattle(); } --------------------------------------------------------- А вот в задачке ТОП-5 любимых настольных игр, мы в каждую ячейку массива "collection" передаём ссылочную переменную на создаваемый объект, имеющий тип "BoardGame". Но когда выводим в консоль массив "collection": System.out.println(Arrays.toString(collection)); в консоль выводятся названия игр, прям как мы их назвали (т.е. присвоили переменной экземпляра "name"): "Шашки", "Шахматы" и т.д. 1) Почему так???? (если закоментировать метод "toString" в классе "BoardGame", то тогда выводится будут хеш-коды). Получается, что когда выполняется строка "System.out.println(Arrays.toString(collection));" метод "toString" в классе "BoardGame" сам исполняется. Но если это так, то почему в задачке про муравейник пришлось писать цикл и непосредственно указывать методы, почему там нельзя было также в цикле задействовать ссылочные переменные на классы муравьёв (Soldier и Worker)? 2) метод "toString" в классе "BoardGame" переопределяет метод метод "toString" в классе "Arreys"? Видимо это не так, потому что мы в строке "System.out.println(Arrays.toString(collection));" вызывали метод "toString" из класса "Arreys". Но тогда, почему в классе "BoardGame" метод возвращающий имя называется "toString"? И что это такое: @Override? Какое-то переопределение. Если так то зачем? Что переопределяли?
Alexey Уровень 15
11 января 2022
Потому что в классе BoardGames идет переопределение метода toString, поэтому при попытке вызвать toString у объекта этого класса будет выводиться name. public class BoardGame { String name; @Override public String toString() { return name; } }
Anonymous #2931973 Уровень 24
12 января 2022
Спасибо. Если можно, поясните, пожалуйста: 1. Если мы переопределили метод "toString()" класса "Arreys" в нашем классе "BoardGame", то почему тогда писали в последней строке так: "System.out.println(Arrays.toString(collection));" ? здесь же вызван метод "toString()" класса "Arreys". 2. Как в этой строке: "System.out.println(Arrays.toString(collection));" запускается метод "toString()" класса "BoardGame"? Второй вопрос я вообще не понимаю. В задаче про муравейник мы явно задавили методы из класса, а здесь в строке запустили только ссылку на объект типа "BoardGame" и метод запустился сам.
FuryCydonian Уровень 22
22 января 2022
по-моему в муравейнике тоже ссылки должны в массивах. В каждом массиве в ячейках ссылки на объекты. Поэтому, мы их явно как бы и вызывали, но все равно через ссылки. Потому что в ячейках наверное все-таки лежали не объекты. Если вас этот вопрос конечно беспокоит) и как будто бы вас кажется, что разница есть.
Anonymous #2931973 Уровень 24
23 января 2022
Ну да, там ссылки были, вроде как. Спасибо.
Рыбалко Иван Уровень 36
11 января 2022