❤4👏2🎉1
Heap (куча) используется Java Runtime для выделения памяти под объекты и классы. Создание нового объекта также происходит в куче. Это же является областью работы сборщика мусора. Любой объект, созданный в куче, имеет глобальный доступ и на него могут ссылаться из любой части приложения.
Stack (стек) это область хранения данных также находящееся в общей оперативной памяти (RAM). Всякий раз, когда вызывается метод, в памяти стека создается новый блок, который содержит примитивы и ссылки на другие объекты в методе. Как только метод заканчивает работу, блок также перестает использоваться, тем самым предоставляя доступ для следующего метода. Размер стековой памяти намного меньше объема памяти в куче. Стек в Java работает по схеме LIFO (Последний-зашел-Первый-вышел)
Различия между Heap и Stack памятью:
✔️ Куча используется всеми частями приложения, в то время как стек используется только одним потоком исполнения программы.
✔️ Всякий раз, когда создается объект, он всегда хранится в куче, а в памяти стека содержится лишь ссылка на него. Память стека содержит только локальные переменные примитивных типов и ссылки на объекты в куче.
✔️ Объекты в куче доступны с любой точки программы, в то время как стековая память не может быть доступна для других потоков.
✔️ Стековая память существует лишь какое-то время работы программы, а память в куче живет с самого начала до конца работы программы.
✔️ Если память стека полностью занята, то Java Runtime бросает исключение java.lang.StackOverflowError. Если заполнена память кучи, то бросается исключение java.lang.OutOfMemoryError: Java Heap Space.
✔️ Размер памяти стека намного меньше памяти в куче.
✔️ Из-за простоты распределения памяти, стековая память работает намного быстрее кучи.
Для определения начального и максимального размера памяти в куче используются -Xms и -Xmx опции JVM. Для стека определить размер памяти можно с помощью опции -Xss.
#java #heap #stack #memory
Please open Telegram to view this post
VIEW IN TELEGRAM
👏14❤3👍3
Не совсем. Примитивное поле экземпляра класса хранится не в стеке, а в куче. Любой объект (всё, что явно или неявно создаётся при помощи оператора new) хранится в куче.
#java #heap #stack #question
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10👎4❤1
public class Quest {
public static void main(String[] args) {
String str1 = "Hello World";
String str2 = new String("Hello World");
Set<String> set = new HashSet<>();
set.add(str1);
set.add(str2);
for (String str : set) {
if (str == str1) {
System.out.print("origin ");
}
if (str == str2) {
System.out.print("replace ");
}
}
}
}👍8
🎉2👍1
✔️ Используйте
Optional из пакета java.util.✔️ При сравнении константы с переменной пришедшей из вне, нужно вызывать
equals() на константе.✔️ А при сравнении двух переменных используйте
java.util.Objects#equals.✔️ Используйте библиотеки с null-безопасностью, например, Apache Commons StringUtils.
✔️ Вызывайте методы
equals() и equalsIgnoreCase() на известных объектах.✔️ Применяйте
valueOf() вместо toString().✔️ Воспользуйтесь аннотациями
@NotNull и @Nullable на основе IDE.✔️ При возврате из метода коллекций, не стоит возвращать
null, лучше пустую коллекцию (java.util.Collections#emptyList).#java #NullPointerException #Optional
Please open Telegram to view this post
VIEW IN TELEGRAM
👍16
Отсортировать список с помощью стрима можно используя метод
sorted():
var list = List.of(10, 5, 7, 3);
var sortedList = list.stream()
.sorted()
.toList();
sortedList.forEach(System.out::println);
// 3 5 7 10
Можно передать
Comparator:
var list = List.of(10, 5, 7, 3);
var sortedList = list.stream()
.sorted(Comparator.reverseOrder())
.toList();
sortedList.forEach(System.out::println);
// 10 7 5 3
#java #stream #sorted
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8❤1🔥1
Через вызов метода
finalize() (который наследуется от java.lang.Object) JVM реализуется функциональность аналогичная функциональности деструкторов в С++, используемых для очистки памяти перед возвращением управления операционной системе. Данный метод вызывается при уничтожении объекта сборщиком мусора (garbage collector) и переопределяя finalize() можно запрограммировать действия необходимые для корректного удаления экземпляра класса - например, закрытие сетевых соединений, соединений с базой данных, снятие блокировок на файлы и т.д.После выполнения этого метода объект должен быть повторно собран сборщиком мусора (и это считается серьезной проблемой метода
finalize() т.к. он мешает сборщику мусора освобождать память). Вызов этого метода не гарантируется, т.к. приложение может быть завершено до того, как будет запущена сборка мусора.Объект не обязательно будет доступен для сборки сразу же - метод
finalize() может сохранить куда-нибудь ссылку на объект. Подобная ситуация называется «возрождением» объекта и считается антипаттерном. Главная проблема такого трюка - в том, что «возродить» объект можно только 1 раз.Пример:
public class MainClass {
public static void main(String args[]) {
TestClass a = new TestClass();
a.a();
a = null;
a = new TestClass();
a.a();
System.out.println("!!! done");
}
}
public class TestClass {
public void a() {
System.out.println("!!! a() called");
}
@Override
protected void finalize() throws Throwable {
System.out.println("!!! finalize() called");
super.finalize();
}
}
Так как в данном случае сборщик мусора может и не быть вызван (в силу простоты приложения), то результат выполнения программы с большой вероятностью будет следующий:
!!! a() called
!!! a() called
!!! done
Теперь несколько усложним программу, добавив принудительный вызов Garbage Collector:
public class MainClass {
public static void main(String args[]) {
TestClass a = new TestClass();
a.a();
a = null;
System.gc(); // Принудительно зовём сборщик мусора
a = new TestClass();
a.a();
System.out.println("!!! done");
}
}
Как и было сказано ранее, Garbage Collector может в разное время отработать, поэтому результат выполнения может разниться от запуска к запуску.
Вариант а:
!!! a() called
!!! a() called
!!! done
!!! finalize() called
Вариант б:
!!! a() called
!!! a() called
!!! finalize() called
!!! done
#java #finalize #gc
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9❤1
Механизм сборки мусора - это процесс освобождения места в куче, для возможности добавления новых объектов.
Объекты создаются посредством оператора new, тем самым присваивая объекту ссылку. Для окончания работы с объектом достаточно просто перестать на него ссылаться, например, присвоив переменной ссылку на другой объект или значение
null; прекратить выполнение метода, чтобы его локальные переменные завершили свое существование естественным образом. Объекты, ссылки на которые отсутствуют, принято называть мусором (garbage), который будет удален.Виртуальная машина Java, применяя механизм сборки мусора, гарантирует, что любой объект, обладающий ссылками, остается в памяти — все объекты, которые недостижимы из исполняемого кода, ввиду отсутствия ссылок на них, удаляются с высвобождением отведенной для них памяти. Точнее говоря, объект не попадает в сферу действия процесса сборки мусора, если он достижим посредством цепочки ссылок, начиная с корневой (GC Root) ссылки, т.е. ссылки, непосредственно существующей в выполняемом коде.
Память освобождается сборщиком мусора по его собственному «усмотрению». Программа может успешно завершить работу, не исчерпав ресурсов свободной памяти или даже не приблизившись к этой черте и поэтому ей так и не потребуются «услуги» сборщика мусора.
Мусор собирается системой автоматически, без вмешательства пользователя или программиста, но это не значит, что этот процесс не требует внимания вовсе. Необходимость создания и удаления большого количества объектов существенным образом сказывается на производительности приложений и, если быстродействие программы является важным фактором, следует тщательно обдумывать решения, связанные с созданием объектов, — это, в свою очередь, уменьшит и объем мусора, подлежащего утилизации.
#java #gc #garbage
Please open Telegram to view this post
VIEW IN TELEGRAM
❤6👍2
Статический вложенный класс имеет прямой доступ только к статическим полям обрамляющего класса.
Простой внутренний класс, может обратиться к любому полю внешнего класса напрямую. В случае, если у вложенного класса уже существует поле с таким же литералом, то обращаться к такому полю следует через ссылку на его экземпляр. Например:
Outer.this.field.#java #nested #outer #access
Please open Telegram to view this post
VIEW IN TELEGRAM
❤7👍4🔥2
Метод peek() возвращает поток, состоящий из элементов этого потока, дополнительно выполняя предусмотренное действие над каждым элементом по мере потребления элементов из результирующего потока.
Это промежуточная операция.
Для конвейеров параллельных потоков действие может быть вызвано в любое время и в любом потоке, в котором элемент становится доступным в результате вышестоящей операции. Если действие изменяет общее состояние, оно отвечает за обеспечение необходимой синхронизации.
Этот метод существует в основном для отладки, когда вы хотите видеть элементы по мере их прохождения через определенную точку конвейера:
Stream.of("one", "two", "three", "four")
.filter(e -> e. length() > 3)
.peek(e -> System.out.println("Filtered value: " + e))
.map(String::toUpperCase)
.peek(e -> System.out.println("Mapped value: " + e))
.collect(Collectors.toList());
// Filtered value: three
// Mapped value: THREE
// Filtered value: four
// Mapped value: FOUR
В тех случаях, когда реализация потока может оптимизировать создание некоторых или всех элементов (например findFirst или count), действие не будет вызываться для этих элементов.
#java #stream #peek
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12❤1
Понятия "оператор" и "операнд" играют ключевую роль в построении выражений и выполнении операций.
Оператор — это специальный символ или ключевое слово, которое указывает на выполнение определенного действия. Операторы используются для выполнения операций над переменными и значениями.
В Java существует несколько типов операторов:
✔️ Арифметические операторы
✔️ Операторы присваивания
✔️ Операторы сравнения
✔️ Логические операторы
✔️ Побитовые операторы
✔️ Операторы инкремента и декремента
Операнд — это элемент, над которым оператор выполняет действие. Операнды могут быть переменными, константами или результатами других выражений.
Примеры:
👉 В выражении a + b операнды это a и b, а оператор +.
👉 В выражении x = 5 операнды это x и 5, а оператор =.
👉 В выражении count++ операнд это count, а оператор ++.
#java #operator #operand
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8🔥3❤1
Тут разработчики не стали мудрствовать лукаво и просто использовали экземпляр
HashMap внутри HashSet. Каждый элемент HashSet хранится как ключ в этой хэш-таблице, а значение для каждого ключа установлено в фиксированное значение PRESENT, что является специальным объектом (обычно new Object()).При добавлении элемента, у него вычисляется хэш-код, определяется соответствующий бакет, и элемент добавляется в этот бакет, если он еще не присутствует (проверяется с помощью метода
equals()).При удалении вычисляется хэш-код элемента, определяется бакет, и элемент удаляется, если он присутствует в этом бакете.
Упрощённый код класса HashSet:
public class HashSet<E> implements Set<E>, Cloneable, java.io.Serializable {
// Внутренний экземпляр HashMap
private transient HashMap<E, Object> map;
// Специальный константный объект, используемый в качестве значения для всех ключей
private static final Object PRESENT = new Object();
public HashSet() {
map = new HashMap<>();
}
public boolean add(E e) {
return map.put(e, PRESENT) == null;
}
public boolean remove(Object o) {
return map.remove(o) == null;
}
public boolean contains(Object o) {
return map.containsKey(o);
}
// Другие методы...
}
#java #hashset #hashmap
Please open Telegram to view this post
VIEW IN TELEGRAM
👍19❤1😁1
public class Quest {
public static void main(String[] args) {
int b = oper2() | oper3() & oper4();
System.out.println("-" + b);
}
private static byte oper2() {
System.out.print(2);
return 2;
}
private static byte oper3() {
System.out.print(3);
return 3;
}
private static byte oper4() {
System.out.print(4);
return 4;
}
}#java #quest
👍2
🎉7
class Person {
Long id;
String name;
public Person(Long id, String name) {
this.id = id;
this.name = name;
}
@Override
public boolean equals(Object obj) {
System.out.print(1);
if (obj == this) {
return true;
}
if (obj instanceof Person person) {
return id.equals(person.id);
}
return false;
}
}
public class Quest {
public static void main(String[] args) {
List<Person> list = new ArrayList<>();
list.add(new Person(1L, "Leo"));
list.add(new Person(2L, "Raph"));
list.add(new Person(3L, "Donnie"));
list.add(new Person(4L, "Mikey"));
list.contains(new Person(3L, "Shredder"));
}
}👍5❤1