System.getenv(): примеры (JAVA)
System.getenv(): MapОписание метода System.getenv()
Метод System.getenv() предназначен для получения переменных окружения операционной системы, в которой выполняется Java-приложение. Переменные окружения представляют собой пары ключ-значение (строка-строка), доступные процессу. Метод используется, когда требуется считать конфигурационные параметры, заданные на уровне среды выполнения: пути к директориям, настройки подключения, секретные ключи и другие внешние параметры.
Метод имеет две перегруженные формы:
- System.getenv() - без аргументов. Возвращает неизменяемую (unmodifiable) карту Map<String, String>, содержащую все текущие переменные окружения. Ключи и значения - строки. Попытка изменить возвращённую карту вызовет исключение UnsupportedOperationException.
- System.getenv(String name) - принимает один аргумент - имя переменной. Возвращает строку - значение переменной окружения с указанным именем. Если переменная не определена, возвращается null.
Имя переменной чувствительно к регистру на большинстве Unix-подобных систем (например, Linux, macOS) и нечувствительно на Windows (хотя рекомендуется всегда указывать точный регистр). Возвращаемое значение в форме с одним аргументом - String или null.
Метод появился в JDK 1.0 и с тех пор не претерпел существенных изменений. Он относится к классу java.lang.System и является точкой доступа к окружению процесса.
Примеры использования System.getenv()
Пример 1: Получение всех переменных окружения.
import java.util.Map;
public class GetEnvAll {
public static void main(String[] args) {
Map<String, String> env = System.getenv();
for (String key : env.keySet()) {
System.out.println(key + "=" + env.get(key));
}
}
}JAVA_HOME=/usr/lib/jvm/java-11-openjdk PATH=/usr/bin:/bin USER=user ... (зависит от системы)
Пример 2: Получение конкретной переменной.
public class GetEnvOne {
public static void main(String[] args) {
String path = System.getenv("PATH");
System.out.println("PATH: " + path);
}
}PATH: /usr/local/bin:/usr/bin:/bin
Пример 3: Попытка получить несуществующую переменную.
public class GetEnvMissing {
public static void main(String[] args) {
String value = System.getenv("MY_VAR_NOT_EXISTS");
System.out.println("Value: " + value);
}
}Value: null
Альтернативы в Java: System.getProperty()
В Java существует аналогичный механизм для доступа к системным свойствам - метод System.getProperty(). Системные свойства отличаются от переменных окружения:
- Системные свойства задаются через флаг -Dproperty=value при запуске JVM и хранятся внутри виртуальной машины.
- Переменные окружения - это параметры операционной системы, доступные всем процессам.
- System.getProperty() возвращает String или null, а также имеет форму с аргументом по умолчанию: System.getProperty(String key, String def).
Какую альтернативу предпочесть:
- Для внешних конфигураций, которые задаются до запуска приложения (например, в Docker-контейнере, на сервере), удобнее использовать переменные окружения.
- Для настроек, специфичных для JVM (пути к библиотекам, кодировки), применяют системные свойства.
- Если требуется передать параметры через командную строку с возможностью переопределения, системные свойства часто удобнее.
Следует помнить, что оба метода возвращают неизменяемые объекты (карту или строку) и не позволяют модифицировать окружение.
Альтернативы в других языках программирования
Практически все современные языки предоставляют доступ к переменным окружения. Ниже приведены краткие примеры и отличия от Java.
PHP - функция getenv():
$path = getenv('PATH');
echo $path;
$all = getenv(); // возвращает ассоциативный массив/usr/local/bin:/usr/binОтличие от Java: возвращает массив, а не Map; имя может быть передано с опциональным аргументом local_only.
JavaScript (Node.js) - объект process.env:
const path = process.env.PATH;
console.log(path);
// process.env - объект, но его изменение не влияет на родительский процесс/usr/local/bin:/usr/binОтличие от Java: напрямую доступен как объект; значения всегда строки; отсутствует метод, возвращающий Map.
Python - словарь os.environ:
import os
path = os.environ.get('PATH')
print(path)
# os.environ - это словарь (mapping)/usr/local/bin:/usr/binОтличие от Java: изменяемый словарь, однако изменения не влияют на родительский процесс (только на дочерние).
C# - метод Environment.GetEnvironmentVariable():
string path = Environment.GetEnvironmentVariable("PATH");
Console.WriteLine(path);/usr/local/bin:/usr/binОтличие от Java: есть перегрузка с указанием целевого уровня (процесс, пользователь, машина); возвращает null при отсутствии.
Go - функция os.Getenv():
package main
import "os"
func main() {
path := os.Getenv("PATH")
println(path)
}/usr/local/bin:/usr/binОтличие от Java: возвращает пустую строку, если переменная не установлена (отсутствует nil); есть вторая форма LookupEnv.
Kotlin (на JVM) - использует тот же System.getenv() из Java, отличий нет.
Lua - таблица os.getenv():
local path = os.getenv("PATH")
print(path)/usr/local/bin:/usr/binОтличие от Java: возвращает nil при отсутствии; нет возможности получить все переменные одной функцией.
В SQL нет прямой альтернативы, так как окружение не является концепцией реляционных баз данных; переменные могут передаваться через системные функции СУБД (например, GETENV() в Oracle).
Типичные ошибки при работе с System.getenv()
1. Попытка изменить возвращённую карту.
Метод System.getenv() возвращает неизменяемую карту. Любая попытка добавить, удалить или заменить элемент приводит к исключению UnsupportedOperationException.
Map<String, String> env = System.getenv();
env.put("NEW_VAR", "value"); // ошибкаException in thread "main" java.lang.UnsupportedOperationException
2. Игнорирование регистра ключа на Unix-системах.
На Linux и macOS имена переменных чувствительны к регистру. Запрос System.getenv("path") вернёт null, даже если существует PATH.
System.out.println(System.getenv("path")); // null на Linux
System.out.println(System.getenv("PATH")); // /usr/bin3. Предположение, что переменная обязательно существует.
Если переменная не определена, System.getenv(name) возвращает null, а не пустую строку. Вызов методов у null приведёт к NullPointerException.
String val = System.getenv("UNDEFINED");
System.out.println(val.length()); // NullPointerExceptionException in thread "main" java.lang.NullPointerException
4. Путаница с системными свойствами.
Начинающие разработчики иногда ожидают, что System.getenv() вернёт аргументы JVM (-D). Для этого следует использовать System.getProperty().
5. Изменение окружения через ProcessBuilder после вызова getenv.
Объект, возвращённый getenv(), не связан с окружением дочерних процессов, создаваемых через ProcessBuilder. Для передачи окружения дочерним процессам необходимо настроить сам ProcessBuilder.
Изменения в версиях Java
Метод System.getenv() существует с самого первого выпуска JDK (1.0) и с тех пор его сигнатура и поведение не менялись. В ранних версиях метод getenv() без аргументов был deprecated (устаревшим) начиная с JDK 1.1 до JDK 1.4, но был восстановлен в JDK 5.0 и больше не является устаревшим.
В Java 9 была введена модульная система (Jigsaw). Модули могут ограничивать доступ к некоторым классам, но java.lang.System остаётся доступным всегда. Изменений в самом методе не произошло.
В Java 17 (LTS) и более новых версиях метод работает без изменений. Не появилось новых перегрузок или флагов.
Таким образом, System.getenv() - стабильный и неизменный API, на который можно полагаться в любой версии Java от 1.0 до 21.
Расширенные примеры использования
Пример 1: Получение значения с проверкой и значением по умолчанию (без использования тернарного оператора).
public class GetEnvWithDefault {
public static void main(String[] args) {
String home = System.getenv("HOME");
if (home == null) {
home = "/tmp";
}
System.out.println("Home: " + home);
}
}Home: /home/user
Пример 2: Создание неизменяемой копии карты окружения (на всякий случай, хотя уже неизменяема).
import java.util.Collections;
import java.util.Map;
public class UnmodifiableCopy {
public static void main(String[] args) {
Map<String, String> env = System.getenv();
Map<String, String> copy = Collections.unmodifiableMap(env);
System.out.println(copy.size());
}
}42
Пример 3: Использование в Docker-среде для чтения пароля из переменной окружения (без жёсткого кода).
public class DbPassword {
public static void main(String[] args) {
String password = System.getenv("DB_PASSWORD");
if (password == null || password.isEmpty()) {
throw new RuntimeException("DB_PASSWORD not set");
}
// соединение с БД
System.out.println("Password retrieved");
}
}(выполнение без ошибок, если переменная задана)
Пример 4: Перебор всех переменных окружения с фильтрацией по префиксу (например, MYAPP_).
public class FilteredEnv {
public static void main(String[] args) {
String prefix = "MYAPP_";
Map<String, String> env = System.getenv();
for (Map.Entry<String, String> entry : env.entrySet()) {
if (entry.getKey().startsWith(prefix)) {
System.out.println(entry.getKey() + " = " + entry.getValue());
}
}
}
}(выводятся только переменные, начинающиеся с MYAPP_)
Пример 5: Проверка на существование переменной с использованием containsKey().
public class CheckExists {
public static void main(String[] args) {
Map<String, String> env = System.getenv();
if (env.containsKey("JAVA_HOME")) {
System.out.println("JAVA_HOME is set to " + env.get("JAVA_HOME"));
} else {
System.out.println("JAVA_HOME is not set");
}
}
}JAVA_HOME is set to /usr/lib/jvm/java-11-openjdk
Пример 6: Конвертация карты в обычный HashMap для последующей модификации (хотя модификация не повлияет на окружение).
import java.util.HashMap;
import java.util.Map;
public class MutableEnvCopy {
public static void main(String[] args) {
Map<String, String> env = System.getenv();
Map<String, String> mutable = new HashMap<>(env);
mutable.put("MY_VAR", "my_value");
System.out.println(mutable.get("MY_VAR"));
}
}my_value