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

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

✍️По всем вопросам: @Pascal4eg
Download Telegram
⌨️ Что такое generics?

Generics - это технический термин, обозначающий набор свойств языка позволяющих определять и использовать обобщенные типы и методы. Обобщенные типы или методы отличаются от обычных тем, что имеют типизированные параметры.

Примером использования обобщенных типов может служить Java Collection Framework. Так, класс LinkedList<E> - типичный обобщенный тип. Он содержит параметр E, который представляет тип элементов, которые будут храниться в коллекции. Создание объектов обобщенных типов происходит посредством замены параметризированных типов реальными типами данных. Вместо того, чтобы просто использовать LinkedList, ничего не говоря о типе элемента в списке, предлагается использовать точное указание типа LinkedList<String>, LinkedList<Integer> и т.п.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍102
⌨️ try-catch-finally

try — данное ключевое слово используется для отметки начала блока кода, который потенциально может привести к ошибке.

catch — ключевое слово для отметки начала блока кода, предназначенного для перехвата и обработки исключений в случае их возникновения.

finally — ключевое слово для отметки начала блока кода, который является дополнительным. Этот блок помещается после последнего блока catch. Управление передаётся в блок finally в любом случае, было выброшено исключение или нет.

Общий вид конструкции для обработки исключительной ситуации выглядит следующим образом:

try {
//код, который потенциально может привести к исключительной ситуации
}
catch(SomeException e ) { //в скобках указывается класс конкретной ожидаемой ошибки
//код обработки исключительной ситуации
}
finally {
//необязательный блок, код которого выполняется в любом случае
}


Возможно ли использование блока try-finally (без catch)?
Такая запись допустима, но смысла в такой записи не так много, всё же лучше иметь блок catch, в котором будет обрабатываться необходимое исключение.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍86❤‍🔥1
⌨️ Есть класс Point{int x, y;}. Почему хэш код в виде 31 * x + y предпочтительнее чем x + y?

Множитель создает зависимость значения хэш кода от очередности обработки полей, что в итоге порождает лучшую хэш функцию.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥82👍1
⌨️ instanceof или getClass() == ...

Часто нам нужно проверить является ли объект экземпляром определенного класса, например в методе equals(). Существует несколько способов это сделать. Разберём два из них.

instanceof проверяет, является ли ссылка на объект в левой части экземпляром типа в правой части или каким-либо подтипом.

getClass() == ... проверяет, идентичны ли типы.

Выбирать способ проверки типа нужно исходя из решаемой задачи. В методе equals() можно использовать оба способа в зависимости от того собираетесь ли вы позволять сравнивать объект определенного класса и объект класса наследника.


class Parent { }
class Child extends Parent { }

public class Test {
public static void main(String[] args) {
Parent parent = new Parent();
Child child = new Child();
System.out.println(parent instanceof Parent); // true
System.out.println(child instanceof Parent); // true
System.out.println(parent.getClass() == Parent.class); // true
System.out.println(child.getClass() == Parent.class); // false
}
}


#java #instanceof #getClass
Please open Telegram to view this post
VIEW IN TELEGRAM
👍114
⌨️ Правила переопределения метода Object.hashCode()

Общий совет: выбирать поля, которые с большой долью вероятности будут различаться. Для этого необходимо использовать уникальные, лучше всего примитивные поля, например, такие как id, uuid. При этом нужно следовать правилу, если поля задействованы при вычислении hashCode(), то они должны быть задействованы и при выполнении equals().

➡️ Могут ли у разных объектов быть одинаковые hashCode()?
Да, могут. Метод hashCode() не гарантирует уникальность возвращаемого значения. Ситуация, когда у разных объектов одинаковые хэш коды называется коллизией. Вероятность возникновения коллизии зависит от используемого алгоритма генерации хэш кода.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍84
⌨️ Полные и сокращённые версии AND и OR

&& и || называются сокращёнными логическими операторами AND и OR соответственно, или операторами короткой схемы вычислений. В спецификации Java их ещё зовут условными. Значения их операндов могут быть только булева типа.

