Java | Фишки и трюки
7.21K subscribers
182 photos
29 videos
6 files
40 links
Java: примеры кода, интересные фишки и полезные трюки

Купить рекламу: https://telega.in/c/java_tips_and_tricks

✍️По всем вопросам: @Pascal4eg
Download Telegram
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
Что выведет код?
Anonymous Quiz
28%
origin
16%
replace
56%
origin replace
🎉2👍1
⌨️ Несколько способов для избежания NullPointerException:

✔️ Используйте 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
👍81🔥1
⌨️ Что такое finalize()? Зачем он нужен?

Через вызов метода 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
👍91
⌨️ Как работает сборщик мусора?

Механизм сборки мусора - это процесс освобождения места в куче, для возможности добавления новых объектов.

Объекты создаются посредством оператора 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
😁51👍3🤷‍♂1🤣1🖕1
⌨️ Полезные стримы. Метод peek()

Метод 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
👍121
👍21🤣9🔥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🔥31
⌨️ Внутреннее устройство HashSet

Тут разработчики не стали мудрствовать лукаво и просто использовали экземпляр 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
👍191😁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
😁24🤣16🔥5
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"));
}
}
👍51
🎉21😁1
public class Quest {
public static void main(String[] args) {
byte b = 50;
print(b);
}
private static void print(Short num) {
System.out.println(num++);
}
}
👍6
Что выведет код?
Anonymous Quiz
42%
50
24%
51
35%
ошибка компиляции
🎉1