Перейти к основному содержимому

Краткое руководство по java.lang.System

· 6 мин. чтения

1. Обзор

В этом руководстве мы кратко рассмотрим класс java.lang.System , его функции и основные функции.

2. ИО

System является частью java.lang , и одной из его основных функций является предоставление нам доступа к стандартным потокам ввода-вывода.

Проще говоря, он предоставляет три поля, по одному для каждого потока:

  • вне
  • ошибаться
  • в

2.1. Системный выход

System.out указывает на стандартный поток вывода, представляя его как PrintStream , и мы можем использовать его для вывода текста на консоль:

System.out.print("some inline message");

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

// Redirect to a text file
System.setOut(new PrintStream("filename.txt"));

2.2. Система.ошибка

System.err очень похож на System.out . Оба поля являются экземплярами PrintStream, и оба предназначены для вывода сообщений на консоль.

Но System.err представляет собой стандартную ошибку, и мы используем ее специально для вывода сообщений об ошибках:

System.err.print("some inline error message");

Консоли часто отображают поток ошибок иначе, чем выходной поток.

Дополнительные сведения см. в документации по PrintStream .

2.3. System.in

System.in указывает на стандартный in, представляя его как InputStream, и мы можем использовать его для чтения ввода с консоли.

И хотя мы немного больше вовлечены, мы все еще можем управлять:

public String readUsername(int length) throws IOException {
byte[] name = new byte[length];
System.in.read(name, 0, length); // by default, from the console
return new String(name);
}

Вызывая System.in.read , приложение останавливается и ожидает ввода из стандартного ввода. Какие бы ни были байты следующей длины , они будут считаны из потока и сохранены в массиве байтов.

Все остальное, что вводит пользователь, остается в потоке , ожидая другого вызова для чтения.

Конечно, работа на таком низком уровне может быть сложной и чреватой ошибками, поэтому мы можем немного почистить ее с помощью BufferedReader :

public String readUsername() throws IOException {
BufferedReader reader = new BufferedReader(
new InputStreamReader(System.in));
return reader.readLine();
}

В приведенном выше расположении readLine будет читать из System.in до тех пор, пока пользователь не нажмет return, что немного ближе к тому, что мы могли бы ожидать.

Обратите внимание, что в данном случае мы намеренно не закрываем поток. Закрытие стандарта означает , что его нельзя прочитать снова в течение жизненного цикла программы!

И, наконец, расширенное использование System.in заключается в вызове System.setIn для перенаправления его в другой InputStream .

3. Вспомогательные методы

Система предоставляет нам множество методов, чтобы помочь нам с такими вещами, как:

  • Доступ к консоли
  • Копирование массивов
  • Дата и время наблюдения
  • Выход из JRE
  • Доступ к свойствам среды выполнения
  • Доступ к переменным среды и
  • Управление сбором мусора

3.1. Доступ к консоли

В Java 1.6 появился другой способ взаимодействия с консолью, а не просто использование System.out и in напрямую.

Мы можем получить к нему доступ, вызвав System.console :

public String readUsername() {
Console console = System.console();

return console == null ? null :
console.readLine("%s", "Enter your name: ");
}

Обратите внимание, что в зависимости от базовой операционной системы и того, как мы запускаем Java для запуска текущей программы, консоль может возвращать значение null, поэтому всегда обязательно проверяйте перед использованием .

Прочтите документацию по консоли , чтобы узнать больше об использовании.

3.2. Копирование массивов

System.arraycopy — это старый способ копирования одного массива в другой в стиле C.

В основном, arraycopy предназначен для копирования одного полного массива в другой массив:

int[] a = {34, 22, 44, 2, 55, 3};
int[] b = new int[a.length];

System.arraycopy(a, 0, b, 0, a.length);
assertArrayEquals(a, b);

Однако мы можем указать начальную позицию для обоих массивов, а также количество копируемых элементов.

Например, допустим, мы хотим скопировать 2 элемента из a , начиная с a[1] в b , начиная с b[3] :

System.arraycopy(a, 1, b, 3, 2); 
assertArrayEquals(new int[] {0, 0, 0, 22, 44, 0}, b);