В отличие от двойных, одиночные & и | называются операторами полной схемы вычислений. Значения их операндов могут быть как только булевыми, так и только целочисленными (вместе с оператором ^ они используются в побитовых операциях).

В чём разница?

В том, что для операторов & и | всегда вычисляются значения обоих операндов, а при работе операторов && и || второй операнд вычисляется только по необходимости.

То есть иногда результат выражения однозначно определён уже по первому операнду:

✔️ Если первый операнд && равен false, то второй не вычисляется, так как уже понятно, что результат всего выражения будет false.

✔️ Если первый операнд || равен true, то второй не вычисляется, так как уже понятно, что || вернёт true.

&& и || используют как операторы булевой логики. Они оперируют значениями только булева типа и применяются только в логических выражениях.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍102
Скачать файл используя Java NIO

Пакет Java NIO предлагает возможность передавать байты между двумя каналами без их буферизации в памяти приложения.

Чтобы прочитать файл по нашему URL-адресу, мы создадим новый ReadableByteChannel из потока URL-адреса.

Байты, прочитанные из ReadableByteChannel, будут переданы в FileChannel, соответствующий загружаемому файлу.

Используем метод transferFrom() из класса ReadableByteChannel для загрузки байтов с заданного URL-адреса в наш FileChannel.

Методы transferTo() и transferFrom() более эффективны, чем простое чтение из потока с использованием буфера. В зависимости от операционной системы данные могут быть перенесены непосредственно из кэша файловой системы в наш файл без копирования каких-либо байтов в память приложения.

В системах Linux и UNIX эти методы используют метод нулевого копирования, который уменьшает количество переключений контекста между режимом ядра и пользовательским режимом.
👍84🔥3
⌨️ Ссылки на методы — это способ упрощенного вызова методов или конструктора, который позволяет передавать их как аргументы в методы или сохранять в переменных. Ссылки на методы появились в Java 8 и являются частью улучшенной поддержки функционального программирования в языке.

Есть несколько видов ссылок на методы:

1️⃣ Ссылка на статический метод
Используется для вызова статических методов класса.
Синтаксис:

ContainingClass::staticMethodName

Пример:

import java.util.function.Function;

public class MethodReferenceExample {
public static void main(String[] args) {
Function<String, Integer> converter = Integer::parseInt;
Integer number = converter.apply("123");
System.out.println(number); // 123
}
}


2️⃣ Ссылка на метод экземпляра конкретного объекта
Используется для вызова методов экземпляра объекта.
Синтаксис:

containingObject::instanceMethodName

Пример:

import java.util.Arrays;
import java.util.List;

public class MethodReferenceExample {
public static void main(String[] args) {
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
names.forEach(System.out::println);
}
}


3️⃣ Ссылка на метод экземпляра произвольного объекта определенного типа
Синтаксис:

ContainingType::methodName

Пример:

import java.util.function.Function;

public class FunctionExample {
public static void main(String[] args) {
Function<String, Integer> stringLength = String::length;
Integer length = stringLength.apply("Hello, World!");
System.out.println(length); // 13
}
}


Отличие от предыдущего вида в том, что в предыдущем ссылка на метод получается у конкретного объекта, стало быть вызовется метод этого объекта, а в нашем случае при получении ссылки на метод, мы знаем только метод, но объект у которого вызовется этот метод еще не известен, он будет предоставлен при вызове метода. Код выше будет означать "Hello, World!".length()

4️⃣ Ссылка на конструктор
Используется для вызова конструктора.
Синтаксис:

ClassName::new

Пример:

import java.util.function.Supplier;

public class MethodReferenceExample {
public static void main(String[] args) {
Supplier<MethodReferenceExample> exampleSupplier = MethodReferenceExample::new;
MethodReferenceExample example = exampleSupplier.get();
System.out.println(example); // MethodReferenceExample@<hashcode>
}
}


#java #MethodReference
Please open Telegram to view this post
VIEW IN TELEGRAM
👍94
☕️Интеграция звуковых эффектов и музыки в игру на Java

😎Задача:
🟢При разработке игр на Java требуется работать со звуком и музыкой.

🟢Нужно подключить звуковые звуки (эффекты и музыку) к игровому проекту.

