Почему некоторые пакеты в java начинаются с com. ? что такое com?
Это просто определение пространства имен, чтобы избежать столкновения имен классов. com.domain.package.Class -это установленное соглашение Java, в котором пространство имен квалифицируется с доменом компании в обратном порядке (то есть, имя пространства имён com.oracle.jdbc в перевернутом виде превратится в более привычное jdbc.oracle.com — что уже очень похоже на «имя сайта, куда надо ходить за jdbc драйвером для оракла»).
Отслеживать
11k 1 1 золотой знак 23 23 серебряных знака 44 44 бронзовых знака
Пакеты классов, package
Пакет package позволяет логически объединить классы в наборы. Основные классы java входят в пакет java.lang. Различные вспомогательные классы располагаются в пакете в java.util. Классы для ввода и вывода входят в пакет java.io, а классы для работы в сети – в java.net. Некоторые их этих пакетов содержат подпакеты. Так, например, java.lang содержит два специализированных пакета java.lang.reflect и java.lang.ref, а java.util содержит подпакет java.util.zip, который включает классы для работы с ZIPархивами.
Каждый класс имеет как простое имя, данное ему в определении, так и полное имя, включающее имя пакета, в который он входит. Например, класс String является частью пакета java.lang, а его полное имя – java.lang.String.
Структура пакетов в точности отображает структуру файловой системы. Все файлы с исходными кодами (java-класс) и байт-кодами (расширением class), образующие один пакет, хранятся в одном каталоге файловой системы. Подпакеты образуют подкаталоги этого каталога. Каждый пакет создает единое пространство имен namespace. Это означает, что все имена классов и интерфейсов в пакете должны быть уникальны. Имена в разных пакетах могут совпадать, но это будут разные программные модули. Организация классов в виде пакетов позволяет избежать конфликта имен между классами. В пакете дублирование имен классов не допускается. Принадлежность класса к пакету позволяет гарантировать однозначность имен.
Чтобы указать, что класс принадлежит определенному пакету, следует использовать директиву package, после которой указывается наименование (путь) пакета :
package company.common; public class HelloWorld < public static void main(String[] args)< System.out.println ("Привет, мир!"); >>
В данном примере класс HelloWorld располагается в пакете company.common. Физически это директория «$/company/common». При создании класса в среде разработки IDE (например, Eclipse) следует указать наименование пакета, тогда IDE самостоятельно при необходимости создаст каталог на жестком диске и разместит новый класс в этом каталоге.
Можно package в классе не определять. В этом случае класс будет находиться в пакете по умолчанию, который не имеет имени «$», т.е. класс будет располагаться в корневой директории исходных кодов проекта.
Наименование пакета может быть любым, но необходимо соблюдать его уникальность в проекте. Соглашение «Code Conventions» рекомендует записывать имена пакетов строчными буквами. Тогда они не будут совпадать с именами классов, которые, по соглашению, начинаются с прописной буквы.
Стандартная библиотека Java API включает сотни классов. Каждый программист в ходе работы создает десятки своих классов. Множество классов быстро увеличивается. Java позволяет отдельные классы, решающие определенную задачу (или несколько задач), объединять в библиотеки классов в виде архивов jar. Но эти библиотеки классов, кроме стандартных, не являются частью языка java.
Импорт пакетов и классов, import
Для использования класса в приложении, его следует подключить. Так расположенный в пакете java.util класс Scanner можно подключить следующим способом :
java.util.Scanner in = new java.util.Scanner(System.in);
В этом примере при определении/создании нового объекта был указыван пакет (полный путь к файлу). Однако данный подход не всегда удобен, и в качестве альтернативы можно импортировать пакеты и классы в приложение с помощью директивы import, которая указывается после директивы package :
package company.common; import java.util.Scanner; public class HelloWorld < public static void main(String[] args)< Scanner in = new Scanner(System.in); >>
Директива import указывается в самом начале кода, после чего идет имя подключаемого класса (класс Scanner в примере).
В примере был подключен только один класс. Однако пакет java.util содержит большое количество разных классов. И чтобы не подключать по отдельности каждый класс, можно сразу подключить весь пакет :
import java.util.*; // импорт всех классов из пакета java.util
Теперь можно использовать любой класс из пакета java.util.
Возможна ситуация, когда используется два класса с одинаковым наименованием, но из разных пакетов. Это относится, например, к классам Date, которые имеются в пакете java.util и в пакете java.sql, или классам List пакетов java.util и java.awt. И если необходимо одновременно использовать оба эти класса, то необходимо указывать полный путь к классам в пакете :
java.util.Date udate = new java.util.Date(); java.sql.Date sdate = new java.sql.Date();
Следует сказать, что основные классы из пакета java.lang (например, String) подключаются автоматически и не требуют «импортирования».
Статический импорт классов, import static
В java можно использовать статический импорт. Для этого вместе с директивой import используется модификатор static :
package company.common; import static java.lang.Math.*; import static java.lang.System.*; public class HelloWorld < public static void main(String[] args) < double result = sqrt(20); out.println(result); >>
В примере определяется статический импорт классов System и Math, которые имеют статические методы. Определение статического импорта позволяет использовать статические методы без названия класса. В примере статическая функция sqrt(20) (можно и Math.sqrt(20)), возвращает квадратный корень числа. То же самое относится и к классу System, в котором определен статический объект out, поэтому можно его использовать без указания класса, если выполнен статический импорт класса System.
Пример использования классов разных пакетов
Рассмотрим простенький проект PackageExample, включающий 3 java-класса. Два java-класса располагаются в одном пакете «ru.java.online», а третий — в другом «ru.java.online.classes». Структура проекта представлена на следующем скриншоте:

