Struchkov Mark
e942b17888
All checks were successful
continuous-integration/drone/push Build is passing
136 lines
9.7 KiB
Markdown
136 lines
9.7 KiB
Markdown
---
|
||
aliases:
|
||
tags:
|
||
- maturity/🌱
|
||
- type/opinion
|
||
date: 2024-09-06
|
||
zero-link:
|
||
- "[[../../meta/zero/00 Java разработка|00 Java разработка]]"
|
||
parents:
|
||
linked:
|
||
---
|
||
Разработчики Java используют подстановочный знак (`*`) в операторах `import` для добавления всех классов из определенного пакета. Но в ходе ревью большинство из вас, возможно, просили убрать этот подстановочный знак импорта и добавить полное имя класса. Разберемся почему не стоит использовать знак подстановки?
|
||
|
||
Но прежде, давайте вспомним, что полное имя класса, помимо названия, содержит также пакет, например: `java.util.List`. ==Такая запись позволяет нам иметь классы с одинаковыми именами, которые находятся в разных пакетах.==
|
||
|
||
```java
|
||
package com.example;
|
||
|
||
public class WithoutImport {
|
||
|
||
public static void main(String[] args) {
|
||
|
||
java.util.List myList = new java.util.ArrayList();
|
||
|
||
}
|
||
}
|
||
```
|
||
|
||
Однако, полная запись весьма непрактична, поэтому в Java существует оператор импорта – `import`. Операторы импорта объявляют компилятору источник имен классов, статических переменных и статических имен методов, используемых в коде. Один раз написали полное имя класса, а дальше используем только название класса.
|
||
|
||
```java
|
||
package com.example;
|
||
|
||
import java.util.ArrayList;
|
||
import java.util.List;
|
||
|
||
public class WithImport {
|
||
|
||
public static void main(String[] args) {
|
||
|
||
List myList = new ArrayList();
|
||
|
||
}
|
||
|
||
}
|
||
```
|
||
|
||
Если мы скомпилируем и запустим эти примеры, результат будет одинаковым.
|
||
|
||
Импорт с подстановочными знаками указывает компилятору искать имена классов в данном пакете. Следовательно, при использовании импорта с wildcard производительность во время компиляции может немного снизиться. Но в большинстве случаев это не окажет заметного влияния.
|
||
|
||
Во время выполнения проблемы с производительностью нет, потому что операторы импорта являются директивами компилятора, и мы не можем найти их в байт-коде. Чтобы пояснить это, мы напишем приведенный выше пример с импортом с подстановочными знаками.
|
||
|
||
```java
|
||
package com.example;
|
||
|
||
import java.util.*;
|
||
|
||
public class WithWildCard {
|
||
public static void main(String[] args) {
|
||
|
||
List myList = new ArrayList();
|
||
|
||
}
|
||
}
|
||
```
|
||
|
||
Если мы получим байт-код этого класса, то он будет выглядеть следующим образом
|
||
|
||
```bytecode
|
||
Compiled from "WithWildCard.java"
|
||
public class com.example.WithWildCard {
|
||
public com.example.WithWildCard();
|
||
Code:
|
||
0: aload_0
|
||
1: invokespecial #1 // Method java/lang/Object."<init>":()V
|
||
4: return
|
||
|
||
public static void main(java.lang.String[]);
|
||
Code:
|
||
0: new #2 // class java/util/ArrayList
|
||
3: dup
|
||
4: invokespecial #3 // Method java/util/ArrayList."<init>":()V
|
||
7: astore_1
|
||
8: return
|
||
}
|
||
```
|
||
|
||
Если сравнить его с байт-кодом прошлого примера, то они оба имеют одинаковый байт-код.
|
||
|
||
Во время выполнения Java использует байт-код, а не исходный код. ==В байт-коде нет операторов импорта.== Из этого ясно следует, что использование импорта с подстановочными знаками не влияет на производительность Java-приложения во время выполнения.
|
||
|
||
## Недостатки
|
||
Так если использование подстановочного знака не приводит к проблемам производительности, то почему бы его не использовать?
|
||
|
||
### Конфликты имен
|
||
Самая серьезная проблема это возможные конфликты именования. Представьте, что у нас есть два класса из разных библиотек `org.test.Parser` и `dev.lib.Parser`. В нашем коде мы используем импорт с wildcard:
|
||
|
||
```java
|
||
import org.test.*
|
||
import dev.lib.*
|
||
```
|
||
|
||
Компилятор никак не отреагирует на наличие классов с одинаковыми именами в двух разных пакетах, импортируемых таким образом, если только не будет предпринята попытка воспользоваться одним из этих классов.
|
||
|
||
Также проблема может возникнуть в будущем, когда вы обновите версию какую-то из библиотек. Допустим у нас была библиотека с классом `org.test.Parser`, а потом разработчик второй библиотеки тоже добавил класс `dev.lib.Parser`, таким образом мы получили конфлик именования в будущем, хотя раньше все было нормально.
|
||
### Чистый код
|
||
Импорты с подстановочными знаками помогают нам избежать длинного списка импортов. Следовательно, это влияет на читабельность кода, так как читателю может потребоваться прокрутить много страниц в каждом файле исходного кода, прежде чем он доберется до кода, который показывает логику. Несомненно, более читабельный код - это также чистый код.
|
||
|
||
Эта идея также поддерживается в книге "Чистый код" Роберта К. Мартина. Фактически, книга рекомендует использовать импорты с подстановочными знаками при использовании нескольких классов из одного источника. Другими словами, когда мы импортируем два или более классов, импортированных из пакета, лучше импортировать весь пакет.
|
||
|
||
Однако, я не считаю это какой-то проблемой, так как IntelliJ IDEA автоматически скрывает все строки импортов.
|
||
|
||
![](../../meta/files/images/Pasted%20image%2020240906164456.png)
|
||
|
||
Также читаемость ухудшается, потому что разработчик не получает четкого представления о полном пути классов, используемых в коде.
|
||
|
||
Однако, это тоже не является проблемой. Достаточно удерживая Ctrl (cmd) навести курсор на класс и вы увидите пакет, в котором этот класс размещается.
|
||
|
||
![](../../meta/files/images/Pasted%20image%2020240906164524.png)
|
||
|
||
Таким образом проблемы "чистого кода" более не актуальны.
|
||
|
||
## Настройки в Idea
|
||
Intellij Idea автоматически сворачивает импорты, когда полные импорты из какого-то пакета достигают заданного количества. Эта опция настраивается в раделе Preferences > Editor > Code Style > Java во вкладке imports.
|
||
|
||
![](../../meta/files/images/Pasted%20image%2020240906164551.png)
|
||
|
||
Чтобы отключить автоматическое сворачивание импортов достаточно указать число 999. Вот и все, теперь Idea не будет автоматически сворачивать импорты.
|
||
|
||
## Резюмирую
|
||
Использование подстановочных импортов никак не повлияет на производительность программы во время выполнения, но может немного повлиять на производительность во время компиляции.
|
||
|
||
Также при обновлении библиотек вы можете столкнуться с проблемой конфликта имен. Шанс этой проблемы не велик, но и не нулевой.
|
||
|
||
Что касается "чистого кода", то с использованием современных IDE эта проблема не является актуальной. |