Java for Beginner
676 subscribers
546 photos
155 videos
12 files
838 links
Канал от новичков для новичков!
Изучайте Java вместе с нами!
Здесь мы обмениваемся опытом и постоянно изучаем что-то новое!

Наш YouTube канал - https://www.youtube.com/@Java_Beginner-Dev

Наш канал на RUTube - https://rutube.ru/channel/37896292/
Download Telegram
У нее деплой на носу, а тут какой-то газоанализатор 🤪 😅

https://t.me/Java_for_beginner_dev

#Mems
Please open Telegram to view this post
VIEW IN TELEGRAM
Вопросы с собеседования 👩‍💻

Какой метод используется для сравнения строк в Java?
Anonymous Quiz
10%
==
77%
equals()
8%
compareTo()
4%
equalsIgnoreCase()
Ключевые директивы JPMS

requires — для указания зависимостей

Директива requires используется для указания зависимостей модуля. Она указывает, что текущий модуль зависит от другого модуля.

Пример:
module com.example.myapp {
requires java.sql; // Зависимость от модуля java.sql
}


exports — для экспорта пакетов

Директива exports делает пакет доступным для других модулей. Только экспортированные пакеты могут быть использованы вне модуля.

Пример:
module com.example.myapp {
exports com.example.myapp.api; // Экспорт пакета com.example.myapp.api
}


opens — для открытия пакетов к рефлексии

Директива opens позволяет другим модулям использовать рефлексию для доступа к пакетам. Это полезно для фреймворков, таких как Hibernate или Spring, которые используют рефлексию для работы с классами.

Пример:
module com.example.myapp {
opens com.example.myapp.internal; // Открытие пакета com.example.myapp.internal для рефлексии
}


provides и uses — для работы с сервисами

Директивы provides и uses используются для работы с сервисами в модульной системе. provides указывает, что модуль предоставляет реализацию определенного сервиса, а uses указывает, что модуль использует сервис.

Пример:
module com.example.myapp {
provides com.example.myapp.spi.MyService with com.example.myapp.MyServiceImpl; // Предоставление реализации сервиса
uses com.example.myapp.spi.MyService; // Использование сервиса
}


Создание и использование модулей

Давайте рассмотрим пример создания и использования модулей в Java. Предположим, у нас есть два модуля: com.example.myapp и com.example.mylib.

Модуль com.example.mylib

Этот модуль предоставляет библиотеку для работы с математическими операциями.
// module-info.java для com.example.mylib
module com.example.mylib {
exports com.example.mylib.math; // Экспорт пакета com.example.mylib.math
}


// com/example/mylib/math/MathUtils.java
package com.example.mylib.math;

public class MathUtils {
public static int add(int a, int b) {
return a + b;
}
}


Модуль com.example.myapp

Этот модуль использует библиотеку com.example.mylib для выполнения математических операций.

// module-info.java для com.example.myapp
module com.example.myapp {
requires com.example.mylib; // Зависимость от модуля com.example.mylib
}


// com/example/myapp/Main.java
package com.example.myapp;

import com.example.mylib.math.MathUtils;

public class Main {
public static void main(String[] args) {
int result = MathUtils.add(5, 3);
System.out.println("Result: " + result);
}
}


Плюсы и минусы модульности

Плюсы:

Улучшенное управление зависимостями: Модульность позволяет явно указывать зависимости, что упрощает управление ими и предотвращает конфликты.
Инкапсуляция: Модули скрывают внутренние детали реализации, что делает код более безопасным и устойчивым к изменениям.
Улучшенная производительность: Загрузка только необходимых модулей может уменьшить время запуска и использование памяти.


Минусы:
Сложность: Модульность добавляет дополнительный уровень сложности в разработку и сборку приложений.
Ограниченная совместимость: Некоторые старые библиотеки и фреймворки могут не поддерживать модульность, что может вызвать проблемы при миграции.


Нюансы использования

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


