Всем привет!
Запустил тестово нового бота @Review_Trainer_Bot. Если интересно - можете пощупать руками)))
Запустил тестово нового бота @Review_Trainer_Bot. Если интересно - можете пощупать руками)))
🔥5
Что выведет код?
#Tasks
import org.yaml.snakeyaml.Yaml;
import java.util.Map;
public class Task060826 {
public static void main(String[] args) {
String yaml = "enabled: on\nvalue: 010";
Yaml yamlParser = new Yaml();
Map<String, Object> data = yamlParser.load(yaml);
System.out.println(data.get("enabled") + ", " + data.get("value"));
}
}
#Tasks
👍2
👍2
Что такое аннотация 🤓
Ответ:
Аннотация @FunctionalInterface указывает компилятору, что интерфейс должен содержать ровно один абстрактный метод.
Она не обязательна, но рекомендуется для документирования намерения. Если в интерфейсе больше одного абстрактного метода, компилятор выдаст ошибку.
Эта аннотация используется в лямбда-выражениях и ссылках на методы. Пример: Runnable, Comparator, Predicate, Consumer.
Помогает избежать случайных изменений в интерфейсах, которые сломают лямбда-совместимость.
#собеседование
@FunctionalInterface и зачем она нужна? Ответ:
Она не обязательна, но рекомендуется для документирования намерения. Если в интерфейсе больше одного абстрактного метода, компилятор выдаст ошибку.
Эта аннотация используется в лямбда-выражениях и ссылках на методы. Пример: Runnable, Comparator, Predicate, Consumer.
Помогает избежать случайных изменений в интерфейсах, которые сломают лямбда-совместимость.
#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
Java for Beginner
Всем привет! Запустил тестово нового бота @Review_Trainer_Bot. Если интересно - можете пощупать руками)))
Ребят вижу что 10 человек попробовало бота.
Не поленитесь - напишите фидбек?
Как вам, чего не хватает, что не интересно и так далее?
Благодарен за любое мнение)))
Не поленитесь - напишите фидбек?
Как вам, чего не хватает, что не интересно и так далее?
Благодарен за любое мнение)))
👍2
История технологии сегодня — 07 августа
ℹ️ Кто родился в этот день
Джи́мми До́нал Уэ́йлс (англ. Jimmy Donal Wales, также известный под псевдонимом Джи́мбо (англ. Jimbo); род. 7 августа 1966, Хантсвилл, Алабама) — американский и британский интернет-предприниматель, идеолог концепции вики, основатель Википедии, председатель Фонда Викимедиа (2003—2006). С лета 2011 года — почётный председатель Фонда Викимедиа; директор компании Fandom (ранее — Wikia).
🌐 Знаковые события
1944 — запущен первый американский программируемый компьютер «Марк I».
1970 — проведён первый компьютерный шахматный турнир.
#Biography #Birth_Date #Events #07августа
Джи́мми До́нал Уэ́йлс (англ. Jimmy Donal Wales, также известный под псевдонимом Джи́мбо (англ. Jimbo); род. 7 августа 1966, Хантсвилл, Алабама) — американский и британский интернет-предприниматель, идеолог концепции вики, основатель Википедии, председатель Фонда Викимедиа (2003—2006). С лета 2011 года — почётный председатель Фонда Викимедиа; директор компании Fandom (ранее — Wikia).
1944 — запущен первый американский программируемый компьютер «Марк I».
1970 — проведён первый компьютерный шахматный турнир.
#Biography #Birth_Date #Events #07августа
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
[Совет по Java #069]
Тема: Всегда переопределяйте
Проблема: Интерфейс
Если это правило нарушено, то
Решение: При реализации
Для этого используйте в
Для примитивных полей используйте
Объяснение:
При этом
Это нарушает принцип "Set не содержит дубликатов" — фактически дубликаты по
#Java #советы
Тема: Всегда переопределяйте
compareTo() в соответствии с equals(), если планируете использовать объекты в TreeSet/TreeMap.Проблема: Интерфейс
Comparable и его метод compareTo() определяют естественный порядок объектов. Контракт Comparable требует, чтобы compareTo() был согласован с equals(), то есть для любых двух объектов a и b должно выполняться: a.compareTo(b) == 0 тогда и только тогда, когда a.equals(b) == true. Если это правило нарушено, то
TreeSet и TreeMap, которые используют compareTo() для сравнения и упорядочивания, перестают корректно работать. Например, если два объекта имеют одинаковый compareTo (возвращают 0), но разные equals, они будут считаться дубликатами, и второй не будет добавлен в TreeSet, либо TreeMap перезапишет значение. Это противоречит ожиданиям, основанным на equals. Ошибка проявляется в виде "потери" элементов, неправильного размера множества или некорректного поиска по ключу.Решение: При реализации
Comparable для классов, которые будут использоваться в упорядоченных коллекциях, всегда проверяйте, что compareTo возвращает 0 для объектов, которые считаются равными по equals. Для этого используйте в
compareTo те же поля, что и в equals, и в одинаковом порядке. Если поля не могут быть сравнимы (например, null), обработайте это явно. Если невозможно достичь согласованности (например, у вас сложная логика сравнения), используйте отдельный Comparator с четкой документацией, но лучше пересмотреть дизайн. Для примитивных полей используйте
Integer.compare, Double.compare и т.д. Для строк — String.compareTo. Также помните, что compareTo должно быть транзитивным и антисимметричным.import java.util.Objects;
public class Person implements Comparable<Person> {
private final String name;
private final int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
//Нарушение: compareTo не согласован с equals
// @Override
// public int compareTo(Person o) {
// return this.age - o.age; // Только по возрасту
// }
// // equals по имени и возрасту
// public boolean equals(Object o) {
// if (!(o instanceof Person)) return false;
// Person p = (Person) o;
// return name.equals(p.name) && age == p.age;
// }
//Корректно: compareTo использует те же поля, что и equals
@Override
public int compareTo(Person o) {
int nameComp = this.name.compareTo(o.name);
if (nameComp != 0) return nameComp;
return Integer.compare(this.age, o.age);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Person)) return false;
Person p = (Person) o;
return age == p.age && name.equals(p.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
@Override
public String toString() {
return name + "(" + age + ")";
}
public static void main(String[] args) {
// Демонстрация нарушения
Person p1 = new Person("Alice", 30);
Person p2 = new Person("Bob", 30);
// Если compareTo только по возрасту, то p1.compareTo(p2) == 0,
// хотя equals вернет false (имена разные).
// TreeSet считает их одинаковыми
TreeSet<Person> set = new TreeSet<>();
set.add(p1);
set.add(p2);
System.out.println("Size: " + set.size()); // Должно быть 1, если compareTo=0
System.out.println("Contains Alice? " + set.contains(p1)); // true
System.out.println("Contains Bob? " + set.contains(p2)); // true? Зависит от реализации
// На самом деле, если compareTo=0, то при добавлении второго он будет считаться дубликатом
// и не будет добавлен, но contains для Bob вернет true, потому что TreeSet использует compareTo
// для поиска, а не equals. Это делает поведение непредсказуемым.
}
}
Объяснение:
TreeSet и TreeMap хранят элементы в красно-черном дереве, где сравнение выполняется через compareTo или Comparator. При добавлении элемента дерево проверяет, существует ли уже узел с тем же значением compareTo (т.е. возвращает 0). Если существует, то новый элемент считается дубликатом, и в TreeSet он не добавляется, а в TreeMap перезаписывается значение. При этом
equals вообще не используется для проверки дубликатов; она применяется только для contains и remove? На самом деле, TreeSet использует compareTo для поиска: если compareTo возвращает 0, объект считается равным, и возвращается существующий, без вызова equals. Поэтому нарушение контракта приводит к тому, что объекты, которые по логике должны быть разными, становятся неразличимыми для коллекции. Это нарушает принцип "Set не содержит дубликатов" — фактически дубликаты по
equals могут быть, но они не добавляются из-за compareTo. И наоборот, объекты с одинаковым equals, но разным compareTo, будут восприниматься как разные, что нарушает контракт Set. Поэтому всегда используйте в compareTo те же поля, что и в equals, и в том же порядке, чтобы обеспечить согласованность. Если поля могут быть null, используйте Objects.compare или явные проверки.#Java #советы
👍3
Что выведет код?
#Tasks
import java.util.TreeSet;
public class Task070826 {
static class Person070826 implements Comparable<Person070826> {
String name;
int age;
Person070826(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public int compareTo(Person070826 o) {
return Integer.compare(this.age, o.age); // только по возрасту
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Person070826)) return false;
Person070826 p = (Person070826) o;
return age == p.age && name.equals(p.name);
}
@Override
public int hashCode() {
return 31 * name.hashCode() + age;
}
}
public static void main(String[] args) {
TreeSet<Person070826> set = new TreeSet<>();
Person070826 p1 = new Person070826("Alice", 25);
Person070826 p2 = new Person070826("Bob", 25);
set.add(p1);
set.add(p2);
System.out.println(set.contains(p1));
System.out.println(set.contains(p2));
System.out.println(set.size());
}
}
#Tasks
👍2
👍3
Java for Beginner
Ребят вижу что 10 человек попробовало бота. Не поленитесь - напишите фидбек? Как вам, чего не хватает, что не интересно и так далее? Благодарен за любое мнение)))
Сколько комментов!))) Аж не успеваю читать)))
👍2
Что такое 🤓
Ответ:
@Autowired — это аннотация Spring для внедрения зависимостей (Dependency Injection).
Может применяться к конструкторам, сеттерам, полям и методам. Spring сканирует контекст и находит бин соответствующего типа.
Если найдено несколько бинов одного типа, используется @Qualifier или @Primary . Начиная с Spring 4.3, @Autowired для конструктора можно не писать, если у класса один конструктор.
Лучшая практика — внедрение через конструктор (для неизменяемых зависимостей и тестируемости).
#собеседование
@Autowired в Spring и как он работает? Ответ:
Может применяться к конструкторам, сеттерам, полям и методам. Spring сканирует контекст и находит бин соответствующего типа.
Если найдено несколько бинов одного типа, используется
Лучшая практика — внедрение через конструктор (для неизменяемых зависимостей и тестируемости).
#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
История технологии сегодня — 08 августа
ℹ️ Кто родился в этот день
Михаил Владимирович Донской (8 августа 1948 — 13 января 2009, Москва) — российский программист и предприниматель, один из создателей шахматной программы «Каисса» — первого чемпиона мира среди шахматных программ (1974 год), создатель и глава информационно-технологической компании «ДИСКо».
Ро́джер Пенро́уз (англ. Roger Penrose; род. 8 августа 1931, Колчестер, Англия) — британский физик и математик, работающий в различных областях математики, общей теории относительности и квантовой теории; автор теории твисторов. Нобелевская премия по физике (2020) «за открытие того, что образование чёрных дыр с необходимостью следует из общей теории относительности».
Поль Адриен Морис Дира́к (англ. Paul Adrien Maurice Dirac; 8 августа 1902, Бристоль — 20 октября 1984, Таллахасси) — британский физик-теоретик, один из создателей квантовой механики. Лауреат Нобелевской премии по физике 1933 года (совместно с Эрвином Шрёдингером). Работы Дирака посвящены квантовой физике, теории элементарных частиц, общей теории относительности. Он является автором основополагающих трудов по квантовой механике (общая теория преобразований), квантовой электродинамике (метод вторичного квантования и многовременной формализм) и квантовой теории поля (квантование систем со связями). Предложенное им релятивистское уравнение электрона позволило естественным образом объяснить спин и ввести представление об античастицах.
Эрнест Орландо Ло́уренс (англ. Ernest Orlando Lawrence; 8 августа 1901, Кантон, Южная Дакота, США — 27 августа 1958, Пало-Алто, Калифорния, США) — американский физик-ядерщик, создатель первого циклотрона (1930), за что он был удостоен Нобелевской премии (1939). Проводил исследования по ядерной физике и принимал участие в создании атомной бомбы.
🌐 Знаковые события
1899 — американский изобретатель из Миннесоты Альберт Маршалл запатентовал холодильник.
#Biography #Birth_Date #Events #08августа
Михаил Владимирович Донской (8 августа 1948 — 13 января 2009, Москва) — российский программист и предприниматель, один из создателей шахматной программы «Каисса» — первого чемпиона мира среди шахматных программ (1974 год), создатель и глава информационно-технологической компании «ДИСКо».
Ро́джер Пенро́уз (англ. Roger Penrose; род. 8 августа 1931, Колчестер, Англия) — британский физик и математик, работающий в различных областях математики, общей теории относительности и квантовой теории; автор теории твисторов. Нобелевская премия по физике (2020) «за открытие того, что образование чёрных дыр с необходимостью следует из общей теории относительности».
Поль Адриен Морис Дира́к (англ. Paul Adrien Maurice Dirac; 8 августа 1902, Бристоль — 20 октября 1984, Таллахасси) — британский физик-теоретик, один из создателей квантовой механики. Лауреат Нобелевской премии по физике 1933 года (совместно с Эрвином Шрёдингером). Работы Дирака посвящены квантовой физике, теории элементарных частиц, общей теории относительности. Он является автором основополагающих трудов по квантовой механике (общая теория преобразований), квантовой электродинамике (метод вторичного квантования и многовременной формализм) и квантовой теории поля (квантование систем со связями). Предложенное им релятивистское уравнение электрона позволило естественным образом объяснить спин и ввести представление об античастицах.
Эрнест Орландо Ло́уренс (англ. Ernest Orlando Lawrence; 8 августа 1901, Кантон, Южная Дакота, США — 27 августа 1958, Пало-Алто, Калифорния, США) — американский физик-ядерщик, создатель первого циклотрона (1930), за что он был удостоен Нобелевской премии (1939). Проводил исследования по ядерной физике и принимал участие в создании атомной бомбы.
1899 — американский изобретатель из Миннесоты Альберт Маршалл запатентовал холодильник.
#Biography #Birth_Date #Events #08августа
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
В бота добавил еще 3 задачи!
Каждого уровня по одной) Дерзайте и делитесь результатами в специальной группе бота. Ссылка в вкладке "от автора".
@Review_Trainer_Bot
@Oleborn
Каждого уровня по одной) Дерзайте и делитесь результатами в специальной группе бота. Ссылка в вкладке "от автора".
@Review_Trainer_Bot
@Oleborn
👍4
История технологии сегодня — 09 августа
ℹ️ Кто родился в этот день
Ма́рвин Ли Ми́нский (англ. Marvin Lee Minsky; 9 августа 1927 — 24 января 2016) — американский учёный в области искусственного интеллекта, сооснователь Лаборатории искусственного интеллекта в Массачусетском технологическом институте.
Никола́й Си́дорович Хло́пкин (9 августа 1923, село Ильинка, Владимирская губерния — 19 декабря 2012, Москва) — советский и российский учёный, доктор технических наук, специалист в области ядерной энергетики и теплофизики.
Анато́лий Ива́нович Кито́в (9 августа 1920, Самара — 14 октября 2005, Москва) — советский и российский учёный, пионер советской кибернетики и информатики, разработчик электронно-вычислительной техники в СССР.
Уи́льям А́лфред Фа́улер (англ. William Alfred Fowler; 9 августа 1911, Питтсбург, Пенсильвания, США — 14 марта 1995, Пасадина, Калифорния, США) — американский физик и астрофизик. Лауреат Нобелевской премии по физике 1983 года — «за теоретическое и экспериментальное исследование ядерных реакций, имеющих важное значение для образования химических элементов Вселенной».
Эрих Арманд Артур Йозеф Хюккель (нем. Erich Armand Arthur Joseph Hückel; 9 августа 1896, Берлин — 16 февраля 1980, Марбург) — немецкий учёный, физик и химик, один из основоположников квантовой химии, создатель теории сильных электролитов (совместно с П. Дебаем).
🌐 Знаковые события
1859 — американец Натан Эймс (Nathan Ames) запатентовал эскалатор.
1910 — американец из Чикаго Альва Джон Фишер запатентовал электрическую стиральную машину.
#Biography #Birth_Date #Events #09августа
Ма́рвин Ли Ми́нский (англ. Marvin Lee Minsky; 9 августа 1927 — 24 января 2016) — американский учёный в области искусственного интеллекта, сооснователь Лаборатории искусственного интеллекта в Массачусетском технологическом институте.
Никола́й Си́дорович Хло́пкин (9 августа 1923, село Ильинка, Владимирская губерния — 19 декабря 2012, Москва) — советский и российский учёный, доктор технических наук, специалист в области ядерной энергетики и теплофизики.
Анато́лий Ива́нович Кито́в (9 августа 1920, Самара — 14 октября 2005, Москва) — советский и российский учёный, пионер советской кибернетики и информатики, разработчик электронно-вычислительной техники в СССР.
Уи́льям А́лфред Фа́улер (англ. William Alfred Fowler; 9 августа 1911, Питтсбург, Пенсильвания, США — 14 марта 1995, Пасадина, Калифорния, США) — американский физик и астрофизик. Лауреат Нобелевской премии по физике 1983 года — «за теоретическое и экспериментальное исследование ядерных реакций, имеющих важное значение для образования химических элементов Вселенной».
Эрих Арманд Артур Йозеф Хюккель (нем. Erich Armand Arthur Joseph Hückel; 9 августа 1896, Берлин — 16 февраля 1980, Марбург) — немецкий учёный, физик и химик, один из основоположников квантовой химии, создатель теории сильных электролитов (совместно с П. Дебаем).
1859 — американец Натан Эймс (Nathan Ames) запатентовал эскалатор.
1910 — американец из Чикаго Альва Джон Фишер запатентовал электрическую стиральную машину.
#Biography #Birth_Date #Events #09августа
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Наш "Темный попутчик"
Наверное у всех происходила ситуация, когда в выходной день, специально выделив время, ты садишься изучить новый фреймворк (или что угодно), открываешь видос или статью и...
“О, уведомление в телефоне, хм...”
“Пойду налью кофе/чай/вискарика, а то не сосредоточусь”
“Так, а может завтра тоже есть время?”
И вот он уже рядом. Сел поудобнее рядом и улыбается.
Тёмный попутчик - ПРОКРАСТИНАЦИЯ🏝
Но на самом деле, все не так страшно ☺️
Давай разбираться😉
Прокрастинация — это не лень ❗️
Серьёзно.
Если бы это была просто лень — ты бы не испытывал вину за бездействие.
Ты бы не планировал, не страдал, не искал решения.
То есть ты откладываешь не потому что «плохо спланировал день», а потому что в моменте задача вызывает дискомфорт, страх, перфекционизм или даже неосознанную тревогу провала.
(И мозг такой: “А может не надо испытывать всё это прямо сейчас?.. Давай YouTube-чик?..”)
Ты можешь спросить: Это как «Синдром самозванца» из предыдущей статьи?
Да.
И они очень часто идут рука об руку. 🤝
Синдром самозванца шепчет тебе: "Ты не справишься. Ты недостаточно хорош. Это не для тебя".
А прокрастинация отвечает: "Окей! Давай немного отложим! На потом! А пока посмотрим видосы про котиков".🆘
Сочетание этих двух — вражеский тандем внутри твоей головы. Один пугает, другой уводит от страха. В итоге ты вроде и не бездельничаешь (ну, ты же чем-то занят!), но никуда не продвигаешься.
❓ И что делать-то? ❓
1. Принять, что это НОРМАЛЬНО.
Если ты осознал, что прокрастинируешь — не страшно. Я, ты, даже суперуспешные программисты — все откладывают. Просто надо научиться держать этот хаос под контролем.🧑💻
2. Обманывать мозг.
Сказать себе: “Сделаю 10 минут, и всё, можно будет отдыхать”. И, о чудо — через 30 минут ты уже глубоко в дебрях кода.
Это называется “техника маленьких шагов” — не грузить себя “большой задачей”, а начинать с малого. Упростить задачу, выбрав, что полегче и начать.
Работает почти всегда.
3. Выбери что-то одно.
Когда у тебя открыто множество обучающих вкладок: “Выучить Spring”, “Новое по Hibernate” или новая статья на канале “ Java for Beginner” — угадай, чем всё закончится? Правильно: YouTube, котики и стирка носков.
Выбери ОДНО и делай. Остальное — в «позже» (а может и в "нафиг"...☺️ ).
4. Используй "tecnica del pomodoro"
25 минут работаешь, 5 отдыхаешь. Простой трюк, но мозгу легче "терпеть" неприятное, если знает, что скоро — пауза.
Это методика из когнитивно-поведенческой психологии — дробление задач снижает тревожность.
Но главное: не жди, что мотивация заняться задачей появится.🤫
Если честно — мотивация в 90% случаев НЕ приходит.
Если прокрастинация в разгаре, то можно провалиться в окончательную лень и перестать бороться.
Начинать нужно без неё. Начинать нужно через "нехочу".
А вот когда пошел процесс, когда что-то получилось — появляется и мотивация.
Старт → действие → результат → мотивация.
Прокрастинация — не отсутствие силы воли. Это просто неправильный диалог с собой.
Мозг не против работать. Он просто не хочет страдать.
Договорись с темным попутчиком, обмани, разбей задачу, убери лишние эмоции — и действуй.
А теперь — иди и начни делать то, что откладывал, прокрастинируя и залипая в эту статью!💪
😎
#motivation
Наверное у всех происходила ситуация, когда в выходной день, специально выделив время, ты садишься изучить новый фреймворк (или что угодно), открываешь видос или статью и...
“О, уведомление в телефоне, хм...”
“Пойду налью кофе/чай/вискарика, а то не сосредоточусь”
“Так, а может завтра тоже есть время?”
И вот он уже рядом. Сел поудобнее рядом и улыбается.
Тёмный попутчик - ПРОКРАСТИНАЦИЯ
Давай разбираться
Прокрастинация — это не лень ❗️
Серьёзно.
Если бы это была просто лень — ты бы не испытывал вину за бездействие.
Ты бы не планировал, не страдал, не искал решения.
С научной точки зрения, прокрастинация — это иррациональное откладывание дел, сопровождающееся стрессом, тревожностью, и часто — сниженной самооценкой.
"Прокрастинация — это не проблема управления временем. Это проблема управления эмоциями."
— Тимоти Пихл, профессор психологии, автор исследований по теме.
То есть ты откладываешь не потому что «плохо спланировал день», а потому что в моменте задача вызывает дискомфорт, страх, перфекционизм или даже неосознанную тревогу провала.
(И мозг такой: “А может не надо испытывать всё это прямо сейчас?.. Давай YouTube-чик?..”)
Ты можешь спросить: Это как «Синдром самозванца» из предыдущей статьи?
Да.
И они очень часто идут рука об руку. 🤝
Синдром самозванца шепчет тебе: "Ты не справишься. Ты недостаточно хорош. Это не для тебя".
А прокрастинация отвечает: "Окей! Давай немного отложим! На потом! А пока посмотрим видосы про котиков".
Сочетание этих двух — вражеский тандем внутри твоей головы. Один пугает, другой уводит от страха. В итоге ты вроде и не бездельничаешь (ну, ты же чем-то занят!), но никуда не продвигаешься.
Откуда приходит прокрастинация?
Психологи выделяют несколько корней прокрастинации:⏺ Эмоциональное избегание – когда ты еще не начал задачу, но уже стрессуешь, что она сложная и ты не справишься. И вместо поиска решения, залипаешь в тик-ток.⏺ Перфекционизм – когда задача кажется слишком важной, и хочется сделать ее «идеально». Но идеал недостижим → страшно, что не получится → откладываем.⏺ Низкая саморегуляция – отсутствие способности справляться с своими внутренними импульсами. Ты просто не можешь заставить себя сесть за задачу.
1. Принять, что это НОРМАЛЬНО.
Если ты осознал, что прокрастинируешь — не страшно. Я, ты, даже суперуспешные программисты — все откладывают. Просто надо научиться держать этот хаос под контролем.
2. Обманывать мозг.
Сказать себе: “Сделаю 10 минут, и всё, можно будет отдыхать”. И, о чудо — через 30 минут ты уже глубоко в дебрях кода.
Это называется “техника маленьких шагов” — не грузить себя “большой задачей”, а начинать с малого. Упростить задачу, выбрав, что полегче и начать.
Работает почти всегда.
3. Выбери что-то одно.
Когда у тебя открыто множество обучающих вкладок: “Выучить Spring”, “Новое по Hibernate” или новая статья на канале “ Java for Beginner” — угадай, чем всё закончится? Правильно: YouTube, котики и стирка носков.
Выбери ОДНО и делай. Остальное — в «позже» (а может и в "нафиг"...
4. Используй "tecnica del pomodoro"
25 минут работаешь, 5 отдыхаешь. Простой трюк, но мозгу легче "терпеть" неприятное, если знает, что скоро — пауза.
Это методика из когнитивно-поведенческой психологии — дробление задач снижает тревожность.
Но главное: не жди, что мотивация заняться задачей появится.
Если честно — мотивация в 90% случаев НЕ приходит.
Если прокрастинация в разгаре, то можно провалиться в окончательную лень и перестать бороться.
Начинать нужно без неё. Начинать нужно через "нехочу".
А вот когда пошел процесс, когда что-то получилось — появляется и мотивация.
Старт → действие → результат → мотивация.
Прокрастинация — не отсутствие силы воли. Это просто неправильный диалог с собой.
Мозг не против работать. Он просто не хочет страдать.
Договорись с темным попутчиком, обмани, разбей задачу, убери лишние эмоции — и действуй.
А теперь — иди и начни делать то, что откладывал, прокрастинируя и залипая в эту статью!
#motivation
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥10
История технологии сегодня — 10 августа
ℹ️ Кто родился в этот день
Алекса́ндр Григо́рьевич Столе́тов (29 июля [10 августа] 1839, Владимир — 16 [28] мая 1896, Москва) — русский физик, заслуженный профессор Императорского Московского университета.
Получил кривую намагничивания железа (1872), систематически исследовал внешний фотоэффект (1888—1890), открыл первый закон фотоэффекта. Исследовал газовый разряд, критическое состояние и другие явления. Основал физическую лабораторию в Императорском Московском университете.
Во́льфганг Па́уль (нем. Wolfgang Paul, МФА: [ˈvɔlfɡaŋ ˈpaʊ̯l]о файле; 10 августа 1913, Лоренцкирх[вд], Саксония — 7 декабря 1993, Бонн, Северный Рейн-Вестфалия) — немецкий физик, профессор, лауреат Нобелевской премии по физике в 1989 году (половина премии совместно с Хансом Демельтом) «за разработку метода удержания одиночных ионов». Вторую половину премии получил Норман Рамзей «за изобретение метода раздельных колебательных полей и его использование в водородном мазере и других атомных часах».
Луис Брюс (англ. Louis E. Brus — Луис Юджин Брус; 10 августа 1943, Кливленд, США — 11 января 2026) — американский физик, специалист по физической химии. Пионер в области квантовых точек. Лауреат Нобелевской премии по химии (2023).
🌐 Знаковые события
2004 — телескоп Хаббл обнаружил галактику NGC3949, похожую на Млечный путь, и лишился одного из видеосенсоров.
#Biography #Birth_Date #Events #10августа
Алекса́ндр Григо́рьевич Столе́тов (29 июля [10 августа] 1839, Владимир — 16 [28] мая 1896, Москва) — русский физик, заслуженный профессор Императорского Московского университета.
Получил кривую намагничивания железа (1872), систематически исследовал внешний фотоэффект (1888—1890), открыл первый закон фотоэффекта. Исследовал газовый разряд, критическое состояние и другие явления. Основал физическую лабораторию в Императорском Московском университете.
Во́льфганг Па́уль (нем. Wolfgang Paul, МФА: [ˈvɔlfɡaŋ ˈpaʊ̯l]о файле; 10 августа 1913, Лоренцкирх[вд], Саксония — 7 декабря 1993, Бонн, Северный Рейн-Вестфалия) — немецкий физик, профессор, лауреат Нобелевской премии по физике в 1989 году (половина премии совместно с Хансом Демельтом) «за разработку метода удержания одиночных ионов». Вторую половину премии получил Норман Рамзей «за изобретение метода раздельных колебательных полей и его использование в водородном мазере и других атомных часах».
Луис Брюс (англ. Louis E. Brus — Луис Юджин Брус; 10 августа 1943, Кливленд, США — 11 января 2026) — американский физик, специалист по физической химии. Пионер в области квантовых точек. Лауреат Нобелевской премии по химии (2023).
2004 — телескоп Хаббл обнаружил галактику NGC3949, похожую на Млечный путь, и лишился одного из видеосенсоров.
#Biography #Birth_Date #Events #10августа
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
18. Кэширование в микросервисах: когда, зачем и какой ценой
В этом видео разбираем кэширование не как "подключить Redis", а как полноценное архитектурное решение — с ценой, альтернативами и осознанным выбором.
Что вас ждёт:
🔹 О чем надо подумать до того, как выбрать технологию — разбор всех альтернатив (реплика для чтения, денормализация, апгрейд железа) и почему кэш — не единственный и не всегда правильный ответ
🔹 Когда кэш вообще не нужен — универсальное правило: чем выше цена устаревших данных, тем осторожнее нужно кэшировать
🔹 Проверка гипотезы через HashMap — и почему это эксперимент, а не продакшен-код
🔹 Переход на Caffeine — вытеснение, TTL, контроль памяти
🔹 А что если просто @Cacheable? Честно разбираем, где стандартная Spring-абстракция полностью решает задачу, а где — нет
🔹 Устаревшие данные и согласованность: TTL vs Cache Evict vs их комбинация
🔹 Cache Hit Ratio как метрика успеха
Исходный код проекта на GitHub наверняка заслуживает Ваших звезд!🙂
Ссылка на Youtube
Ссылка на Рутьюб
Смотрите, ставьте лайки, подписывайтесь на каналы!✌️
Жду ваших реакций и оценок🙂
В этом видео разбираем кэширование не как "подключить Redis", а как полноценное архитектурное решение — с ценой, альтернативами и осознанным выбором.
Что вас ждёт:
🔹 О чем надо подумать до того, как выбрать технологию — разбор всех альтернатив (реплика для чтения, денормализация, апгрейд железа) и почему кэш — не единственный и не всегда правильный ответ
🔹 Когда кэш вообще не нужен — универсальное правило: чем выше цена устаревших данных, тем осторожнее нужно кэшировать
🔹 Проверка гипотезы через HashMap — и почему это эксперимент, а не продакшен-код
🔹 Переход на Caffeine — вытеснение, TTL, контроль памяти
🔹 А что если просто @Cacheable? Честно разбираем, где стандартная Spring-абстракция полностью решает задачу, а где — нет
🔹 Устаревшие данные и согласованность: TTL vs Cache Evict vs их комбинация
🔹 Cache Hit Ratio как метрика успеха
Исходный код проекта на GitHub наверняка заслуживает Ваших звезд!
Ссылка на Youtube
Ссылка на Рутьюб
Смотрите, ставьте лайки, подписывайтесь на каналы!
Жду ваших реакций и оценок
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11🔥1🤯1😱1
Раздел 11. Работа с файлами, I/O и сетью (NIO.2)
Глава 3. Сериализация и форматы обмена
Protocol Buffers (Protobuf) — бинарный формат сериализации от Google
Protocol Buffers (Protobuf) — это механизм нейтрального к платформе и языку расширяемого сериализации структурированных данных, разработанный Google. Первый публичный релиз состоялся в 2008 году, хотя внутри Google формат использовался с 2001 года. На момент 2026 года актуальная версия спецификации — proto3 (Protocol Buffers версии 3), выпущенная в 2016 году, с последующими обновлениями языка и runtime.
Protobuf решает фундаментальную проблему текстовых форматов вроде JSON и XML: они удобны для человека, но неэффективны для машины. Каждый символ в JSON занимает байт (или несколько в UTF-8), каждая фигурная скобка, запятая и кавычка — это накладные расходы. В высоконагруженных распределённых системах, где сервисы обмениваются миллионами сообщений в секунду, эти накладные расходы становятся bottleneck на уровне CPU, памяти и сетевой пропускной способности. Protobuf заменяет текстовое представление на компактное бинарное, при этом сохраняя строгую типизацию и возможность эволюции схемы.
Архитектура: схема как контракт
В основе Protobuf лежит идея schema-first (сначала схема). Разработчик описывает структуру данных в файле с расширением
Пример .proto файла
Ключевые элементы синтаксиса:
#Java #для_новичков #beginner #IO #NIO #Serialize #Protobuf
Глава 3. Сериализация и форматы обмена
Protocol Buffers (Protobuf) — бинарный формат сериализации от Google
Protocol Buffers (Protobuf) — это механизм нейтрального к платформе и языку расширяемого сериализации структурированных данных, разработанный Google. Первый публичный релиз состоялся в 2008 году, хотя внутри Google формат использовался с 2001 года. На момент 2026 года актуальная версия спецификации — proto3 (Protocol Buffers версии 3), выпущенная в 2016 году, с последующими обновлениями языка и runtime.
Protobuf решает фундаментальную проблему текстовых форматов вроде JSON и XML: они удобны для человека, но неэффективны для машины. Каждый символ в JSON занимает байт (или несколько в UTF-8), каждая фигурная скобка, запятая и кавычка — это накладные расходы. В высоконагруженных распределённых системах, где сервисы обмениваются миллионами сообщений в секунду, эти накладные расходы становятся bottleneck на уровне CPU, памяти и сетевой пропускной способности. Protobuf заменяет текстовое представление на компактное бинарное, при этом сохраняя строгую типизацию и возможность эволюции схемы.
Bottleneck — это узкое место в системе, которое ограничивает общую производительность. В контексте сериализации bottleneck часто проявляется в виде высокой нагрузки на CPU при парсинге текстовых форматов, избыточном потреблении памяти кучи и низкой пропускной способности сети из-за раздутого размера сообщений.
Архитектура: схема как контракт
В основе Protobuf лежит идея schema-first (сначала схема). Разработчик описывает структуру данных в файле с расширением
.proto на специальном языке описания интерфейсов (IDL — Interface Definition Language), а затем компилирует этот файл в код на целевом языке программирования. Этот подход кардинально отличается от JSON, где схема существует только в головах разработчиков или в отдельном документе (OpenAPI), но не является частью процесса сериализации.IDL (Interface Definition Language) — это язык формальной спецификации интерфейсов программных компонентов. В контексте Protobuf IDL описывает структуру сообщений, их поля, типы и правила версионирования.
Пример .proto файла
syntax = "proto3";
package library;
// Опция java_package переопределяет пакет для сгенерированных Java-классов
option java_package = "com.example.library.proto";
option java_multiple_files = true;
// Сообщение Book описывает структуру книги
message Book {
// Поле с номером тега 1. Тег — это уникальный идентификатор поля в пределах сообщения
string title = 1;
// Поле с номером тега 2
string author = 2;
// int32 — 32-битное целое со знаком
int32 year = 3;
// double — 64-битное число с плавающей точкой
double price = 4;
// bool — булево значение
bool available = 5;
// repeated — повторяющееся поле, аналог списка или массива
repeated string tags = 6;
// Вложенное сообщение
message Publisher {
string name = 1;
string country = 2;
}
Publisher publisher = 7;
}
Ключевые элементы синтаксиса:
syntax = "proto3" — указание версии языка. proto3 — современная версия, упрощённая по сравнению с proto2. В proto3 все поля технически optional, нет required-полей, нет значений по умолчанию для полей сообщений.message — единица структуры данных, аналог класса в ООП. Каждое сообщение компилируется в класс на целевом языке.field_type field_name = field_number — объявление поля. Тип, имя и номер тега. Номер тега — целое число от 1 до 536870911 (2^29 - 1), но рекомендуется использовать 1–15 для частых полей, так как они кодируются одним байтом.repeated — модификатор, указывающий, что поле является коллекцией. В proto3 repeated-поля кодируются как packed по умолчанию для скалярных типов, что экономит пространство.option — метаданные компиляции. java_package задаёт пакет Java-классов, java_multiple_files = true генерирует отдельный файл для каждого сообщения вместо одного большого файла с вложенными классами.Тег (field number) — это уникальный числовой идентификатор поля в пределах сообщения Protobuf. Тег, а не имя поля, записывается в бинарное представление. Это позволяет изменять имена полей в схеме, не ломая бинарную совместимость, так как парсер опирается на номера тегов.
#Java #для_новичков #beginner #IO #NIO #Serialize #Protobuf
👍4
Бинарное кодирование: wire format
Protobuf использует собственный бинарный формат передачи — wire format. Он основан на принципе TLV (Tag-Length-Value) для сложных типов и TV (Tag-Value) для скаляров переменной длины. Каждое поле сообщения кодируется независимо, и порядок полей в бинарном потоке не обязан совпадать с порядком объявления в .proto файле.
Структура поля в wire format
Каждое поле кодируется как:
Тег состоит из двух компонентов, упакованных в varint:
field number (номер поля, 3 бита wire type + оставшиеся биты на номер)
wire type (тип кодирования значения, 3 бита)
Wire types определены спецификацией:
0 — Varint (целые числа, булевы, enum)
1 — 64-bit (fixed64, sfixed64, double)
2 — Length-delimited (string, bytes, вложенные сообщения, packed repeated)
3 — Start group (устаревший, не используется в proto3)
4 — End group (устаревший)
5 — 32-bit (fixed32, sfixed32, float)
Varint: переменная длина целых чисел
Varint позволяет кодировать малые числа компактно: числа от 0 до 127 занимают 1 байт. Это главная причина, по которой рекомендуется использовать теги 1–15 для частых полей — теговый байт тоже кодируется как varint, и малые номера полей занимают 1 байт.
ZigZag: кодирование отрицательных чисел
Стандартный varint плохо подходит для отрицательных чисел в знаковых типах (sint32, sint64), так как в дополнительном коде (two's complement) отрицательные числа имеют установленные старшие биты и кодируются максимальной длиной (5 байт для sint32, 10 байт для sint64). Для решения этой проблемы Protobuf использует ZigZag encoding.
Таким образом,
Length-delimited: строки и вложенные сообщения
Для типов с переменной длиной (string, bytes, вложенные message) используется wire type 2.
Формат:
Где
Packed repeated fields
В proto3 скалярные числовые repeated-поля кодируются как packed по умолчанию. Это означает, что вместо отдельного тега для каждого элемента массива весь массив кодируется как один length-delimited блок:
Это значительно экономит пространство по сравнению с unpacked-форматом, где каждый элемент имел бы свой тег.
Компиляция: от .proto к Java
Компилятор
Для Java процесс выглядит так:
Флаг
Ключевые особенности сгенерированного кода:
Immutability (неизменяемость): после создания через
Builder pattern: создание объекта идёт через вложенный класс
LazyStringList: оптимизированная реализация
CodedOutputStream / CodedInputStream: низкоуровневые потоки для записи и чтения wire format. Работают напрямую с
#Java #для_новичков #beginner #IO #NIO #Serialize #Protobuf
Protobuf использует собственный бинарный формат передачи — wire format. Он основан на принципе TLV (Tag-Length-Value) для сложных типов и TV (Tag-Value) для скаляров переменной длины. Каждое поле сообщения кодируется независимо, и порядок полей в бинарном потоке не обязан совпадать с порядком объявления в .proto файле.
Wire format — это конкретное бинарное представление сообщения Protobuf при передаче по сети или записи на диск. Оно определяет, как типы данных, номера полей и значения упаковываются в последовательность байтов.
Структура поля в wire format
Каждое поле кодируется как:
[tag][value]
Тег состоит из двух компонентов, упакованных в varint:
field number (номер поля, 3 бита wire type + оставшиеся биты на номер)
wire type (тип кодирования значения, 3 бита)
Wire types определены спецификацией:
0 — Varint (целые числа, булевы, enum)
1 — 64-bit (fixed64, sfixed64, double)
2 — Length-delimited (string, bytes, вложенные сообщения, packed repeated)
3 — Start group (устаревший, не используется в proto3)
4 — End group (устаревший)
5 — 32-bit (fixed32, sfixed32, float)
Varint: переменная длина целых чисел
Varint (variable-length integer) — это способ кодирования целых чисел в виде последовательности байтов переменной длины. Каждый байт varint содержит 7 бит данных и 1 бит-флаг продолжения (most significant bit). Если флаг установлен, следует ещё один байт.
Значение 1:
Бинарное: 00000001
Varint: 00000001 (1 байт)
Значение 150:
Бинарное: 10010110
Varint: 10010110 00000001 (2 байта)
Разбор: младшие 7 бит первого байта = 1001010 (22), старший бит = 1 (продолжение)
второй байт = 0000001 (1), итого: 1 * 128 + 22 = 150
Varint позволяет кодировать малые числа компактно: числа от 0 до 127 занимают 1 байт. Это главная причина, по которой рекомендуется использовать теги 1–15 для частых полей — теговый байт тоже кодируется как varint, и малые номера полей занимают 1 байт.
ZigZag: кодирование отрицательных чисел
Стандартный varint плохо подходит для отрицательных чисел в знаковых типах (sint32, sint64), так как в дополнительном коде (two's complement) отрицательные числа имеют установленные старшие биты и кодируются максимальной длиной (5 байт для sint32, 10 байт для sint64). Для решения этой проблемы Protobuf использует ZigZag encoding.
ZigZag encoding — это схема отображения целых чисел со знаком на целые без знака, при которой малые по модулю числа (положительные и отрицательные) отображаются на малые положительные числа. Формула: (n << 1) ^ (n >> 31) для 32-битных чисел.
Исходное значение -> Закодированное
0 -> 0
-1 -> 1
1 -> 2
-2 -> 3
2 -> 4
Таким образом,
-1 кодируется как 1 и занимает 1 байт вместо 5. Для полей, которые могут содержать отрицательные значения, в .proto следует использовать sint32 или sint64 вместо int32/int64.Length-delimited: строки и вложенные сообщения
Для типов с переменной длиной (string, bytes, вложенные message) используется wire type 2.
Формат:
[tag][length][data]
Где
length — varint, указывающий количество байт в data. Это позволяет парсеру пропустить неизвестные поля (unknown fields) или поля с неправильным типом, не читая их содержимое байт за байтом.Packed repeated fields
В proto3 скалярные числовые repeated-поля кодируются как packed по умолчанию. Это означает, что вместо отдельного тега для каждого элемента массива весь массив кодируется как один length-delimited блок:
[tag][total_length][value1][value2][value3]...
Это значительно экономит пространство по сравнению с unpacked-форматом, где каждый элемент имел бы свой тег.
Компиляция: от .proto к Java
Компилятор
protoc (Protocol Buffers Compiler) трансформирует .proto файлы в исходный код на целевом языке.Для Java процесс выглядит так:
# Установка компилятора (например, через Maven plugin или скачивание бинарника)
protoc --java_out=./src/main/java library.proto
Флаг
--java_out указывает директорию для сгенерированных Java-файлов. Результат компиляции сообщения Book из примера выше:// Сгенерированный класс Book.java
package com.example.library.proto;
public final class Book extends GeneratedMessageV3 implements BookOrBuilder {
// Приватные поля — immutable объект
private volatile Object title_;
private volatile Object author_;
private int year_;
private double price_;
private boolean available_;
// Repeated поле — хранится как ProtocolStringList (оптимизированная реализация List<String>)
private LazyStringList tags_;
private Publisher publisher_;
// Приватный конструктор — объекты создаются через Builder
private Book() {
title_ = "";
author_ = "";
tags_ = LazyStringArrayList.EMPTY;
}
// Геттеры
public String getTitle() { ... }
public String getAuthor() { ... }
public int getYear() { ... }
public List<String> getTagsList() { ... }
public Publisher getPublisher() { ... }
// Сериализация в OutputStream
public void writeTo(CodedOutputStream output) throws IOException {
// Кодирование каждого поля в wire format
if (!getTitleBytes().isEmpty()) {
GeneratedMessageV3.writeString(output, 1, title_);
}
if (!getAuthorBytes().isEmpty()) {
GeneratedMessageV3.writeString(output, 2, author_);
}
if (year_ != 0) {
output.writeInt32(3, year_);
}
// ... и так далее для каждого поля
}
// Десериализация из InputStream
public static Book parseFrom(InputStream input) throws IOException {
return parseFrom(input, DEFAULT_INSTANCE);
}
// Вложенный класс Builder — реализация паттерна Builder
public static final class Builder extends GeneratedMessageV3.Builder<Builder> {
// Мутабельная копия полей для построения объекта
public Builder setTitle(String value) { ... }
public Builder setAuthor(String value) { ... }
public Builder setYear(int value) { ... }
public Builder addTags(String value) { ... }
public Book build() { ... } // создаёт immutable Book
}
// Singleton-экземпляр DEFAULT_INSTANCE для пустого сообщения
private static final Book DEFAULT_INSTANCE;
static {
DEFAULT_INSTANCE = new Book();
}
}
Ключевые особенности сгенерированного кода:
Immutability (неизменяемость): после создания через
build() объект Book не может быть изменен. Все поля private final (или private volatile для строк), сеттеров нет. Изменение требует создания нового объекта через toBuilder().Builder pattern: создание объекта идёт через вложенный класс
Builder, что позволяет конструировать объект пошагово и гарантирует валидность на момент build().LazyStringList: оптимизированная реализация
List<String> для repeated string-полей. Хранит строки как ByteString или byte[] до первого обращения как String, что экономит перекодирование UTF-8.CodedOutputStream / CodedInputStream: низкоуровневые потоки для записи и чтения wire format. Работают напрямую с
byte[], минуя промежуточные текстовые представления.Immutability (неизменяемость) — это свойство объекта, при котором его состояние не может быть изменено после создания. Неизменяемые объекты потокобезопасны по определению, так как их нельзя изменить из любого потока. В Protobuf immutability гарантирует, что сериализованное сообщение не изменится во время передачи.
Builder pattern (паттерн строитель) — это порождающий паттерн проектирования, который позволяет создавать сложные объекты пошагово. В Protobuf Builder изолирует мутабельное состояние на этапе конструирования, а финальный объект остаётся immutable.
#Java #для_новичков #beginner #IO #NIO #Serialize #Protobuf
👍4
Практический пример: сериализация и десериализация
Метод
Версионирование и эволюция схемы
Одно из ключевых преимуществ Protobuf — встроенная поддержка backward и forward compatibility через правила изменения схемы.
Правила безопасного изменения схемы
Добавление полей: можно добавлять новые поля с новыми тегами. Старый код проигнорирует неизвестные теги (wire parser пропускает их по length-delimiter или varint-размеру). Новый код получит default value для отсутствующих в старом сообщении полей.
Удаление полей: поле можно удалить, но его тег нельзя повторно использовать (чтобы избежать коллизий со старыми сообщениями, где это поле ещё может присутствовать). Рекомендуется помечать удалённые поля как
Изменение типа: нельзя менять wire type поля (например, int32 на string), так как это сломает бинарный парсинг. Но можно менять тип в пределах совместимых wire type: int32 на int64 (wire type 0), string на bytes (wire type 2).
Изменение имени: имя поля можно менять свободно, так как в wire format хранится только тег, а не имя.
Default values: в proto3 поля всегда имеют zero-value по умолчанию (0 для чисел, пустая строка, false, первое значение enum). Это означает, что невозможно отличить "поле не было установлено" от "поле было установлено в значение по умолчанию". Для явного контроля наличия поля в proto3 используется обёртка
Преимущества Protobuf
Компактность
Бинарное представление Protobuf значительно меньше JSON. Для сообщения
JSON с отступами: ~280 байт.
JSON minified: ~200 байт.
Protobuf binary: ~55-65 байт (в зависимости от длины строк).
Экономия достигается за счёт:
Отсутствия имён полей в бинарном потоке (только числовые теги).
Varint-кодирования малых целых чисел.
Packed repeated-полей.
Отсутствия запятых, скобок, кавычек.
Для высоконагруженных систем экономия 70-80% трафика критична. В микросервисной архитектуре, где сервисы обмениваются через сеть, снижение размера сообщений прямо пропорционально снижению задержек (latency) и стоимости сетевой инфраструктуры.
Скорость
Protobuf парсится быстрее JSON по нескольким причинам:
Отсутствие текстового разбора: не нужно искать кавычки, запятые, скобки, обрабатывать escape-последовательности. Парсер читает байты последовательно, используя заранее известную структуру.
Нет рефлексии при десериализации: сгенерированный код содержит жёстко заданные инструкции вида "тег 1 — строка, записать в поле title". В Jackson для JSON требуется рефлексия или runtime-генерация bytecode.
Zero-copy для строк:
Предсказуемость аллокаций: размер сообщения известен до сериализации (вызов
В бенчмарках (JMH — Java Microbenchmark Harness) сериализация/десериализация Protobuf в Java обычно в 3–10 раз быстрее Jackson JSON для типичных сообщений, и в 20+ раз быстрее для сложных вложенных структур.
Строгая типизация
Кроссплатформенность и межъязыковая совместимость
Один .proto файл компилируется в C++, Java, Python, Go, C#, JavaScript, Ruby, Objective-C, PHP, Dart, Kotlin и другие языки. Это означает, что бэкенд на Java, мобильное приложение на Kotlin и фронтенд на JavaScript могут использовать одну и ту же схему данных, гарантируя совместимость на уровне wire format.
#Java #для_новичков #beginner #IO #NIO #Serialize #Protobuf
import com.example.library.proto.Book;
import com.example.library.proto.Book.Publisher;
import com.google.protobuf.ByteString;
import java.io.FileOutputStream;
import java.io.FileInputStream;
public class ProtobufExample {
public void createAndSerialize() throws Exception {
// Создание объекта через Builder
Book book = Book.newBuilder()
.setTitle("Clean Code")
.setAuthor("Robert C. Martin")
.setYear(2008)
.setPrice(42.50)
.setAvailable(true)
.addTags("programming")
.addTags("software engineering")
.setPublisher(
Publisher.newBuilder()
.setName("Prentice Hall")
.setCountry("USA")
.build()
)
.build();
// Сериализация в байтовый массив
byte[] bytes = book.toByteArray();
System.out.println("Serialized size: " + bytes.length + " bytes");
// Для сравнения: JSON-представление этого же объекта заняло бы ~250-300 байт
// Запись в файл
try (FileOutputStream fos = new FileOutputStream("book.pb")) {
book.writeTo(fos);
}
// Десериализация из файла
try (FileInputStream fis = new FileInputStream("book.pb")) {
Book restored = Book.parseFrom(fis);
System.out.println("Restored: " + restored.getTitle() + " by " + restored.getAuthor());
}
// Десериализация из байтового массива
Book fromBytes = Book.parseFrom(bytes);
}
}
Метод
toByteArray() сериализует сообщение в компактный byte[]. Метод parseFrom() выполняет обратную операцию. Обратите внимание: parseFrom() не выбрасывает checked-исключений при невалидном формате — вместо этого выбрасывается InvalidProtocolBufferException (unchecked, наследник IOException в старых версиях, но в proto3 runtime это RuntimeException).Версионирование и эволюция схемы
Одно из ключевых преимуществ Protobuf — встроенная поддержка backward и forward compatibility через правила изменения схемы.
Backward compatibility (обратная совместимость) — это свойство системы, при котором новая версия может корректно обрабатывать данные, созданные старой версией. Forward compatibility (прямая совместимость) — это свойство, при котором старая версия может корректно обрабатывать данные, созданные новой версией.
Правила безопасного изменения схемы
Добавление полей: можно добавлять новые поля с новыми тегами. Старый код проигнорирует неизвестные теги (wire parser пропускает их по length-delimiter или varint-размеру). Новый код получит default value для отсутствующих в старом сообщении полей.
Удаление полей: поле можно удалить, но его тег нельзя повторно использовать (чтобы избежать коллизий со старыми сообщениями, где это поле ещё может присутствовать). Рекомендуется помечать удалённые поля как
reserved.Изменение типа: нельзя менять wire type поля (например, int32 на string), так как это сломает бинарный парсинг. Но можно менять тип в пределах совместимых wire type: int32 на int64 (wire type 0), string на bytes (wire type 2).
Изменение имени: имя поля можно менять свободно, так как в wire format хранится только тег, а не имя.
Default values: в proto3 поля всегда имеют zero-value по умолчанию (0 для чисел, пустая строка, false, первое значение enum). Это означает, что невозможно отличить "поле не было установлено" от "поле было установлено в значение по умолчанию". Для явного контроля наличия поля в proto3 используется обёртка
google.protobuf.BoolValue, Int32Value и т.д. (well-known types).message BookV2 {
string title = 1;
string author = 2;
int32 year = 3;
// Новое поле — старый код проигнорирует тег 8
string isbn = 8;
// Зарезервированные теги и имена — нельзя использовать повторно
reserved 4, 5, 6;
reserved "price", "available";
}Преимущества Protobuf
Компактность
Бинарное представление Protobuf значительно меньше JSON. Для сообщения
Book из примера:JSON с отступами: ~280 байт.
JSON minified: ~200 байт.
Protobuf binary: ~55-65 байт (в зависимости от длины строк).
Экономия достигается за счёт:
Отсутствия имён полей в бинарном потоке (только числовые теги).
Varint-кодирования малых целых чисел.
Packed repeated-полей.
Отсутствия запятых, скобок, кавычек.
Для высоконагруженных систем экономия 70-80% трафика критична. В микросервисной архитектуре, где сервисы обмениваются через сеть, снижение размера сообщений прямо пропорционально снижению задержек (latency) и стоимости сетевой инфраструктуры.
Latency — это задержка между отправкой запроса и получением ответа. В распределённых системах latency складывается из времени сериализации, передачи по сети, десериализации и обработки. Компактные форматы снижают время передачи и десериализации.
Скорость
Protobuf парсится быстрее JSON по нескольким причинам:
Отсутствие текстового разбора: не нужно искать кавычки, запятые, скобки, обрабатывать escape-последовательности. Парсер читает байты последовательно, используя заранее известную структуру.
Нет рефлексии при десериализации: сгенерированный код содержит жёстко заданные инструкции вида "тег 1 — строка, записать в поле title". В Jackson для JSON требуется рефлексия или runtime-генерация bytecode.
Zero-copy для строк:
ByteString и LazyStringList позволяют избежать копирования строк при передаче между слоями приложения.Предсказуемость аллокаций: размер сообщения известен до сериализации (вызов
getSerializedSize()), что позволяет выделить точный byte[] без переаллокаций.В бенчмарках (JMH — Java Microbenchmark Harness) сериализация/десериализация Protobuf в Java обычно в 3–10 раз быстрее Jackson JSON для типичных сообщений, и в 20+ раз быстрее для сложных вложенных структур.
JMH (Java Microbenchmark Harness) — это фреймворк от OpenJDK для написания корректных микробенчмарков Java-кода. Он решает проблемы JIT-оптимизаций, warmup-фазы и статистической значимости результатов.
Строгая типизация
.proto файл является контрактом. Компилятор protoc гарантирует, что сгенерированный код соответствует схеме. Невозможно случайно записать строку в числовое поле — это будет ошибкой компиляции, а не runtime-ошибкой парсинга. Это снижает количество ошибок интеграции между сервисами.Кроссплатформенность и межъязыковая совместимость
Один .proto файл компилируется в C++, Java, Python, Go, C#, JavaScript, Ruby, Objective-C, PHP, Dart, Kotlin и другие языки. Это означает, что бэкенд на Java, мобильное приложение на Kotlin и фронтенд на JavaScript могут использовать одну и ту же схему данных, гарантируя совместимость на уровне wire format.
#Java #для_новичков #beginner #IO #NIO #Serialize #Protobuf
👍4