🟢Реализовать звуковой сигнал в нужные моменты (например, выстрел, прыжок, победа).

🟢Обеспечить громкость и возможность паузы/продолжения музыки.

🟢Оптимизировать загрузку и меры для минимизации задержек и нагрузки на систему.



😎Способы решения

🔢Использование стандартного Java Sound API


🔢Библиотека
🟢javax.sound.sampled позволяет работать с аудиофайлами формата WAV, AIFF и др.


🔢Использование различных библиотек
🟢Например, LWJGL OpenAL , TinySound , JOAL — более мощные и гибкие решения для работы со звуком в играх, 3D-звуке, резервных источниках и других возможностях.


🔢Интеграция с игровыми движками
🟢Если используются игровые движки (например, LibGDX), он обычно предоставляет собственный удобный API для работы со звуком.


😎Пример на Java с использованием стандартного Java Sound API


import javax.sound.sampled.*;
import java.io.File;
import java.io.IOException;

public class SoundPlayer {

    private Clip clip;

    // Загрузка и подготовка звукового файла
    public void loadSound(String filepath) {
        try {
            AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(new File(filepath));
            clip = AudioSystem.getClip();
            clip.open(audioInputStream);
        } catch (UnsupportedAudioFileException | IOException | LineUnavailableException e) {
            System.err.println("Ошибка загрузки звука: " + e.getMessage());
        }
    }

    // Воспроизведение звука
    public void play() {
        if (clip == null) return;
        if (clip.isRunning()) clip.stop();
        clip.setFramePosition(0);
        clip.start();
    }

    // Остановка звука
    public void stop() {
        if (clip != null && clip.isRunning()) {
            clip.stop();
        }
    }

    // Регулировка громкости (от 0.0 до 1.0)
    public void setVolume(float volume) {
        if (clip == null) return;
        FloatControl gainControl = (FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN);
        float dB = (float)(Math.log10(volume) * 20);
        gainControl.setValue(dB);
    }

    public static void main(String[] args) {
        SoundPlayer sound = new SoundPlayer();
        sound.loadSound("jump.wav"); // Замените на путь к вашему звуковому файлу
        sound.setVolume(0.5f);
        sound.play();

        // Для демонстрации задержка перед завершением программы
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        sound.stop();
    }
}
Please open Telegram to view this post
VIEW IN TELEGRAM
👍115🔥1👏1
☕️Работа с сохранением и загрузкой прогресса игрока в Java: сериализация данных

😎Задача:
🟢Сохранить состояние игрового объекта (например, класс Player) в файл.

🟢Загрузить данные из файла при старте игры.

🟢Обеспечить корректную работу даже при изменениях в структуре класса.

🟢Обработать возможные ошибки ввода-вывода.


😎Способы решения

🔢Стандартная сериализация Java (Serializable)

🟢Класс реализует интерфейс Serializable, и с помощью ObjectOutputStream и ObjectInputStream объекты записываются и читаются из файла.


🔢Использование JSON или XML

🟢Сериализация в человекочитаемый формат с помощью библиотек, например, Gson, Jackson (для JSON) или JAXB (для XML). Это удобно для отладки и совместимости.


🔢Кастомная сериализация

🟢Реализация собственных методов записи и чтения данных, например, через DataOutputStream/DataInputStream, что даёт больше контроля над форматом и размером файла.


😎Пример реализации на Java с использованием стандартной сериализации

import java.io.*;

class Player implements Serializable {
    private static final long serialVersionUID = 1L;
    String name;
    int level;
    int score;

    public Player(String name, int level, int score) {
        this.name = name;
        this.level = level;
        this.score = score;
    }

    @Override
    public String toString() {
        return "Player{name='" + name + "', level=" + level + ", score=" + score + '}';
    }
}