#Java #Training #Medium #JPMS
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
Модульность и Maven

1. Настройка многомодульного проекта в Maven

Многомодульный проект в Maven — это проект, который состоит из нескольких подпроектов (модулей), каждый из которых может быть собран и использован независимо. Основная идея — разделение функциональности на логические модули, что упрощает управление кодом и зависимостями.

Структура многомодульного проекта:
parent-project/
├── pom.xml
├── module1/
│ └── pom.xml
├── module2/
│ └── pom.xml
└── module3/
└── pom.xml


parent-project/pom.xml — корневой POM-файл, который объединяет все модули.
module1/, module2/, module3/ — отдельные модули, каждый со своим POM-файлом.


Пример корневого pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.example</groupId>
<artifactId>parent-project</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging> <!-- Указываем, что это родительский POM -->

<modules>
<module>module1</module>
<module>module2</module>
<module>module3</module>
</modules>
</project>


Пример pom.xml для модуля (module1):
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>com.example</groupId>
<artifactId>parent-project</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>

<artifactId>module1</artifactId>
</project>


2. Управление зависимостями между модулями

Чтобы один модуль мог использовать другой, нужно добавить зависимость в pom.xml.

Например, если module2 зависит от module1, то в pom.xml module2 нужно добавить:
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>module1</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>


Плюсы:
Четкое разделение ответственности между модулями.
Упрощение управления зависимостями.
Возможность повторного использования кода.


Минусы:
Усложнение структуры проекта.
Необходимость тщательного планирования зависимостей.


#Java #Training #Medium #JPMS #Maven
3. Пример конфигурации pom.xml для модульного проекта

Рассмотрим пример, где module1 содержит общие утилиты, module2 — бизнес-логику, а module3 — веб-интерфейс.

Корневой pom.xml:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>parent-project</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>

<modules>
<module>module1</module>
<module>module2</module>
<module>module3</module>
</modules>
</project>


pom.xml для module1:
<project>
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.example</groupId>
<artifactId>parent-project</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>module1</artifactId>
</project>


pom.xml для module2:
<project>
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.example</groupId>
<artifactId>parent-project</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>module2</artifactId>

<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>module1</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</project>

pom.xml для module3:
<project>
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.example</groupId>
<artifactId>parent-project</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>module3</artifactId>

<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>module2</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</project>


Сборка и запуск модульных проектов

1. Сборка модульного проекта с помощью Maven

Maven:
mvn clean install


2. Запуск модульного приложения

Для запуска приложения, собранного с помощью Maven, используйте команду java -jar, указав путь к JAR-файлу.

#Java #Training #Medium #JPMS #Maven
Что выведет код?

import java.util.stream.IntStream;

public class Task130225 {
public static void main(String[] args) {
int sum = IntStream.range(1, 5)
.filter(i -> i % 2 == 0)
.map(i -> i * 2)
.sum();
System.out.println(sum);
}
}


#Tasks
Варианты ответа:
Anonymous Quiz
13%
6
68%
12
8%
20
11%
Exception
🧐 да там на всех эндпоинтах такая валидация что фиг пробьешься 🤓

https://t.me/Java_for_beginner_dev

#Mems
Please open Telegram to view this post
VIEW IN TELEGRAM
Вопросы с собеседования 👩‍💻

Какой интерфейс используется для сортировки элементов в коллекции?
Anonymous Quiz
27%
List
17%
Set
52%
Comparable
4%
Map
Модульность и Gradle

1. Настройка многомодульного проекта в Gradle

Gradle использует декларативный подход для настройки проектов. В отличие от Maven, где конфигурация задается в XML, Gradle использует Groovy или Kotlin DSL, что делает его более гибким и мощным.

Структура многомодульного проекта:
parent-project/
├── build.gradle
├── settings.gradle
├── module1/
│ └── build.gradle
├── module2/
│ └── build.gradle
└── module3/
└── build.gradle