Листинг базового класса, BaseClass.java
Базовый класс включает 2 поля (id, name) и методы get/set. В конструкторе значения полей инициализируется.
package ru.java.online; public class BaseClass < private String protected String name = null; public BaseClass() < this.id = "default"; this.name = "Наименование не определено"; >public String getId() < return id; >public void setId(String id) < this.id = id; >public String getName() < return name; >public void setName(String name) < this.name = name; >@Override public String toString() < return this.getClass().getName() + "\n\t"; > >
Переопределенная функция toString() возвращает наименование класса и значение полей.
Листинг наследника, Inheritor.java
Класс Inheritor.java наследует свойства базового класса BaseClass.java. Поскольку классы располаются в разных пакетах, то базовый класс необходимо импортировать.
package ru.java.online.classes; import ru.java.online.BaseClass; public class Inheritor extends BaseClass < public Inheritor() < this.name = "Наследник"; this.setId("Первый"); >>
Листинг основного класса, MainPackage.java
Основной класс включает статический метод main. Поскольку данный класс не «видит» наследника, то его приходится импортировать.
package ru.java.online; import ru.java.online.classes.Inheritor; public class MainPackage < public MainPackage() < BaseClass bc = new BaseClass(); Inheritor ir = new Inheritor(); System.out.println (bc.toString()); System.out.println (ir.toString()); >public static void main(String[] args) < new MainPackage(); System.exit(0); >>
Результат выполнения данной программы выводится в консоль в следующем виде :
ru.java.online.BaseClass: ru.java.online.classes.Inheritor:
Как видно по результату выполнения программы наименование класса включает пакет.
Говоря о полном наименовании класса следует отметить, что оно включает не только наименование пакета и наименование класса, но также и класс-загрузчик classloader. Подробно о классах-загрузчиках можно почитать здесь.
Использование компонентов данных
В данном разделе рассмотрены практические примеры работы с компонентами данных.
Декларативное использование
Обычно компоненты данных определяются и привязываются к визуальным компонентам декларативно в XML-дескрипторе экрана. Если экран для сущности создан с помощью Studio, можно увидеть корневой элемент , содержащий объявления компонентов данных.
Ниже приведен пример компонентов данных на экране деталей сущности User , который содержит to-one ссылку на Department и to-many ссылку на сущность UserStep :
(1) (2) (3) (4) (5) (6) (7)
| 1 | Корневой элемент data определяет экземпляр DataContext. |
| 2 | Контейнер InstanceContainer сущности User . |
| 3 | Опциональный атрибут fetchPlan определяет граф объектов, который должен быть жадно загружен из базы данных. |
| 4 | InstanceLoader , загружающий экземпляры сущности User . |
| 5 | Контейнер CollectionPropertyContainer для вложенной сущности UserStep . Этот контейнер привязан к атрибуту-коллекции User.steps . |
| 6 | Контейнер CollectionContainer для сущности Department . Он может быть использован как источник элементов выпадающего списка выбора Department . |
| 7 | CollectionLoader , загружающий экземпляры сущности Department по определенному запросу. |
Заданные выше контейнеры данных могут использоваться в визуальных компонентах следующим образом:
(1) (2) (3) (4)
| 1 | Отдельные поля имеют атрибуты dataContainer и property . |
| 2 | Компонент formLayout распространяет свой dataContainer на все вложенные поля, поэтому они требуют только указания атрибута property . |
| 3 | Компонент entityComboBox имеет атрибут itemsContainer для получения списка опций. |
| 4 | У таблицы dataGrid есть только атрибут dataContainer . |
Программное использование
Компоненты данных можно создавать и использовать программно.
В следующем примере мы создадим экран деталей с теми же компонентами данных и визуальными компонентами, которые мы определяли декларативно в предыдущем примере, только на Java без XML-дескриптора.
@Route(value = "users2/:id", layout = MainView.class) @ViewController("User.detail2") public class UserDetailViewProgrammatic extends StandardDetailView (1) @Autowired private UiComponents uiComponents; @Autowired private FetchPlans fetchPlans; @Autowired private Metadata metadata; private InstanceContainer userDc; private InstanceLoader userDl; private CollectionPropertyContainer stepsDc; private CollectionContainer departmentsDc; private CollectionLoader departmentsDl; @Subscribe public void onInit(InitEvent event) < createDataComponents(); createUiComponents(); >private void createDataComponents() (2) userDc = dataComponents.createInstanceContainer(User.class); userDl = dataComponents.createInstanceLoader(); userDl.setContainer(userDc); (3) userDl.setDataContext(dataContext); (4) FetchPlan userFetchPlan = fetchPlans.builder(User.class) .addFetchPlan(FetchPlan.BASE) .add("department", FetchPlan.BASE) .add("steps", FetchPlan.BASE) .add("steps.step", FetchPlan.BASE) .build(); userDl.setFetchPlan(userFetchPlan); stepsDc = dataComponents.createCollectionContainer( UserStep.class, userDc, "steps"); (5) departmentsDc = dataComponents.createCollectionContainer(Department.class); departmentsDl = dataComponents.createCollectionLoader(); departmentsDl.setContainer(departmentsDc); departmentsDl.setDataContext(dataContext); departmentsDl.setQuery("select e from Department e"); (6) departmentsDl.setFetchPlan(FetchPlan.BASE); > private void createUiComponents() < TypedTextFieldusernameField = uiComponents.create(TypedTextField.class); usernameField.setValueSource(new ContainerValueSource<>(userDc, "username")); (7) getContent().add(usernameField); FormLayout formLayout = uiComponents.create(FormLayout.class); getContent().add(formLayout); TypedTextField firstNameField = uiComponents.create(TypedTextField.class); firstNameField.setValueSource(new ContainerValueSource<>(userDc, "firstName")); formLayout.add(firstNameField); TypedTextField lastNameField = uiComponents.create(TypedTextField.class); lastNameField.setValueSource(new ContainerValueSource<>(userDc, "lastName")); formLayout.add(lastNameField); EntityComboBox departmentField = uiComponents.create(EntityComboBox.class); departmentField.setValueSource(new ContainerValueSource<>(userDc, "department")); departmentField.setItems(departmentsDc); (8) formLayout.add(departmentField); DataGrid dataGrid = uiComponents.create(DataGrid.class); dataGrid.addColumn(metadata.getClass(UserStep.class).getPropertyPath("step.name")); dataGrid.setItems(new ContainerDataGridItems<>(stepsDc)); (9) getContent().add(dataGrid); getContent().expand(dataGrid); Button okButton = uiComponents.create(Button.class); okButton.setText("OK"); okButton.addClickListener(clickEvent -> closeWithSave()); getContent().add(okButton); Button cancelButton = uiComponents.create(Button.class); cancelButton.setText("Cancel"); cancelButton.addClickListener(clickEvent -> closeWithDiscard()); getContent().add(cancelButton); > @Override protected InstanceContainer getEditedEntityContainer() (10) return userDc; > @Subscribe protected void onBeforeShow(BeforeShowEvent event) (11) userDl.load(); departmentsDl.load(); > >
| 1 | DataComponents — это фабрика для создания компонентов данных. |
| 2 | Регистрируем в экране экземпляр DataContext , чтобы обеспечить работу стандартного действия сохранения экрана. |
| 3 | Загрузчик userDl загружает данные в контейнер userDc . |
| 4 | Загрузчик userDl помещает загруженные сущности в data context для отслеживания изменений. |
| 5 | stepsDc создается как контейнер свойства. |
| 6 | Определяем запрос для загрузчика departmentsDl . |
| 7 | ContainerValueSource используется для связи одиночных полей с контейнерами данных. |
| 8 | CollectionContainer напрямую используется для предоставления списка элементов для полей выбора. |
| 9 | ContainerDataGridItems используется для связи таблиц dataGrid с контейнерами. |
| 10 | Переопределяем getEditedEntityContainer() , чтобы указать контейнер вместо аннотации @EditedEntityContainer . |
| 11 | Загружаем данные перед отображением экрана. Идентификатор редактируемой сущности будет автоматически передан в загрузчик userDl . |
Зависимости между компонентами данных
Иногда требуется загружать и отображать данные, которые зависят от других данных в том же экране. К примеру, на скриншоте ниже таблица слева отображает список пользователей (сущность User ), а таблица справа – список шагов онбординга (сущность UserStep ) выбранного сотрудника. Список справа обновляется каждый раз, когда меняется выбранный элемент в таблице слева.

