Java Geek
2.5K subscribers
282 photos
1 file
31 links
Практичные советы, лайфхаки и код для Java-разработчиков. Каждый пост — реальная польза. Учим Java на примерах.

По всем вопросам @evgenycarter
Download Telegram
☕️ Java Tips: Инициализация карты в одну строку с Map.of()

Помните, как раньше приходилось создавать Map с заранее известными значениями? Куча вызовов .put(), статические блоки или (не дай бог) двойные фигурные скобки. Начиная с Java 9, у нас есть красивый и лаконичный способ - Map.of().

Разберем, как это работает и, главное, чего нельзя делать.

🆚 До и После

Как было раньше (The Old Way):


Map<String, Integer> map = new HashMap<>();
map.put("One", 1);
map.put("Two", 2);
map.put("Three", 3);
// Результат: много строк кода ради простых данных



Как сейчас (The Modern Way):


Map<String, Integer> map = Map.of(
"One", 1,
"Two", 2,
"Three", 3
);
// Результат: чисто, читаемо, одна инструкция



⚠️ Важные нюансы (Gotchas)

Использование Map.of() - это не просто синтаксический сахар для HashMap. Это создание неизменяемой (Immutable) структуры.

1. Нельзя менять данные
Попытка добавить или удалить элемент приведет к ошибке.


var colors = Map.of("Red", "#FF0000");
colors.put("Blue", "#0000FF");
// Ошибка: UnsupportedOperationException



2. Никаких null
В отличие от HashMap, здесь нельзя использовать null ни в ключах, ни в значениях.


Map.of("Key", null);
// Ошибка: NullPointerException



3. Лимит в 10 пар
Метод Map.of() перегружен для приема до 10 пар ключ-значение. Если нужно больше, используйте Map.ofEntries():


Map.ofEntries(
Map.entry("k1", "v1"),
Map.entry("k2", "v2"),
// ... хоть 100 пар
Map.entry("k100", "v100")
);



🚀 Когда использовать?

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

#Java #CodeTips #Programming #Java9

👉 @java_geek
👍41🤡1
⚔️ Java Battle: List.of() vs Arrays.asList() - в чем разница?

На код-ревью часто можно увидеть, как эти два метода используют взаимозаменяемо. На первый взгляд, результат один - список элементов. Но под капотом это два совершенно разных зверя.

Давайте разберем, почему замена одного на другой может сломать ваш код.

1. Иллюзия неизменяемости (The Mutability Trap)

Это самое важное различие.

🔴List.of() (Java 9+): Создает по-настоящему неизменяемый список. Вы не можете ни добавить, ни удалить, ни изменить элемент.
🔴Arrays.asList() (Java 1.2+): Создает список фиксированного размера, который "обернут" вокруг массива. Вы не можете менять размер (add/remove), но можете заменять элементы!


var legacyList = Arrays.asList("A", "B");
var modernList = List.of("A", "B");

legacyList.set(0, "C"); // РАБОТАЕТ! Список теперь ["C", "B"]
modernList.set(0, "C"); // Ошибка: UnsupportedOperationException

legacyList.add("D"); // Ошибка (размер фиксирован)
modernList.add("D"); // Ошибка (полная иммутабельность)



2. Отношение к null

🔴Arrays.asList: Разрешает null элементы.
🔴List.of: Враждебен к null. Если попытаетесь передать null, мгновенно получите NullPointerException. Это сделано специально, чтобы избежать ошибок в логике.

3. Связь с исходным массивом (Reference vs Copy)

Если вы создаете список из существующего массива:


String[] arr = {"One", "Two"};
var list1 = Arrays.asList(arr);
var list2 = List.of(arr);

arr[0] = "Zero"; // Меняем исходный массив

System.out.println(list1); // ["Zero", "Two"] <- Изменился вслед за массивом!
System.out.println(list2); // ["One", "Two"] <- Остался прежним



Arrays.asList работает как "окно" (view) в массив. List.of создает защитную копию данных.

🏁 Итог

🔴Используйте List.of() в 99% случаев. Это безопаснее, быстрее и потребляет меньше памяти.
🔴Используйте Arrays.asList(), только если вам нужны null-ы или вы намеренно хотите, чтобы изменения в исходном массиве отражались в списке (редкий кейс).

#Java #CodeTips #InterviewQuestions #JavaCore

👉 @java_geek
Please open Telegram to view this post
VIEW IN TELEGRAM
5👍2
🕵️ Java var: Удобный сахар или скрытая угроза?

С выходом Java 10 ключевое слово var позволило нам писать меньше кода. var - это Local Variable Type Inference. Это значит, что Java осталась строго типизированным языком, просто теперь компилятор сам догадывается о типе переменной, глядя на то, что находится справа от знака равно (=).

Но иногда его догадки могут вас удивить. Вот 3 примера, где var работает неочевидно.

1. Ловушка "Diamond Operator" (<>)

Самая частая ошибка новичков.


// Без var (Классика)
List<String> list = new ArrayList<>();
// Компилятор видит слева List<String> и понимает, что справа тоже String.

// С var (Ошибка)
var list = new ArrayList<>();



В чем проблема?
У компилятора нет информации о типе. Он видит пустые скобки <> и решает, что это ArrayList<Object>.
В итоге вы теряете типизацию:


list.add("Hello");
list.add(123); // Это сработает, хотя вы, вероятно, хотели только строки!



Как исправить:
Если используете var с конструктором, всегда указывайте тип справа:


var list = new ArrayList<String>();



2. Магия "Пересечения типов" (Intersection Types)

А вот это уже высший пилотаж, который часто встречается при использовании List.of() или Map.of().

Что будет, если сложить в список данные разных типов?


var magicList = List.of(10, 20.5, "30");
// Какой тут тип списка? List<Object>?



На самом деле компилятор выведет наиболее специфичный общий тип.
Тип переменной magicList будет выглядеть примерно так:
List<? extends Serializable & Comparable<? extends Serializable & Comparable<?>>>

Java находит общие интерфейсы для Integer, Double и String (все они реализуют Serializable и Comparable) и создает этот ужасный тип-франкенштейн. Это работает, но может свести с ума вашу IDE или методы, принимающие конкретные типы.

3. Анонимные классы на стероидах

var позволяет делать трюк, невозможный ранее: сохранять тип анонимного класса.


var user = new Object() {
String name = "Alex";
int age = 25;
};

// Это работает!
System.out.println(user.name);
System.out.println(user.age);



Если бы мы написали Object user = ..., поля name и age были бы недоступны. А var "видит" реальную структуру анонимного объекта. Это иногда полезно для локальных промежуточных вычислений, заменяя DTO или кортежи.

🧠 Золотое правило использования

var хорош тогда, когда тип очевиден из правой части:

🔴👍 var users = Map.of("id", 1); (Понятно, что это Map)

🔴👍 var stream = list.stream(); (Понятно, что Stream)

🔴👎 var result = service.process(); (Что вернулось? boolean? User? null?)

Читаемость кода важнее краткости!

#Java #CleanCode #Var #Java10

👉 @java_geek
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥41👍1