settings.gradle — определяет, какие модули входят в проект.
build.gradle — корневой файл сборки, который может содержать общие настройки для всех модулей.


Пример settings.gradle:
rootProject.name = 'parent-project'
include 'module1', 'module2', 'module3'


Пример корневого build.gradle:
allprojects {
group = 'com.example'
version = '1.0-SNAPSHOT'
}

subprojects {
apply plugin: 'java'
repositories {
mavenCentral()
}
}


Пример build.gradle для модуля (module1):
dependencies {
// Зависимости модуля
}


2. Управление зависимостями между модулями

В Gradle зависимости между модулями добавляются с помощью ключевого слова project.

Например, если module2 зависит от module1, то в build.gradle module2 нужно добавить:
dependencies {
implementation project(':module1')
}


Плюсы:
Гибкость и мощь Groovy/Kotlin DSL.
Быстрая сборка благодаря инкрементальной компиляции.
Поддержка современных практик, таких как контейнеризация.


Минусы:
Более сложная настройка по сравнению с Maven.
Требует знания Groovy/Kotlin.


3. Пример конфигурации build.gradle для модульного проекта

Корневой build.gradle:
allprojects {
group = 'com.example'
version = '1.0-SNAPSHOT'
}

subprojects {
apply plugin: 'java'
repositories {
mavenCentral()
}
}


build.gradle для module1:
dependencies {
// Зависимости модуля
}


build.gradle для module2:
dependencies {
implementation project(':module1')
}


build.gradle для module3:
dependencies {
implementation project(':module2')
}


Сборка и запуск модульных проектов

1. Сборка модульного проекта с помощью Gradle

Gradle:
gradle build


2. Запуск модульного приложения
Для запуска приложения, собранного с помощью Gradle, используйте команду java -jar, указав путь к JAR-файлу.

Пример:
java -jar module3/build/libs/module3-1.0-SNAPSHOT.jar


3. Использование jlink для создания минимальных runtime-образов

jlink — это утилита, которая позволяет создавать минимальные runtime-образы Java, включающие только необходимые модули. Это полезно для уменьшения размера приложения.

Пример использования:
jlink --module-path $JAVA_HOME/jmods:mods --add-modules com.example.module1 --output myapp-runtime


Плюсы:
Уменьшение размера приложения.
Ускорение запуска приложения.
Упрощение развертывания.


Минусы:
Требует знания модульной системы Java.
Необходимость тщательного планирования зависимостей.
Пример полного цикла: от сборки до запуска


Сборка проекта:
gradle build


Создание runtime-образа:
jlink --module-path $JAVA_HOME/jmods:mods --add-modules com.example.module1 --output myapp-runtime


Запуск приложения:
./myapp-runtime/bin/java -m com.example.module1/com.example.module1.Main


#Java #Training #Medium #JPMS #Gradle #Jlink
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
Процессы и потоки (Process API). Класс ProcessBuilder

1. Введение в процессы и потоки

Процесс — это экземпляр программы, которая выполняется в операционной системе. Каждый процесс имеет собственное адресное пространство, ресурсы и состояние. Например, когда вы запускаете программу на Java, операционная система создает новый процесс для выполнения вашего кода.

Поток (thread) — это наименьшая единица выполнения внутри процесса. Потоки разделяют память и ресурсы процесса, но выполняются независимо. В Java многопоточность позволяет выполнять несколько задач одновременно в рамках одного процесса.

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


Зачем управлять внешними процессами?
Интеграция с другими программами: Например, вы можете запустить скрипт на Python или вызвать системную команду.
Автоматизация задач: Например, автоматическое создание резервных копий или выполнение системных команд.


2. Класс ProcessBuilder

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