public class SaveLoadGame {
    public static void savePlayer(Player player, String filename) {
        try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filename))) {
            oos.writeObject(player);
            System.out.println("Прогресс сохранён.");
        } catch (IOException e) {
            System.err.println("Ошибка при сохранении: " + e.getMessage());
        }
    }

    public static Player loadPlayer(String filename) {
        try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filename))) {
            return (Player) ois.readObject();
        } catch (IOException | ClassNotFoundException e) {
            System.err.println("Ошибка при загрузке: " + e.getMessage());
            return null;
        }
    }

    public static void main(String[] args) {
        Player player = new Player("Игрок1", 5, 1500);
        String saveFile = "player.dat";

        savePlayer(player, saveFile);

        Player loadedPlayer = loadPlayer(saveFile);
        if (loadedPlayer != null) {
            System.out.println("Загруженный игрок: " + loadedPlayer);
        }
    }
}
Please open Telegram to view this post
VIEW IN TELEGRAM
👍85🔥2
⌨️ Описание и назначение разных циклов

Цикл for со счетчиком

for (initialization; condition; update) {
// тело цикла
}

Описание:
initialization: выполняется один раз перед началом цикла. Обычно используется для инициализации счетчика.

condition: проверяется перед каждой итерацией. Если условие истинно, выполняется тело цикла.

update: выполняется после каждой итерации. Обычно используется для изменения счетчика.


int[] numbers = {1, 2, 3, 4, 5};
for (int i = 0; i < numbers.length; i++) {
System.out.println(i + ": " + numbers[i]);
}

Применение:
Используется, когда известно количество итераций заранее. Часто применяется для работы с массивами или коллекциями, когда нужен индекс.


Цикл for-each

for (type element : collection) {
// тело цикла
}

Описание:
Итерируется по каждому элементу коллекции (например, массива, списка, множества). Обеспечивает удобный способ доступа к каждому элементу без использования индексов.


int[] numbers = {1, 2, 3, 4, 5};
for (int number : numbers) {
System.out.println(number);
}

Применение:
Предпочтителен, когда не нужен доступ к индексам элементов.


Цикл while

while (condition) {
// тело цикла
}

Описание:
condition: проверяется перед каждой итерацией. Если условие истинно, выполняется тело цикла.


String code = UUID.randomUUID().toString();
boolean isCodeExists = repo.isCodeExists(code);
while (isCodeExists) {
code = UUID.randomUUID().toString();
isCodeExists = repo.isCodeExists(code);
}
repo.saveCode(code);

Применение:
Используется, когда количество итераций неизвестно заранее и определяется во время выполнения программы. Цикл может не выполниться ни одного раза.


Цикл do-while

do {
// тело цикла
} while (condition);

Описание:
Выполняет тело цикла хотя бы один раз, а затем проверяет условие condition. Если условие истинно, цикл повторяется.


String command;
do {
command = readCommand();
doCommand(command);
} while (!"EXIT".equals(command));

Применение:
Используется, когда тело цикла должно выполниться хотя бы один раз, независимо от условия. Часто применяется для меню или ввода данных, где сначала нужно выполнить действие, а затем проверить условие.

#java #cycles #for #while
Please open Telegram to view this post
VIEW IN TELEGRAM
👍81
⌨️ Методы compose и andThen интерфейса Function

Function<T,R> — функциональный интерфейс, который умеет принимать объект типа T и возвращать R. У него есть два метода-комбинатора:

default <V> Function<V,R> compose(Function<? super V,? extends T> before)
default <V> Function<T,V> andThen(Function<? super R,? extends V> after)


🔵f.compose(g) → сначала выполняет g, потом результат передаёт в f.
🔵f.andThen(h) → сначала выполняет f, потом h.

✔️ Пример:

import java.util.function.Function;

public class ComposeAndThenDemo {
public static void main(String[] args) {
Function<String, Integer> parse = Integer::parseInt;
Function<Integer, Double> half = i -> i / 2.0;
Function<Double, String> toStr = d -> "Result: " + d;

// Составляем: сначала parse, затем half, затем toStr
Function<String, String> pipeline =
toStr
.compose(half) // toStr(half(x))
.compose(parse); // toStr(half(parse(x)))

// То же самое через andThen:
Function<String, String> pipeline2 =
parse
.andThen(half) // half(parse(x))
.andThen(toStr); // toStr(half(parse(x)))

System.out.println(pipeline.apply("42")); // Result: 21.0
System.out.println(pipeline2.apply("42")); // Result: 21.0
}
}