Также помните, что arraycopy выдаст:

  • NullPointerException , если любой из массивов имеет значение null
  • IndexOutOfBoundsException , если копия ссылается на какой-либо массив за пределами своего диапазона
  • ArrayStoreException , если копия приводит к несоответствию типа

3.3. Дата и время наблюдения

В System есть два метода, связанных со временем . Один — currentTimeMillis , а другой — nanoTime .

currentTimeMillis возвращает количество миллисекунд, прошедших с эпохи Unix, то есть 1 января 1970 года, 12:00 UTC:

public long nowPlusOneHour() {
return System.currentTimeMillis() + 3600 * 1000L;
}

public String nowPrettyPrinted() {
return new Date(System.currentTimeMillis()).toString();
}

nanoTime возвращает время относительно запуска JVM. Мы можем вызвать его несколько раз, чтобы отметить течение времени в приложении:

long startTime = System.nanoTime();
// ...
long endTime = System.nanoTime();

assertTrue(endTime - startTime < 10000);

Обратите внимание, что, поскольку nanoTime настолько детализирован, безопаснее использовать endTime — startTime < 10000 , чем endTime < startTime из-за возможности числового переполнения .

3.4. Выход из программы

Если мы хотим программно выйти из выполняемой в данный момент программы, System.exit сделает свое дело.

Чтобы вызвать выход , нам нужно указать код выхода, который будет отправлен на консоль или оболочку, запустившую программу.

По соглашению в Unix статус 0 означает нормальный выход, а ненулевой означает, что произошла какая-то ошибка:

if (error) {
System.exit(1);
} else {
System.exit(0);
}

Обратите внимание, что в настоящее время для большинства программ было бы странно вызывать это. Например, при вызове в приложении веб-сервера он может отключить весь сайт!

3.5. Доступ к свойствам среды выполнения

Система предоставляет доступ к свойствам времени выполнения с помощью getProperty .

И мы можем управлять ими с помощью setProperty и clearProperty :

public String getJavaVMVendor() {
System.getProperty("java.vm.vendor");
}

System.setProperty("abckey", "abcvaluefoo");
assertEquals("abcvaluefoo", System.getProperty("abckey"));

System.clearProperty("abckey");
assertNull(System.getProperty("abckey"));

Свойства, указанные через -D , доступны через getProperty .

Мы также можем указать значение по умолчанию:

System.clearProperty("dbHost");
String myKey = System.getProperty("dbHost", "db.host.com");
assertEquals("db.host.com", myKey);

А System.getProperties предоставляет набор всех системных свойств:

Properties properties = System.getProperties();

Из которого мы можем делать любые операции со свойствами :

public void clearAllProperties() {
System.getProperties().clear();
}

3.6. Доступ к переменным среды

Система также предоставляет доступ только для чтения к переменным среды с помощью getenv .

Например, если мы хотим получить доступ к переменной среды PATH , мы можем сделать:

public String getPath() {
return System.getenv("PATH");
}

3.7. Управление сборкой мусора

Как правило, усилия по сборке мусора непрозрачны для наших программ. Однако иногда мы можем захотеть сделать прямое предложение JVM.

System.runFinalization — это метод, который позволяет нам предложить JVM выполнить процедуру финализации.

System.gc — это метод, который позволяет нам предложить JVM запустить процедуру сборки мусора.

Поскольку контракты этих двух методов не гарантируют, что завершение или сборка мусора будут выполняться, их полезность ограничена.

Однако их можно использовать как оптимизацию, например, вызывать gc , когда настольное приложение свернуто:

public void windowStateChanged(WindowEvent event) {
if ( event == WindowEvent.WINDOW_DEACTIVATED ) {
System.gc(); // if it ends up running, great!
}
}

Чтобы узнать больше о финализации, ознакомьтесь с нашим руководством по финализации .

4. Вывод

В этой статье мы познакомились с некоторыми полями и методами , предоставляемыми системой . Полный список можно найти в официальной документации Системы .

Кроме того, ознакомьтесь со всеми примерами в этой статье на Github .