Каков вариант использования нулевого (входного / выходного) потокового API в Java? - PullRequest
0 голосов
/ 23 ноября 2018

С Java 11 я мог бы инициализировать InputStream как:

InputStream inputStream = InputStream.nullInputStream();

Но я не могу понять потенциальный вариант использования InputStream.nullInputStream или аналогичный API дляOutputStream т.е. OutputStream.nullOutputStream.

Из API Javadocs я мог бы выяснить, что он

Возвращает новый InputStream, который не читает байтов .Возвращенный поток изначально открыт.Поток закрывается путем вызова метода close ().

Последующие вызовы close() не имеют никакого эффекта.Пока поток открыт, методы available(), read(), read(byte[]), ... skip(long) и transferTo() ведут себя так, как будто достигнут конец потока.

Я прошел подробные примечания к выпуску , в которых говорится:

В некоторых случаях я хотел бы использовать методы, которые требуют в качестве параметра целевой OutputStream / Writer для отправкиoutput, но хотел бы выполнить эти методы без вывода сообщений для других их эффектов.

Это соответствует способности в Unix перенаправлять вывод команды в / dev / null или в DOS для добавления вывода команды в NUL.

Тем не менее, я не понимаю, что такое эти методы в выражении, как указано как .... выполняют эти методы молча для других их эффектов .(вините в том, что у меня не хватает практической работы с API)

Может кто-нибудь помочь мне понять, в чем полезность такого потока ввода или вывода с помощью примера, если это возможно?


Редактировать : Одной из похожих реализаций, которую я мог найти при просмотре, является apache-commons 'NullInputStream, который оправдывает вариант использования тестированиянамного лучше.

Ответы [ 3 ]

0 голосов
/ 23 ноября 2018

Я вижу это как более безопасную (1) и более выразительную (2) альтернативу инициализации переменной потока с помощью null.

  1. Не беспокойтесь о NPE.
  2. [Output|Input]Stream - это абстракция.Чтобы возвратить поток null / empty / mock, вам пришлось отклониться от базовой концепции до конкретной реализации.
0 голосов
/ 23 ноября 2018

Я думаю, nullOutputStream очень просто и понятно: просто отбросить вывод (аналогично > /dev/null) и / или для тестирования (не нужно изобретать OutputStream).

An (очевидно,простой примерне содержат никаких данных, или вы не можете доставить, и где null не является приемлемым вариантом:

importer.importDocument("name", /* input stream... */);
InputStream inputStream = content.getInputStream(); // better having no data to read, then getting a null

Когда вы тестируете этот импортер, вы можете просто использовать nullInputStream там, снова вместоизобретать свой собственный InputStream или вместо использования макета.Другие варианты использования здесь скорее похожи на обходной путь или неправильное использование API; -)

Относительно возврата InputStream: это скорее имеет смысл.Если у вас нет никаких данных, вы можете вернуть это nullInputStream вместо null, чтобы вызывающим абонентам не приходилось иметь дело с null, и они могли бы просто читать, как если бы были данные.

Наконец, это просто удобные методы, облегчающие жизнь без добавления другой зависимости ;-) и, как уже говорили другие (комментарии / ответы), это в основном реализация шаблона нулевого объекта .

Использование null*Stream также может иметь преимущество в том, что тесты выполняются быстрее ... если вы выполняете потоковую передачу реальных данных (конечно ... в зависимости от размера и т. Д.), Вы можете просто без необходимости замедлять свои тесты, и мы всехотите, чтобы тесты прошли быстро, верно?(некоторые тут насмехаются ... ну ...)

0 голосов
/ 23 ноября 2018

Иногда вы хотите иметь параметр типа InputStream, но также и иметь возможность не передавать свой код какими-либо данными.В тестах это, вероятно, проще смоделировать, но в производственном процессе вы можете выбрать привязку null input вместо разброса вашего кода с помощью if s и флагов.

сравнение:

class ComposableReprinter {
    void reprint(InputStream is) throws IOException {
        System.out.println(is.read());
    }

    void bla() {
        reprint(InputStream.nullInputStream());
    }
}

с этим:

class ControllableReprinter {
    void reprint(InputStream is, boolean for_real) throws IOException {
        if (for_real) {
            System.out.println(is.read());
        }
    }
    void bla() {
        reprint(new BufferedInputStream(), false);
    }
}

или с этим:

class NullableReprinter {
    void reprint(InputStream is) throws IOException {
        if (is != null) {
            System.out.println(is.read());
        }
    }
    void bla() {
        reprint(null);
    }
}

Это имеет больше смысла с выводом ИМХО.Ввод, вероятно, больше для согласованности.

Этот подход называется Null Object : https://en.wikipedia.org/wiki/Null_object_pattern

...