2009-09-03 21 views

risposta

324

Sì, i costruttori possono generare eccezioni. Di solito questo significa che il nuovo oggetto è immediatamente idoneo per la garbage collection (sebbene non possa essere raccolto per qualche tempo, ovviamente). È possibile che l'oggetto "semi-costruito" rimanga bloccato, se viene reso visibile in precedenza nel costruttore (ad esempio assegnando un campo statico o aggiungendosi a una raccolta).

Una cosa da fare attenzione al lancio di eccezioni nel costruttore: poiché il chiamante (di solito) non ha modo di utilizzare il nuovo oggetto, il costruttore deve fare attenzione ad evitare l'acquisizione di risorse non gestite (handle di file ecc.) E quindi lanciare un'eccezione senza rilasciarli. Ad esempio, se il costruttore tenta di aprire un FileInputStream e un FileOutputStream e il primo riesce ma il secondo non riesce, provare a chiudere il primo flusso. Questo diventa più difficile se si tratta di un costruttore sottoclasse che lancia l'eccezione, ovviamente ... tutto diventa un po 'complicato. Non è un problema molto spesso, ma vale la pena considerare.

+25

+1. Di solito nessuno pensa alle eccezioni lanciate dalle sottoclassi. –

+1

@JonSkeet: ** Puoi darci qualche esempio di codice su ** * se è reso visibile in precedenza nel costruttore (ad esempio assegnando un campo statico o aggiungendo se stesso a una raccolta). *? – Tarik

+3

@Tarik: beh, l'esempio di codice dovrebbe fare esattamente questo - ad es. 'someStaticField = this;' o 'someCollection.add (this)' all'interno di un costruttore. –

31

Assolutamente.

Se il costruttore non riceve input validi o non può costruire l'oggetto in modo valido, non ha altra opzione se non generare un'eccezione e avvisare il chiamante.

7

Sì.

I costruttori non sono altro che metodi speciali e possono generare eccezioni come qualsiasi altro metodo.

+0

La cosa importante nella tua affermazione è "metodi speciali". Quindi non sono come nessun altro metodo. Lanciare un'eccezione da un costruttore di classe non finalizzato ** potrebbe ** creare un buco di sicurezza, quindi è necessario prestare particolare attenzione quando si decide di farlo. Vedere la risposta di @Billy sopra, con l'estratto delle Linee guida per la codifica sicura di Java. –

11

Sì, i costruttori possono rilasciare eccezioni.

Tuttavia, è molto saggio scegliere quali eccezioni dovrebbero essere: controllate le eccezioni o deselezionate. Le eccezioni non controllate sono fondamentalmente sottoclassi di RuntimeException.

In quasi tutti i casi (non sono riuscito a trovare un'eccezione in questo caso), è necessario generare un'eccezione controllata. Il motivo è che le eccezioni non controllate (come NullPointerException) sono normalmente dovute a errori di programmazione (come la mancata convalida degli input).

Il vantaggio offerto da un'eccezione verificata è che il programmatore è costretto a rilevare l'eccezione nel suo codice di istanziazione e in questo modo si rende conto che non è possibile creare un'istanza dell'oggetto. Naturalmente, solo una revisione del codice catturerà la scarsa pratica di programmazione di deglutire un'eccezione.

76

Sì, possono generare eccezioni. Se è così, saranno solo parzialmente inizializzati e se non definitivi, soggetti ad attacco.

Quanto segue è il Secure Coding Guidelines 2.0.

È possibile accedere a istanze parzialmente inizializzate di una classe non finalizzata tramite un attacco finalizzatore. L'utente malintenzionato esegue l'override del metodo finalize protetto in una sottoclasse e tenta di creare una nuova istanza di tale sottoclasse. Questo tentativo non riesce (nell'esempio precedente, il controllo SecurityManager nel costruttore di ClassLoader genera un'eccezione di sicurezza), ma l'utente malintenzionato ignora semplicemente qualsiasi eccezione e attende che la macchina virtuale esegua la finalizzazione sull'oggetto parzialmente inizializzato. Quando ciò si verifica, viene invocata l'implementazione del metodo finalize malevolo, che consente all'utente malintenzionato di accedere a questo riferimento, un riferimento all'oggetto da finalizzare. Sebbene l'oggetto sia solo parzialmente inizializzato, l'utente malintenzionato può comunque richiamare i metodi su di esso (aggirando quindi il controllo di SecurityManager).

+1

Questo significa che il lancio da una classe non definitiva è una violazione della sicurezza? È ancora un problema? – kroiz

+1

Si noti che questa linea guida è rilevante solo se il proprio codice è o è probabile che venga utilizzato in un contesto in cui la sicurezza è importante. Ad esempio, la maggior parte del codice Java viene utilizzata in contesti in cui non è presente SecurityManager. –

0

Un costruttore può lanciare qualsiasi eccezione. Ma se un costruttore di sottoclasse chiama un costruttore super-classe che genera un'eccezione, allora il costruttore della sottoclasse deve catturare l'eccezione o lanciarlo.

+8

Un costruttore di sottoclasse non può rilevare un'eccezione, poiché l'utilizzo di un blocco try prima di super() causerà un errore di compilazione ("call to super deve essere la prima istruzione nel costruttore") –

10

Sì, può generare un'eccezione e si può dichiarare che nella firma del costruttore troppo, come mostrato nell'esempio seguente:

public class ConstructorTest 
{ 
    public ConstructorTest() throws InterruptedException 
    { 
     System.out.println("Preparing object...."); 
     Thread.sleep(1000); 
     System.out.println("Object ready"); 
    } 

    public static void main(String ... args) 
    { 
     try 
     { 
      ConstructorTest test = new ConstructorTest(); 
     } 
     catch (InterruptedException e) 
     { 
      System.out.println("Got interrupted..."); 
     } 
    } 
} 
-1

sì, può generare un'eccezione come altro metodo fa

+1

Grazie mille per questa risposta dettagliata, anche se questa domanda è già stato risposto da post molto migliori. – Tom

Problemi correlati