В этом примере сущность User содержит атрибут steps , который является коллекцией с отношением one-to-many. Самый простой способ реализации такого экрана – загружать список пользователей с фетч-планом, содержащим атрибут steps , и использовать контейнер свойств для работы со списком зависимых строк UserStep . Затем связать левую таблицу с родительским контейнером, а правую – с контейнером свойства.
Однако этот подход имеет следующие последствия для производительности: экземпляры UserStep будут сразу загружены для всех пользователей из левой таблицы, несмотря на то, что в один момент времени отображаются строки только для одного выбранного пользователя. При большом количестве пользователей это вызовет большую бессмысленную нагрузку на сервер. Поэтому мы рекомендуем использовать контейнеры свойств и глубокие фетч-планы только тогда, когда нужно загрузить единственный экземпляр корневой сущности: например, в экране деталей одного сотрудника.
Кроме того, корневая сущность может не иметь прямого атрибута, указывающего на зависимую сущность. В этом случае подход с использованием контейнера свойств совсем не подходит.
Наиболее общей практикой организации отношений между данными в экране является использование запросов с параметрами. Зависимый загрузчик содержит запрос с параметром, который связывает данные с главным контейнером. Когда меняется текущий экземпляр в главном контейнере, этот экземпляр передается в качестве параметра в зависимый загрузчик и вызывается его перезагрузка.
Рассмотрим пример экрана, в котором есть две зависимых пары контейнер/загрузчик и привязанные к ним таблицы для отображения данных.
(1) (2) (3) (4) (5)
| 1 | Главный контейнер и загрузчик. |
| 2 | Зависимый контейнер и загрузчик. |
| 3 | Фасет DataLoadCoordinator здесь не используется, поэтому загрузчики нужно вызвать программно в контроллере. |
| 4 | Главная таблица. |
| 5 | Зависимая таблица. |
@Route(value = "users-with-steps", layout = MainView.class) @ViewController("UserWithStepsListView") @ViewDescriptor("user-with-steps-list-view.xml") @LookupComponent("usersTable") @DialogMode(width = "50em", height = "37.5em") public class UserWithStepsListView extends StandardListView < @ViewComponent private CollectionLoaderusersDl; @ViewComponent private CollectionLoader userStepsDl; @Subscribe public void onBeforeShow(final BeforeShowEvent event) (1) > @Subscribe(id = "usersDc", target = Target.DATA_CONTAINER) public void onUsersDcItemChange(final InstanceContainer.ItemChangeEvent event) (2) userStepsDl.load(); > >
| 1 | Главный загрузчик вызывается обработчиком BeforeShowEvent . |
| 2 | В обработчике ItemChangeEvent главного контейнера передается параметр в зависимый загрузчик и вызывается его загрузка. |
| Фасет DataLoadCoordinator позволяет устанавливать связи между компонентами данных декларативно без написания кода на Java. |
Специализированная сортировка
Сортировка таблиц по атрибутам сущности в UI производится объектом типа CollectionContainerSorter , который устанавливается для CollectionContainer. Стандартная реализация сортирует данные в памяти, если загруженный список умещается на одной странице, или посылает запрос с соответствующим «order by» в базу данных. Выражение «order by» формируется бином JpqlSortExpressionProvider .
Некоторые атрибуты могут потребовать специальной реализации сортировки. Ниже рассматривается простой пример: предположим, в сущности Department есть атрибут num типа String , но на самом деле атрибут хранит только числовые значения. Поэтому необходимо иметь порядок сортировки для чисел: 1 , 2 , 3 , 10 , 11 . Стандартный механизм сортировки в данном случае выдаст порядок 1 , 10 , 11 , 2 , 3 .
Сначала создайте наследника класса CollectionContainerSorter для сортировки в памяти:
package com.company.onboarding.app; import com.company.onboarding.entity.Department; import io.jmix.core.Sort; import io.jmix.core.metamodel.model.MetaClass; import io.jmix.core.metamodel.model.MetaPropertyPath; import io.jmix.flowui.model.BaseCollectionLoader; import io.jmix.flowui.model.CollectionContainer; import io.jmix.flowui.model.impl.CollectionContainerSorter; import io.jmix.flowui.model.impl.EntityValuesComparator; import org.springframework.beans.factory.BeanFactory; import java.util.Comparator; import java.util.Objects; public class CustomCollectionContainerSorter extends CollectionContainerSorter < public CustomCollectionContainerSorter(CollectionContainer>container, BaseCollectionLoader loader, BeanFactory beanFactory) < super(container, loader, beanFactory); >@Override protected Comparator >createComparator(Sort.Order sortOrder, MetaClass metaClass) < MetaPropertyPath metaPropertyPath = Objects.requireNonNull( metaClass.getPropertyPath(sortOrder.getProperty())); if (metaPropertyPath.getMetaClass().getJavaClass().equals(Department.class) && "num".equals(metaPropertyPath.toPathString())) < boolean isAsc = sortOrder.getDirection() == Sort.Direction.ASC; return Comparator.comparing((Department e) ->e.getNum() == null ? null : Integer.valueOf(e.getNum()), new EntityValuesComparator<>(isAsc, metaClass, beanFactory)); > return super.createComparator(sortOrder, metaClass); > >
Создайте сортировщик в нужном экране:
public class DepartmentListView2 extends StandardListView < @ViewComponent private CollectionContainerdepartmentsDc; @ViewComponent private CollectionLoader departmentsDl; @Autowired private BeanFactory beanFactory; @Subscribe public void onInit(final InitEvent event)
Если же специализированная сортировка должна являться глобальной, то создайте собственную фабрику, которая будет инстанциировать сортировщик для всей системы:
package com.company.onboarding.app; import io.jmix.flowui.model.BaseCollectionLoader; import io.jmix.flowui.model.CollectionContainer; import io.jmix.flowui.model.Sorter; import io.jmix.flowui.model.SorterFactory; import org.springframework.lang.Nullable; import org.springframework.context.annotation.Primary; import org.springframework.stereotype.Component; @Primary @Component public class CustomSorterFactory extends SorterFactory < @Override public Sorter createCollectionContainerSorter(CollectionContainer container, @Nullable BaseCollectionLoader loader) < return new CustomCollectionContainerSorter(container, loader, beanFactory); >>
Кроме того, можно создать собственную реализацию JpqlSortExpressionProvider для сортировки на уровне базы данных:
package com.company.onboarding.app; import com.company.onboarding.entity.Department; import io.jmix.core.metamodel.model.MetaPropertyPath; import io.jmix.data.impl.DefaultJpqlSortExpressionProvider; import org.springframework.context.annotation.Primary; import org.springframework.stereotype.Component; @Primary @Component public class CustomSortExpressionProvider extends DefaultJpqlSortExpressionProvider < @Override public String getDatatypeSortExpression(MetaPropertyPath metaPropertyPath, boolean sortDirectionAsc) < if (metaPropertyPath.getMetaClass().getJavaClass().equals(Department.class) && "num".equals(metaPropertyPath.toPathString())) < return String.format("CAST(.%s BIGINT)", metaPropertyPath); > return String.format(".%s", metaPropertyPath); > >
This page was built using the Antora default UI.
The source code for this UI is licensed under the terms of the MPL-2.0 license.
Package com company что это java
Как правило, в Java классы объединяются в пакеты. Пакеты позволяют организовать классы логически в наборы. По умолчанию java уже имеет ряд встроенных пакетов, например, java.lang , java.util , java.io и т.д. Кроме того, пакеты могут иметь вложенные пакеты.
Организация классов в виде пакетов позволяет избежать конфликта имен между классами. Ведь нередки ситуации, когда разработчики называют свои классы одинаковыми именами. Принадлежность к пакету позволяет гарантировать однозначность имен.
Чтобы указать, что класс принадлежит определенному пакету, надо использовать директиву package , после которой указывается имя пакета:
package название_пакета;
Как правило, названия пакетов соответствуют физической структуре проекта, то есть организации каталогов, в которых находятся файлы с исходным кодом. А путь к файлам внутри проекта соответствует названию пакета этих файлов. Например, если классы принадлежат пакету mypack, то эти классы помещаются в проекте в папку mypack.
Классы необязательно определять в пакеты. Если для класса пакет не определен, то считается, что данный класс находится в пакете по умолчанию, который не имеет имени.
Например, создадим в папке для исходных файлов каталог study . В нем создадим файл Program.java со следующим кодом:
package study; public class Program < public static void main(String[] args) < Person kate = new Person("Kate", 32); kate.displayInfo(); >> class Person < String name; int age; Person(String name, int age)< this.name = name; this.age = age; >void displayInfo() < System.out.printf("Name: %s \t Age: %d \n", name, age); >>
Директива package study в начале файла указывает, что классы Program и Person, которые здесь определены, принадлежат пакету study.
Когда мы работаем в среде разработки, например, в Netbeans, то IDE берет на себя все вопросы компиляции пакетов и входящих в них файлов. Соответственно нам достаточно нажать на кнопку, и все будет готово. Однако если мы компилируем программу в командной строке, то мы можем столкнуться с некоторыми трудностями. Поэтому рассмотрим этот аспект.
Для компиляции программы вначале в командной строке/терминале с помощью команды cd перейдем к папке, где находится каталог study.
cd C:\java
Например, в моем случае это каталог C:\java (то есть файл с исходным кодом расположен по пути C:\java\study\Program.java).
Для компиляции выполним команду
javac study\Program.java
После этого в папке study появятся скомпилированные файлы Program.class и Person.class. Для запуска программы выполним команду:
java study.Program

