Почему компилятор Java позволяет повторно использовать поток? - PullRequest
0 голосов
/ 21 апреля 2020

Давайте представим следующий код:

Stream<Integer> numberStream = ...;

Predicate<Integer> isEven = ...;
Predicate<Integer> isOdd = ...;

List<Integer> evenNumbers = numberStream
    .filter(isEven)
    .collect(Collectors.toList());

List<Integer> oddNumbers = numberStream 
    .filter(isOdd)
    .collect(Collectors.toList()); // this line will throw IllegalStateException

Приведенный выше код компилируется без каких-либо предупреждений. Однако попытка запустить его всегда приведет к IllegalStateException.

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

Мне кажется, что это будет очень легко обнаружить компилятором. Почему он компилируется без ошибок? Есть ли какой-то случай, когда подобный код будет полезен?

1 Ответ

2 голосов
/ 21 апреля 2020

Компилятор в некотором смысле прост.

Он проверяет, что ваш код допустим в соответствии с правилами языка Java и что все ваши вызовы соответствуют правилам и типу языка Java система требует.

Ни правило языка , ни система типов как-то не "кодирует", что Stream не может быть повторно использовано. Это просто факт, о котором компилятор не знает.

Думайте о потоках как о предметно-ориентированном c языке, построенном поверх Java. Компилятор знает только нижний «Java» уровень этой концепции, но не понимает правил «языка» потоков более высокого уровня.

Так что пока компилятор может можно сказать о правилах этого специфического c языка, это опасный путь к go, потому что существует много, много доменных спецификаций c языков, подобных тем, которые можно было бы предположительно проверить и сделать их правильно ... маловероятно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...