Кофе-брейк #121. Что такое Classpath в Java и как его установить? Неизменяемость в Java

Статья из группы Random

Что такое Classpath в Java и как его установить?

Источник: Medium Знание основ программирования и потока выполнения программных файлов помогает нам понять язык. Знание параметра Classpath — одно из основных понятий, которым должен владеть каждый Java-разработчик. Сегодня мы обсудим, что такое путь к классам (Classpath), как его установить и как он помогает JVM исполнять файлы классов. Кофе-брейк #121. Что такое Classpath в Java и как его установить? Неизменяемость в Java - 1

Что такое Classpath?

Classpath является одним из основных параметров в Java, однако новички в программировании часто понимают его неправильно. Если упростить, то Classpath — это просто набор путей, по которым компилятор Java и JVM должны находить необходимые классы для компиляции или выполнения других классов.

Как Classpath помогает JVM в выполнении файлов классов

Давайте начнем с примера. Предположим, что у нас есть файл Main.java, который находится в папке /Users/vikram/Documents/test-java/src/com/programming/v1/Main.java.

package com.programming.v1;

public class Main {
    public static void main(String[] args) {
        System.out.println("Hello classpath");
    }
}
Допустим, мы находимся в /Users/vikram/Documents и хотим скомпилировать этот класс:

javac test-java/src/com/programming/v1/Main.java
Теперь, чтобы выполнить этот файл класса, нам нужно сообщить виртуальной машине Java, где искать файл .class, используя classpath или флаг cp в команде java.

vg@lp1 Documents % java -cp "test-java/src" com.programming.v1.Main
Hello classpath
vg@lp1 Documents % java -classpath "test-java/src" com.programming.v1.Main
Hello classpath
Первый параметр — это корневая папка, в которую записывается пакет. Второй параметр — это имя пакета с именем класса. Когда команда Java исполняется, виртуальная машина Java просматривает папку test-java/src, а затем загружает основной класс для ее выполнения.

Как установить переменный Classpath

Переменный параметр Classpath может быть установлен, как показано ниже, на компьютерах под управлением Linux:

export CLASSPATH="test-java/src"
Classpath на компьютере с Windows можно добавить/обновить с помощью переменных среды. После того, как переменная среды установлена, команду java можно выполнить, как показано ниже:

vg@lp1 Documents % java com.programming.v1.Main
Hello classpath
Вот и все, что нужно знать о Classpath. Спасибо за чтение!

Неизменяемость в Java

Источник: Medium Переменные в Java бывают двух типов: примитивные и ссылочные. Все в Java передается по значению, но в случае ссылочных типов исходные данные могут обновляться с использованием переданного адреса памяти. Кофе-брейк #121. Что такое Classpath в Java и как его установить? Неизменяемость в Java - 2Ключевое слово final используется для того, чтобы переменная действовала как константа, то есть избегала переназначения. Это хорошо работает для примитивов, у которых нет памяти в куче, тогда как для ссылочных типов ограничено только переназначение, а внутреннее состояние может быть изменено. Это может привести к множеству проблем с параллелизмом и условиям гонки (race conditions). Таким образом включение неизменяемых характеристик в обычный тип в Java дает много преимуществ.

Преимущества неизменяемости в Java

1. Безопасность потоков

Неизменяемые типы невосприимчивы к условиям гонки в многопоточной среде, поскольку объект останется согласованным после его создания. Несколько потоков не могут изменить свое внутреннее состояние, поэтому синхронизация не требуется.

2. Основополагающий тип

String в стандартной библиотеке Java — хороший пример базового класса. Это очень простой и неизменяемый класс, который можно использовать для создания доменов бизнес-логики поверх него. Точно так же неизменяемый тип может выступать в качестве отличного базового типа, на основе которого можно строить.

Характеристики

1. Поля Private и Final

Поля, содержащие состояние объекта, — это private и final. Частная (private) видимость запрещает прямой доступ к полю, а окончательная (final) гарантирует, что поле назначается только один раз.

2. Никаких методов-модификаторов