Импорт пакетов и классов
Если нам надо использовать классы из других пакетов, то нам надо подключить эти пакеты и классы. Исключение составляют классы из пакета java.lang (например, String ), которые подключаются в программу автоматически.
Например, знакомый по прошлым темам класс Scanner находится в пакете java.util , поэтому мы можем получить к нему доступ следующим способом:
java.util.Scanner in = new java.util.Scanner(System.in);
То есть мы указываем полный путь к файлу в пакете при создании его объекта. Однако такое нагромождение имен пакетов не всегда удобно, и в качестве альтернативы мы можем импортировать пакеты и классы в проект с помощью директивы import , которая указывается после директивы package:
package study; import java.util.Scanner; // импорт класса Scanner public class Program < public static void main(String[] args) < Scanner in = new Scanner(System.in); >>
Директива import указывается в самом начале кода, после чего идет имя подключаемого класса (в данном случае класса Scanner).
В примере выше мы подключили только один класс, однако пакет java.util содержит еще множество классов. И чтобы не подключать по отдельности каждый класс, мы можем сразу подключить весь пакет:
import java.util.*; // импорт всех классов из пакета java.util
Теперь мы можем использовать любой класс из пакета java.util.
Возможна ситуация, когда мы используем два класса с одним и тем же названием из двух разных пакетов, например, класс Date имеется и в пакете java.util , и в пакете java.sql . И если нам надо одновременно использовать два этих класса, то необходимо указывать полный путь к этим классам в пакете:
java.util.Date utilDate = new java.util.Date(); java.sql.Date sqlDate = new java.sql.Date();
Статический импорт
В java есть также особая форма импорта - статический импорт. Для этого вместе с директивой import используется модификатор static :
package study; import static java.lang.System.*; import static java.lang.Math.*; public class Program < public static void main(String[] args) < double result = sqrt(20); out.println(result); >>
Здесь происходит статический импорт классов System и Math. Эти классы имеют статические методы. Благодаря операции статического импорта мы можем использовать эти методы без названия класса. Например, писать не Math.sqrt(20) , а sqrt(20) , так как функция sqrt() , которая возвращает квадратный корень числа, является статической. (Позже мы рассмотрим статические члены класса).
То же самое в отношении класса System: в нем определен статический объект out , поэтому мы можем его использовать без указания класса.