compose строит цепочку справа-налево (parse → half → toStr).
andThen — слева-направо (parse → half → toStr).
Please open Telegram to view this post
VIEW IN TELEGRAM
👍104🔥1
⌨️ Что такое Heap и Stack память в Java? Какая разница между ними?

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
👍92🔥1
⌨️ Что такое default методы интрефейса?

Java 8 позволяет добавлять неабстрактные реализации методов в интерфейс, используя ключевое слово default:

interface Example {
int process(int a);
default void show() {
System.out.println("default show()");
}
}



✔️Если класс реализует интерфейс, он может, но не обязан, реализовать методы по-умолчанию, уже реализованные в интерфейсе. Класс наследует реализацию по умолчанию.

✔️Если некий класс реализует несколько интерфейсов, которые имеют одинаковый метод по умолчанию, то класс должен реализовать метод с совпадающей сигнатурой самостоятельно. Ситуация аналогична, если один интерфейс имеет метод по умолчанию, а в другом этот же метод является абстрактным - никакой реализации по умолчанию классом не наследуется.

✔️Метод по умолчанию не может переопределить метод класса java.lang.Object.

✔️Помогают реализовывать интерфейсы без страха нарушить работу других классов.

✔️Позволяют избежать создания служебных классов, так как все необходимые методы могут быть представлены в самих интерфейсах.

✔️Дают свободу классам выбрать метод, который нужно переопределить.

✔️Одной из основных причин внедрения методов по умолчанию является возможность коллекций в Java 8 использовать лямбда-выражения.

Вызывать default метод интерфейса в реализующем этот интерфейс классе можно используя ключевое слово super вместе с именем интерфейса:

interface Paper {
default void show() {
System.out.println("default show()");
}
}

class Licence implements Paper {
public void show() {
Paper.super.show();
}
}
Please open Telegram to view this post
VIEW IN TELEGRAM
🤝10👍21🔥1
⌨️ Что такое static метод интерфейса?

Статические методы интерфейса похожи на методы по умолчанию, за исключением того, что для них отсутствует возможность переопределения в классах, реализующих интерфейс.

✔️Статические методы в интерфейсе являются частью интерфейса без возможности переопределить их для объектов класса реализации;

✔️Методы класса java.lang.Object нельзя переопределить как статические;

✔️Статические методы в интерфейсе используются для обеспечения вспомогательных методов, например, проверки на null, сортировки коллекций и т.д.

Вызывать static метод интерфейса можно используя имя интерфейса:

interface Paper {
static void show() {
System.out.println("static show()");
}
}

class Licence {
public void showPaper() {
Paper.show();
}
}
Please open Telegram to view this post
VIEW IN TELEGRAM
👍161🔥1
⌨️ Switch Expressions

В Java 12 появился новый синтаксис для switch, который позволяет возвращать значение используя стрелки ->, что делает код более компактным и удобным. Теперь switch может использоваться как выражение, а не только как оператор, что упрощает его применение в логике.

Ранее switch использовался как оператор, и код мог выглядеть громоздко:

String day = "MONDAY";
int numLetters;
switch (day) {
case "MONDAY":
case "FRIDAY":
case "SUNDAY":
numLetters = 6;
break;
case "TUESDAY":
numLetters = 7;
break;
default:
numLetters = 8;
}
System.out.println(numLetters); // Вывод: 6


Со Switch Expressions можно переписать этот код более лаконично:

String day = "MONDAY";
int numLetters = switch (day) {
case "MONDAY", "FRIDAY", "SUNDAY" -> 6;
case "TUESDAY" -> 7;
default -> 8;
};
System.out.println(numLetters); // Вывод: 6


Теперь switch может вернуть значение, и нет необходимости в break.

#java #switch
Please open Telegram to view this post
VIEW IN TELEGRAM
👍223
⌨️ Использование java.util.stream.Collectors для обработки коллекций

Код:

import java.util.List;
import java.util.stream.Collectors;

