Cosa succede se chiudo un InputStream che viene passato come argomento?

5

Ho letto che Java è un valore pass-by, e ne ho letto in questa domanda su StackOverflow , ma sono ancora un po 'confuso riguardo ai metodi close () o shutdown () in varie classi.

Quello che voglio sapere è, supponiamo che io faccia questo:

public Constructor(){

    if(isProceeding){
        InputStream iStream = new InputStream();
        processStuff(iStream);
    }
}


public void processStuff(InputStream stream){
    //do stuff
    stream.close();
}

La variabile iStream viene effettivamente chiusa nel metodo processStuff () o una sua copia viene chiusa e lo stesso iStream rimane aperto?

    
posta Raestloz 17.07.2014 - 12:21
fonte

2 risposte

11

Gli oggetti passati ad altri metodi possono essere modificati dal metodo e il chiamante noterà la modifica. Se lasci che qualcun altro usi il tuo Stream , potrebbero chiuderlo e non te ne accorgeresti mai fino a quando non proverai a scrivere e fallire. Ecco perché di solito è una buona idea non passare oggetti mutabili fuori dal tuo controllo.

La confusione si verifica spesso perché molti libri di testo dicono categoricamente che "Java ha una semantica pass-by-value". Ciò è tecnicamente vero, ma non molto utile per uno studente di lingue. Tecnicamente , non è l'oggetto che viene passato in giro ma un riferimento a un oggetto, e il metodo chiamato ottiene una copia del riferimento, che ovviamente fa riferimento allo stesso oggetto .

Ma in pratica, la differenza tra riferimento a oggetti e oggetti spesso non è chiara nelle menti delle persone. Nessuno è mai interessato al valore di un riferimento se non quello di verificare se è null . Infatti, Java non ha nemmeno ha una sintassi di dereferenziamento a parte il selettore di membri . . Ciò che interessa alla gente è lo stato dell'oggetto sottostante . Quindi efficace significa che gli oggetti mutabili sono passati per riferimento nel senso che il chiamante può cambiarli, e tu potresti esserne influenzato. In questo senso, la spiegazione del manuale è corretta e utile per i tipi primitivi, ma corretta e fuorviante per i tipi di oggetto.

    
risposta data 17.07.2014 - 12:31
fonte
1

Nel tuo esempio, iStream viene effettivamente chiuso in processStuff (), non una copia. Raccomanderei comunque di chiudere sempre InputStream nello stesso metodo in cui lo hai creato, altrimenti è difficile capire se è chiuso o no. La chiamata a close () dovrebbe essere in una clausola {...} finally in modo tale che di sicuro viene chiamata, anche se viene generata un'eccezione, come questa:

package org.company;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;

public class Test1 {

    private boolean isProceeding;

    public Test1() {
    }

    public void init(String str) throws IOException {
        if(isProceeding){
            InputStream iStream = null;
            try {
                iStream = new ByteArrayInputStream(str.getBytes("UTF-8"));
                processStuff(iStream);

            } finally {
                iStream.close();
            }
        }
    }

    public void processStuff(InputStream stream){
        //do stuff
    }

    public boolean isProceeding() {
        return isProceeding;
    }

    public void setProceeding(boolean isProceeding) {
        this.isProceeding = isProceeding;
    }

}
    
risposta data 17.07.2014 - 23:53
fonte

Leggi altre domande sui tag