К полю private нельзя получить доступ за пределами класса. Обычно для чтения и записи в поля предусмотрены методы доступа (геттеры) и методы-модификаторы (сеттеры) соответственно. Для обеспечения неизменности модификаторы не допускаются.

3. Класс Final

Предоставление возможности наследования класса может нарушить неизменяемость. Подкласс, расширяющий неизменяемый класс, может повлиять на состояние объекта. Следовательно, класс является окончательным (final).

4. Защитные копии (Defensive Copies)

Во время создания объекта вместо того, чтобы назначать аргументы из конструктора непосредственно закрытым полям, создание глубокой копии (или неизменяемой копии) аргументов обеспечит внешнее изменение. Если один из аргументов является ссылочным типом, им можно легко манипулировать на вызывающей стороне. Создание защитных копий позволяет избежать этой манипуляции. Точно так же для средств доступа (геттеров) вместо прямой ссылки на внутреннее поле можно свободно делиться его копией.

Реализация

Employee


import java.time.LocalDate;
import java.util.List;

import static java.util.List.copyOf;

public final class Employee {
    
    private final long id;
    private final String name;
    private final LocalDate joinDate;
    private final List<String> achievements;

    public Employee(long id,
                    String name,
                    LocalDate joinDate,
                    List<String> achievements) {
        this.id = id;
        this.name = name;
        this.joinDate = joinDate;
        this.achievements = copyOf(achievements);
    }

    public long getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public LocalDate getJoinDate() {
        return joinDate;
    }

    public List<String> getAchievements() {
        return achievements;
    }
}
  • Не все поля имеют защитные копии в конструкторе. Это связано с тем, что id является примитивным, а поля name и joinDate являются неизменяемыми типами. Они не могут быть изменены вызывающей стороной и останутся неизменными, в то время как поле achievements требует копии аргумента, сделанного с помощью метода List.copyOf. Это объясняется тем, что copyOf возвращает неизменяемый List.

  • Точно так же методы доступа возвращают поля напрямую, а не защитные копии, потому что все типы полей являются неизменяемыми (включая achievements) и, следовательно, не могут быть изменены вне класса.

Улучшения

До Java 16

Реализация Employee может быть улучшена с помощью таких библиотек, как Lombok. Это уменьшает многословие в коде и помогает ему выглядеть более чистым. Библиотека поставляется с аннотациями для сокращения стандартного кода. @Value (аннотация) может использоваться для создания геттеров и конструктора всех аргументов. Это также создает класс final и поля private и final. В качестве примечания, он также генерирует методы toString, equals и hashCode. Реализация Employee может быть переписана с помощью @Value, как показано ниже:

import lombok.Value;

import java.time.LocalDate;
import java.util.List;

import static java.util.List.copyOf;

@Value
public class Employee {
    
    long id;
    String name;
    LocalDate joinDate;
    List<String> achievements;

    public Employee(long id,
                    String name,
                    LocalDate joinDate,
                    List<String> achievements) {
        this.id = id;
        this.name = name;
        this.joinDate = joinDate;
        this.achievements = copyOf(achievements);
    }
}

Java 16 и более поздние версии

В релизе Java 16 появилась новая функция Record. Она (как утверждает JEP) является классами, которые действуют как прозрачные носители неизменяемых данных и могут рассматриваться как номинальные кортежи (tuples). Класс Employee можно повторно реализовать как record Employee, что показано ниже.

import java.time.LocalDate;
import java.util.List;

import static java.util.List.copyOf;

public record Employee(long id,
                       String name,
                       LocalDate joinDate,
                       List<String> achievements) {
    
    public Employee(long id,
                    String name,
                    LocalDate joinDate,
                    List<String> achievements) {
        this.id = id;
        this.name = name;
        this.joinDate = joinDate;
        this.achievements = copyOf(achievements);
    }
}

Недостатки

Единственная проблема с неизменяемостью — дополнительная память и обработка, которые требуются даже для небольшой модификации. Каждый раз необходимо создавать новый объект, что может быть весьма накладно. Чтобы обойти этот недостаток, можно реализовать такие механизмы, как кэширование и сохранение результатов.
Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