public class StreamCollectorsExample {
public static void main(String[] args) {
List<Integer> numbers = List.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

// Примеры использования Collectors
// Преобразование элементов коллекции в строку
String numbersAsString = numbers.stream()
.map(Object::toString)
.collect(Collectors.joining(", "));
System.out.println("Числа в виде строки: " + numbersAsString);

// Получение среднего значения всех элементов коллекции
double average = numbers.stream()
.collect(Collectors.averagingInt(Integer::intValue));
System.out.println("Среднее значение: " + average);

// Фильтрация элементов и сборка их в новую коллекцию
List<Integer> evenNumbers = numbers.stream()
.filter(num -> num % 2 == 0)
.collect(Collectors.toList());
System.out.println("Четные числа: " + evenNumbers);

// Группировка элементов по условию
System.out.println("Числа по остатку от деления на 3: " + numbers.stream()
.collect(Collectors.groupingBy(num -> num % 3)));
}
}


⚙️Этот пример демонстрирует использование класса Collectors из пакета java.util.stream для более эффективной обработки коллекций в Java. Методы класса Collectors предоставляют различные операции для сбора (collecting) элементов из потока данных в различные структуры данных или для выполнения агрегатных операций над элементами потока.
Please open Telegram to view this post
VIEW IN TELEGRAM
6❤‍🔥1👍1
Varargs (Variable Arguments List, изменяющийся список аргументов) — это способ создания методов, которые могут принимать произвольное количество аргументов одного типа (от нуля и более). Данная возможность появилась в JDK 5.

Запись вида Object... args и есть varargs.

При этом три точки после типа указывают, что метод в качестве аргумента может принимать как массив, так и любую последовательность аргументов, записанных через запятую, которая все равно преобразуется в одномерный массив - «под капотом» компилятор на уровне байт-кода неявно заменяет переданную последовательность массивом. Уже в методе аргумент varargs используется как одномерный массив.

Альтернативой varargs является перегрузка методов или передача в метод массива значений.

Varargs был создан с целью упрощения работы программиста, удобства и краткости кода.

📌 В качестве ограничения любой метод может использовать varargs только в единственном числе и строго последним аргументом.
👍113
⌨️ var в Java 10+: удобство или ловушка?

Java 10 принес с собой var — возможность объявлять переменные без явного указания типа. Это делает код короче, но может иметь последствия.

Пример:
var list = new ArrayList<String>();


➡️ Компилятор сам выводит тип. Вроде удобно. Но давай разберем плюсы и минусы.

✔️ Плюсы использования var:

1. 👍 Меньше шаблонного кода

Не надо повторять длинные типы:
   var map = new HashMap<String, List<Integer>>();


2. 👍 Лучшая читаемость при очевидных типах

Когда справа всё ясно — var делает код чище.

3. 👍 Удобно для циклов
   for (var entry : map.entrySet()) { ... }


➡️ особенно в сочетании с лямбдами и stream API.

⚠️ Подводные камни:

1. 🟢 Потеря явности типа
   var result = someMethod();  // Что за тип?


➡️ Нужно смотреть реализацию метода или IDE-подсказки.

2. 🟢 Повышается риск ошибок

Пример: можно случайно получить Object, если возвращается не тот тип.

3. 🟢 Плох для публичного API

В методах и сигнатурах var использовать нельзя — и это правильно: API должно быть прозрачным.

📌 Лучшие практики:

✔️ Используй var, когда тип очевиден
Избегай в сложных выражениях с неочевидным выводом типа
Не используй в публичных API или при работе в больших командах без согласованных правил

🗣️ Запомни: var — это инструмент, не костыль. Он не делает Java динамической. Используй его с умом — для читаемости, а не ради моды.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍82
⌨️ Есть ли какие-либо рекомендации о том, какие поля следует использовать при подсчете hashCode()?

Общий совет: выбирать поля, которые с большой долью вероятности будут различаться. Для этого необходимо использовать уникальные, лучше всего примитивные поля, например, такие как id, uuid. При этом нужно следовать правилу, если поля задействованы при вычислении hashCode(), то они должны быть задействованы и при выполнении equals().

#java #hashCode #equals
Please open Telegram to view this post
VIEW IN TELEGRAM
👨‍💻62