Основные методы ProcessBuilder:
command(String... command) — задает команду и аргументы для выполнения. Например, command("ls", "-l") для Linux или command("cmd.exe", "/c", "dir") для Windows.
start() — запускает процесс и возвращает объект Process.
directory(File directory) — устанавливает рабочий каталог для процесса.
redirectOutput(ProcessBuilder.Redirect destination) — перенаправляет стандартный вывод процесса в файл или другой поток.
redirectError(ProcessBuilder.Redirect destination) — перенаправляет вывод ошибок.


Пример создания и запуска простого внешнего процесса
import java.io.IOException;

public class ProcessBuilderExample {
public static void main(String[] args) {
try {
// Создаем ProcessBuilder для команды "ls -l" (Linux) или "dir" (Windows)
ProcessBuilder processBuilder = new ProcessBuilder();
processBuilder.command("ls", "-l"); // Для Windows: "cmd.exe", "/c", "dir"

// Запускаем процесс
Process process = processBuilder.start();

// Ждем завершения процесса
int exitCode = process.waitFor();
System.out.println("Процесс завершен с кодом: " + exitCode);
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}
}


Объяснение:
Мы создаем объект ProcessBuilder и задаем команду ls -l (список файлов в Linux).
Метод start() запускает процесс.
Метод waitFor() блокирует выполнение программы до завершения процесса.


Плюсы и минусы ProcessBuilder

Плюсы:
Гибкость: можно настраивать рабочий каталог, перенаправлять вывод и ошибки.
Удобство: интуитивно понятный API для работы с процессами.


Минусы:
Зависимость от ОС: команды могут отличаться для разных операционных систем.
Ошибки выполнения: если процесс завершится с ошибкой, нужно обрабатывать исключения.


#Java #Training #Medium #Process_API #ProcessBuilder
Что выведет код?

public class Task140225 {
public static void main(String[] args) {
int x = 1;
if (x++ > 1) {
System.out.println("A");
} else if (x++ > 2) {
System.out.println("B");
} else {
System.out.println("C");
}
System.out.println(x);
}
}


#Tasks
Варианты ответа:
Anonymous Quiz
38%
А 1
3%
В 2
45%
С 3
15%
Ничегошеньки
А он просто покурить вышел... 😂

https://t.me/Java_for_beginner_dev

#Mems
Please open Telegram to view this post
VIEW IN TELEGRAM
Вопросы с собеседования 👩‍💻

Какой блок используется для обработки исключений?
Anonymous Quiz
89%
try-catch
11%
if-else
0%
for
0%
while
Запуск внешних процессов и чтение вывода. Подробности о классе ProcessBuilder

1. Подробное описание класса ProcessBuilder

Класс ProcessBuilder предоставляет мощный инструмент для создания и управления внешними процессами. Он позволяет настраивать команды, аргументы, рабочий каталог, переменные окружения и перенаправление вывода.

Основные методы ProcessBuilder

command(String... command)
Назначение: Устанавливает команду и аргументы для выполнения.
Параметры: Команда и аргументы (например, "ls", "-l").

Пример:
ProcessBuilder processBuilder = new ProcessBuilder("ls", "-l");


start()
Назначение: Запускает процесс и возвращает объект Process.
Возвращаемое значение: Объект Process, который представляет запущенный процесс.


Пример:
Process process = processBuilder.start();


directory(File directory)
Назначение: Устанавливает рабочий каталог для процесса.
Параметры: Объект File, представляющий каталог.


Пример:
processBuilder.directory(new File("/path/to/directory"));


redirectOutput(ProcessBuilder.Redirect destination)
Назначение: Перенаправляет стандартный вывод процесса.
Параметры: Объект ProcessBuilder.Redirect, который может быть файлом или потоком.


Пример:
processBuilder.redirectOutput(ProcessBuilder.Redirect.to(new File("output.txt")));


redirectError(ProcessBuilder.Redirect destination)
Назначение: Перенаправляет вывод ошибок процесса.
Параметры: Объект ProcessBuilder.Redirect.


Пример:
processBuilder.redirectError(ProcessBuilder.Redirect.to(new File("error.txt")));


redirectInput(ProcessBuilder.Redirect source)
Назначение: Перенаправляет стандартный ввод процесса.
Параметры: Объект ProcessBuilder.Redirect.


Пример:
processBuilder.redirectInput(ProcessBuilder.Redirect.from(new File("input.txt")));


environment()
Назначение: Возвращает объект Map, представляющий переменные окружения процесса.
Возвращаемое значение: Map<String, String>, где ключ — имя переменной, значение — ее значение.


Пример:
Map<String, String> env = processBuilder.environment();
env.put("VAR_NAME", "value");


inheritIO()
Назначение: Наследует стандартный ввод, вывод и ошибки от текущего процесса.

Пример:
processBuilder.inheritIO();


2. Пример использования ProcessBuilder с перенаправлением вывода

import java.io.File;
import java.io.IOException;

public class ProcessBuilderRedirectExample {
public static void main(String[] args) {
try {
ProcessBuilder processBuilder = new ProcessBuilder("ls", "-l");

// Устанавливаем рабочий каталог
processBuilder.directory(new File("/path/to/directory"));

// Перенаправляем вывод в файл
processBuilder.redirectOutput(new File("output.txt"));

// Перенаправляем ошибки в файл
processBuilder.redirectError(new File("error.txt"));

// Запускаем процесс
Process process = processBuilder.start();

// Ждем завершения процесса
int exitCode = process.waitFor();
System.out.println("Процесс завершен с кодом: " + exitCode);
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}
}


Объяснение:
Мы перенаправляем стандартный вывод и ошибки в файлы output.txt и error.txt.
Рабочий каталог процесса установлен на /path/to/directory.


#Java #Training #Medium #Process_API #ProcessBuilder
3. Пример использования переменных окружения

import java.io.IOException;
import java.util.Map;

public class ProcessBuilderEnvironmentExample {
public static void main(String[] args) {
try {
ProcessBuilder processBuilder = new ProcessBuilder("echo", "$VAR_NAME");

// Получаем переменные окружения
Map<String, String> env = processBuilder.environment();
env.put("VAR_NAME", "Hello, World!");

// Запускаем процесс
Process process = processBuilder.start();

// Чтение вывода
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
System.out.println("Вывод: " + line);
}

int exitCode = process.waitFor();
System.out.println("Процесс завершен с кодом: " + exitCode);
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}
}


Объяснение:
Мы добавляем переменную окружения VAR_NAME и используем ее в команде echo.

4. Пример наследования ввода-вывода

import java.io.IOException;

public class ProcessBuilderInheritIOExample {
public static void main(String[] args) {
try {
ProcessBuilder processBuilder = new ProcessBuilder("ls", "-l");

// Наследуем ввод, вывод и ошибки
processBuilder.inheritIO();

// Запускаем процесс
Process process = processBuilder.start();

// Ждем завершения процесса
int exitCode = process.waitFor();
System.out.println("Процесс завершен с кодом: " + exitCode);
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}
}


Объяснение:
Мы используем inheritIO(), чтобы вывод и ошибки процесса отображались в консоли текущего процесса.

5. Пример обработки ошибок и вывода

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class ProcessBuilderErrorHandling {
public static void main(String[] args) {
try {
ProcessBuilder processBuilder = new ProcessBuilder("invalid_command");

// Запускаем процесс
Process process = processBuilder.start();

// Чтение вывода ошибок
BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
String line;
while ((line = errorReader.readLine()) != null) {
System.out.println("Ошибка: " + line);
}

// Чтение стандартного вывода
BufferedReader outputReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
while ((line = outputReader.readLine()) != null) {
System.out.println("Вывод: " + line);
}

int exitCode = process.waitFor();
System.out.println("Процесс завершен с кодом: " + exitCode);
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}
}


Объяснение:

Мы читаем как стандартный вывод, так и вывод ошибок, чтобы обработать все возможные сценарии.

#Java #Training #Medium #Process_API #ProcessBuilder