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

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

Наш канал на RUTube - https://rutube.ru/channel/37896292/
Download Telegram
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
Создание объектов через Reflection

Reflection (отражение) в Java — это механизм, который позволяет анализировать и изменять поведение классов, методов, полей и других элементов программы во время выполнения. Это мощный инструмент, но он требует осторожности, так как может привести к снижению производительности и усложнению кода.

1. Использование Class.newInstance() (устаревший метод)

Метод Class.newInstance() был одним из первых способов создания объектов через Reflection. Он позволяет создать экземпляр класса, используя его пустой конструктор (конструктор без аргументов).

Как это работает:
Вы получаете объект Class с помощью Class.forName("полное.имя.класса").
Затем вызываете метод newInstance(), который создает объект.


Пример кода:
public class MyClass {
public MyClass() {
System.out.println("Объект MyClass создан!");
}
}

public class ReflectionExample {
public static void main(String[] args) {
try {
// Получаем объект Class
Class<?> clazz = Class.forName("MyClass");

// Создаем объект через newInstance()
MyClass obj = (MyClass) clazz.newInstance();
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
}
}


Плюсы:
Простота использования.
Не требует явного указания конструктора.


Минусы:
Устаревший метод (начиная с Java 9, он считается deprecated).
Работает только с классами, у которых есть публичный конструктор без аргументов.
Не поддерживает передачу параметров в конструктор.


Под капотом:
Метод newInstance() внутри вызывает getDeclaredConstructor() для получения конструктора без аргументов, а затем вызывает Constructor.newInstance().

2. Использование Constructor.newInstance()

Этот метод является более гибким и современным способом создания объектов через Reflection. Он позволяет использовать любой конструктор, включая те, которые принимают аргументы.

Как это работает:
Вы получаете объект Class.
С помощью метода getDeclaredConstructor() получаете конкретный конструктор.
Вызываете метод newInstance() у объекта Constructor, передавая необходимые аргументы.


Пример кода:
public class MyClass {
private String name;

public MyClass(String name) {
this.name = name;
System.out.println("Объект MyClass создан с именем: " + name);
}
}

public class ReflectionExample {
public static void main(String[] args) {
try {
// Получаем объект Class
Class<?> clazz = Class.forName("MyClass");

// Получаем конструктор с параметром String
Constructor<?> constructor = clazz.getDeclaredConstructor(String.class);

// Создаем объект через newInstance()
MyClass obj = (MyClass) constructor.newInstance("John");
} catch (ClassNotFoundException | NoSuchMethodException | InstantiationException |
IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
}


Плюсы:
Поддерживает конструкторы с параметрами.
Более гибкий и мощный, чем Class.newInstance().
Не deprecated.


Минусы:
Требует больше кода для получения конструктора.
Может выбросить исключения, если конструктор недоступен или параметры не совпадают.


Под капотом:

Метод newInstance() внутри вызывает нативный метод, который выделяет память для объекта и инициализирует его с помощью переданного конструктора.

#Java #Training #Medium #Reflection_API #Constructor_newInstance
Что выведет код?

public class Task110225 {
public static void main(String[] args) {
String s = "hello";
switch (s) {
case "hello":
System.out.print("A");
case "world":
System.out.print("B");
default:
System.out.print("C");
}
}
}


#Tasks
Варианты ответа:
Anonymous Quiz
51%
A
3%
AB
38%
ABC
8%
RuntimeException
Ну хоть леща не прописывает... Пока... 😁

https://t.me/Java_for_beginner_dev

#Mems
Please open Telegram to view this post
VIEW IN TELEGRAM
Вызов методов через Reflection

Теперь перейдем к вызову методов через Reflection. Это полезно, когда вы хотите вызвать метод, имя которого неизвестно до момента выполнения программы.

1. Использование Method.invoke() для вызова методов

Метод Method.invoke() позволяет вызывать методы объекта динамически. Вы можете получить объект Method с помощью getDeclaredMethod() или getMethod(), а затем вызвать его.

Как это работает:
Вы получаете объект Class.
С помощью getDeclaredMethod() или getMethod() получаете объект Method.
Вызываете метод invoke(), передавая объект и аргументы.


Пример кода:
public class MyClass {
public void sayHello(String name) {
System.out.println("Привет, " + name + "!");
}
}

public class ReflectionExample {
public static void main(String[] args) {
try {
// Получаем объект Class
Class<?> clazz = Class.forName("MyClass");

// Создаем объект
Object obj = clazz.getDeclaredConstructor().newInstance();

// Получаем метод sayHello с параметром String
Method method = clazz.getDeclaredMethod("sayHello", String.class);

// Вызываем метод
method.invoke(obj, "John");
} catch (ClassNotFoundException | NoSuchMethodException | InstantiationException |
IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
}


Плюсы:
Позволяет вызывать методы динамически.
Поддерживает методы с параметрами.


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


Под капотом:
Метод invoke() использует нативные вызовы для выполнения метода. Это требует дополнительных проверок и может привести к снижению производительности.

2. Обработка исключений при вызове методов

При работе с Reflection важно правильно обрабатывать исключения.

Основные исключения, которые могут возникнуть:
IllegalAccessException: если метод недоступен (например, он private).
InvocationTargetException: если метод выбросил исключение.
NoSuchMethodException: если метод не найден.


Пример обработки исключений:
try {
Method method = clazz.getDeclaredMethod("sayHello", String.class);
method.setAccessible(true); // Разрешаем доступ к private методам
method.invoke(obj, "John");
} catch (NoSuchMethodException e) {
System.out.println("Метод не найден: " + e.getMessage());
} catch (IllegalAccessException e) {
System.out.println("Нет доступа к методу: " + e.getMessage());
} catch (InvocationTargetException e) {
System.out.println("Метод выбросил исключение: " + e.getCause().getMessage());
}


Плюсы:
Позволяет безопасно работать с Reflection.
Помогает отлаживать проблемы.


Минусы:
Увеличивает объем кода.
Требует внимательности при обработке исключений.


#Java #Training #Medium #Reflection_API #Method_invoke
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
Введение в модульность и история Java Platform Module System — JPMS

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

Зачем нужна модульность?


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


Проблемы, которые решает модульность

До появления модульности в Java разработчики сталкивались с несколькими проблемами:
JAR Hell: Конфликты версий библиотек из-за отсутствия четкого управления зависимостями.
Отсутствие инкапсуляции: Все классы в classpath были доступны друг другу, что могло привести к непреднамеренному использованию внутренних API.
Большие размеры приложений: Приложения включали все библиотеки, даже если они не использовались, что увеличивало размер и время запуска.


История появления JPMS (Java Platform Module System)

Java Platform Module System (JPMS), также известный как Project Jigsaw, был введен в Java 9 для решения вышеупомянутых проблем.

JPMS добавил в Java поддержку модульности на уровне языка, что позволило:
Разделять JDK на модули, что уменьшило размер runtime-окружения.
Управлять зависимостями на уровне модулей.
Улучшить безопасность и производительность за счет инкапсуляции.


Основные концепции

Модуль (module) как единица инкапсуляции
Модуль в Java — это набор пакетов, который может быть скомпилирован и запущен независимо. Модуль определяет, какие пакеты он экспортирует (делает доступными для других модулей) и какие модули ему необходимы для работы.
Файл
module-info.java — его структура и назначение
Каждый модуль должен содержать файл
module-info.java, который описывает его структуру и зависимости. Этот файл находится в корне модуля и содержит директивы, определяющие, какие пакеты экспортируются, какие модули требуются и т.д.

Пример простого модуля:
module com.example.myapp {
requires java.base; // Зависимость от базового модуля Java
exports com.example.myapp.api; // Экспорт пакета com.example.myapp.api
}
В этом примере модуль com.example.myapp зависит от базового модуля java.base и экспортирует пакет com.example.myapp.api.


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

import java.util.function.Function;

public class Task120225 {
public static void main(String[] args) {
Function<String, String> func1 = String::toUpperCase;
Function<String, String> func2 = s -> s.toUpperCase();

String result1 = func1.apply("hello");
String result2 = func2.apply("hello");

System.out.println(result1 == result2);
}
}


#Tasks
У нее деплой на носу, а тут какой-то газоанализатор 🤪 😅

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