As instâncias do Java 8 Stream devem sempre estar próximas ()?

12

O Javadoc :

Os fluxos têm um método BaseStream.close () e implementam o AutoCloseable, mas quase todas as instâncias do fluxo não precisam ser fechadas após o uso. Geralmente, apenas os fluxos cuja origem é um canal de E / S (como os retornados por Files.lines (Path, Charset)) exigirão o fechamento. A maioria dos fluxos é apoiada por coleções, matrizes ou funções de geração, que não requerem gerenciamento de recursos especiais. (Se um fluxo exigir fechamento, ele poderá ser declarado como um recurso em uma instrução try-with-resources.)

"Quase todos" e "geralmente" são vagos - se você está escrevendo uma biblioteca e abstraindo a fonte do seu Stream dos usuários desse Stream, então você sempre precisa se perguntar: "devo fechar esta?" Os Streams apoiados por IO precisam ser fechados porque as operações do terminal não chamam close; portanto, efetivamente eu sempre tenho que lembrar / documentar de onde meu Stream vem, ou sempre tenho que closefazê - lo.

A opção nuclear, eu acho, seria não retornar o Streams dos métodos ou aceitar os parâmetros do Stream, que é um sentimento que foi ecoado por algumas pessoas na equipe do JDK. Acho que isso é excessivamente limitante, considerando a utilidade prática do Streams.

Quais são suas práticas recomendadas para fechar o Streams? Procurei on-line uma resposta para isso de algumas pessoas do JDK que geralmente são ativas em questões semelhantes da comunidade, mas não encontraram nada relevante.

RuslanD
fonte
Não sou desenvolvedor Java, mas eu usaria essas regras: - Se um fluxo for passado como argumento, documente que o chamador deve fechar o fluxo, se necessário; - Se o fluxo lhe retornar de uma função, suponha que você precise fechá-lo.
Bart van Ingen Schenau

Respostas:

6

Como você disse, em Java, você precisa saber exatamente quem é responsável por liberar qual recurso, para poder colocar as construções try-catch-construct, try-with-resources apropriadas ou, de alguma forma, delegar essa tarefa.

A única coisa em que você pode confiar no GC para limpar é 100% de memória pura.
Se não pode haver alguns outros recursos misturados, a única coisa que você pode razoavelmente fazer é simplesmente jogar pelo seguro.

Desduplicador
fonte
Então, basicamente, closeé a única alternativa segura? Acho que a questão é como não fazer o código parecer muito feio toda vez que um Stream for útil.
Rússia
1
Sim, se não pode ser recursos não-memória, a única coisa segura a fazer é assumir que não são . Não há maneira de contornar isso, mesmo que o Java seja muito inadequado para recursos que não sejam da GC.
Deduplicator
Portanto, se for apenas um fluxo entre duas coleções (memória pura), não será necessário fechá-lo?
Amalgovinus
@Amalgovinus correct #
Brad Cupit
5

No que diz respeito às "melhores práticas", acho uma boa idéia usar uma convenção de nomenclatura para métodos que retornam "fluxos de recursos".

Se um fluxo precisar ser close()editado, chame o método de fábrica open()ou openStream(). Chame métodos que constroem fluxos efêmeros stream(), seguindo a convenção estabelecida pelo SDK. Sempre coloque o javadoc no método para alertar o cliente que ele deve close().

public interface StreamingServer<RECORD> {
    /** 
     * Return a memory-efficient record stream from {@code source}.
     * Clients <em>must</em> call {@link Stream#close} to dispose the
     * stream.
     */
    Stream<RECORD> openStream(URI source) throws IOException;
}

Eu gostaria que os autores do SDK não tivessem escolhido colocar AutoCloseablena classe de fluxo base. Um ResourceStreamsubtipo distinto , que trivialmente implementa AutoCloseable, tornaria óbvios os diferentes contratos. Então você não poderia fechar um Streamque não precisava, e você poderia detectar potencialmente mal gerenciado ResourceStreamem ferramentas de análise estática.

Dependendo das necessidades da sua base de código (e da sua capacidade de impor convenções na revisão de código), você pode estabelecer uma subclasse de fluxo exigida por você mesmo. Ou se você deseja criar suas próprias ferramentas de análise estática, uma anotação de método que marca diretamente os recursos gerenciados.

@RequiresClose
Stream<RECORD> openStream(URI source) throws IOException { ... }
Jason Trump
fonte