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

Cat cat = new Cat();//вот сейчас и начался жизненный цикл нашего объекта Cat!
Вначале виртуальная Java-машина выделяет необходимый объем памяти для создания объекта. Потом она создает на него ссылку, в нашем случае — cat, чтобы иметь возможность его отслеживать. После этого происходит инициализация всех переменных, вызов конструктора и вот — наш свежий объект уже живет своей жизнью :) Срок жизни у объектов разный, точных цифр здесь не существует. В любом случае, в течение какого-то времени он живет внутри программы и выполняет свои функции. Если говорить точно, объект является “живым” пока на него есть ссылки. Как только ссылок не остается — объект “умирает”. Например:

public class Car {
  
   String model;

   public Car(String model) {
       this.model = model;
   }

   public static void main(String[] args) {
       Car lamborghini  = new Car("Lamborghini Diablo");
       lamborghini = null;

   }

}
В методе main() объект машины Lamborghini Diablo перестает быть живым уже на второй строке. На него была всего одна ссылка, а теперь этой ссылке был присвоен null. Поскольку на Lamborghini Diablo не осталось ссылок, он становится “мусором”. Ссылку при этом не обязательно обнулять:

public class Car {

   String model;

   public Car(String model) {
       this.model = model;
   }

   public static void main(String[] args) {
       Car lamborghini  = new Car("Lamborghini Diablo");

       Car lamborghiniGallardo = new Car("Lamborghini Gallardo");
       lamborghini = lamborghiniGallardo;
   }

}
Здесь мы создали второй объект, после чего взяли ссылку lamborghini и присвоили ей этот новый объект. Теперь на объект Lamborghini Gallardo указывает две ссылки, а на объект Lamborghini Diablo — ни одной. Поэтому объект Diablo становится мусором. И в этот момент в работу вступает встроенный механизм Java под названием сборщик мусора, или по-другому — Garbage Collector, GC.
Жизненный цикл объекта  - 2
Сборщик мусора — внутренний механизм Java, который отвечает за освобождение памяти, то есть удаление из нее ненужных объектов. Мы не зря выбрали для его изображения картинку с роботом-пылесосом. Ведь сборщик мусора работает примерно так же: в фоновом режиме он “ездит” по твоей программе, собирает мусор, и при этом ты с ним практически не взаимодействуешь. Его работа — удалять объекты, которые уже не используются в программе. Таким образом он освобождает в компьютере память для других объектов. Помнишь в начале лекции мы говорили, что в обычной жизни тебе приходится следить за состоянием твоего компьютера и удалять старые файлы? Так вот, в случае с Java-объектами сборщик мусора делает это вместо тебя. Garbage Collector запускается многократно в течение работы твоей программы: его не надо вызывать специально и отдавать команды, хотя технически это возможно. Позднее мы еще поговорим о нем и разберем процесс его работы более детально. В момент, когда сборщик мусора добрался до объекта, перед самым его уничтожением, у объекта вызывается специальный метод — finalize(). Его можно использовать, чтобы освободить какие-то дополнительные ресурсы, которые использовал объект. Метод finalize() принадлежит классу Object. То есть, наравне с equals(), hashCode() и toString(), с которыми ты уже познакомился ранее, он есть у любого объекта. Его отличие от других методов в том, что он... как бы это сказать... весьма своенравен. А именно — перед уничтожением объекта он вызывается далеко не всегда. Программирование — штука точная. Программист говорит компьютеру что-то сделать — компьютер это и делает. Ты, полагаю, уже привык к такому поведению, и тебе поначалу может быть сложно принять идею: “Перед уничтожением объектов вызывается метод finalize() класса Object. Или не вызывается. Как повезет!” Тем не менее, это действительно так. Java-машина сама определяет, вызывать метод finalize() в каждом конкретном случае или нет. Например, давай попробуем ради эксперимента запустить такой код:

public class Cat {

   private String name;

   public Cat(String name) {
       this.name = name;
   }

   public Cat() {
   }

   public static void main(String[] args) throws Throwable {
       for (int i = 0 ; i < 1000000; i++) {
           Cat cat = new Cat();
           cat = null;//вот здесь первый объект становится доступен сборщику мусора
       }
   }

   @Override
   protected void finalize() throws Throwable {
       System.out.println("Объект Cat уничтожен!");
   }
}
Мы создаем объект Cat и уже в следующей строчке кода обнуляем единственную ссылку на него. И так — миллион раз. Мы явно переопределили метод finalize(), и он должен миллион раз вывести строку в консоль, каждый раз перед уничтожением объекта Cat. Но нет! Если быть точным, на моем компьютере он отработал всего 37346 раз! То есть только в 1 случае из 27-ми установленная у меня Java-машина принимала решение вызвать метод finalize() — в остальных случаях сборка мусора проходила без этого. Попробуй запустить этот код у себя: скорее всего, результат будет отличаться. Как видишь,finalize() трудно назвать надежным партнером :) Поэтому небольшой совет на будущее: не стоит полагаться на метод finalize() в случае с освобождением каких-то критически важных ресурсов. Может JVM его вызовет, а может нет. Кто знает? Если твой объект при жизни занимал какие-то суперважные для производительности ресурсы, например, держал открытым соединение с базой данных, лучше создай в своем классе специальный метод для их освобождения и вызови его явно, когда объект уже будет не нужен. Так ты точно будешь знать, что производительность твоей программы не пострадает. В самом начале мы сказали, что работа с памятью и удаление мусора очень важны, и это действительно так. Неподобающая работа с ресурсами и непонимание процесса сборки ненужных объектов могут привести к утечке памяти. Это одна из самых известных ошибок в программировании. Неправильно написанный программистом код может привести к тому, что для вновь созданных объектов каждый раз будет выделяться новая память, при этом старые, ненужные объекты будут недоступны для удаления сборщиком мусора. Раз уж мы привели аналогию с роботом пылесосом, представь, что будет, если перед запуском робота разбросать по дому носки, разбить стеклянную вазу и оставить на полу разобранный конструктор Lego. Робот, конечно, попытается что-то сделать, но в один прекрасный момент он застрянет.
Жизненный цикл объекта  - 3
Для его правильной работы нужно держать пол в нормальном состоянии и убирать оттуда все, с чем не справится пылесос. По такому же принципу работает и сборщик мусора. Если в программе будет оставаться много объектов, которые он не может собрать (как носок или Lego для робота-пылесоса), в один прекрасный момент память закончится. И может зависнуть не только написанная тобой программа, но и все остальные программы, запущенные в этот момент на компьютере. Для них тоже может не хватать памяти.

Это не нужно заучивать: достаточно просто понять принцип работы.

undefined
14
Задача
Java Syntax Pro, 14 уровень, 1 лекция
Недоступна
Оформляем возврат
В классе Solution есть метод arrayToHashSet(String[]), который должен из переданного массива вернуть HashSet с теми же элементами. Метод main не участвует в проверке.
undefined
14
Задача
Java Syntax Pro, 14 уровень, 1 лекция
Недоступна
Проверка присутствия
В классе Solution есть метод checkWords(String), который должен проверять наличие переданного слова в множестве words. Если слово есть, то выводим в консоль: Слово [переданное слово] есть в множестве Если нет: Слова [переданное слово] нет в множестве Метод main не участвует в проверке. Пример