2009-08-14 3 views
6

Desidero che l'API del mio modulo sollevi MyPackageSpecificException ogni volta che qualcosa va storto e il modulo non è in grado di eseguire il suo compito. (L'eccezione originale verrà indicata come causa di MyPackageSpecificException).Avvolgimento di eccezioni generate in super/questo costruttore chiama in altre eccezioni

Ora, per un costruttore, avevo bisogno di un URL come parametro per localizzare una risorsa. Vorrei anche fare un costruttore di un'alternativa al quale può essere data una rappresentazione di stringa del URL:

public MyClass(String urlString) throws MalformedURLException{ 
    this(new URL(urlString)); 
} 

Come il costruttore URL getta MalformedURLException, voglio avvolgerla in un MyPackageSpecificException facendo:

public MyClass(String urlString) throws MyPackageSpecificException{ 
    try{ 
     this(new URL(urlString)); 
    } catch (MalformedURLException e){ 
     throw new MyPackageSpecificException(e); 
    } 
} 

Tuttavia, quanto sopra non è valido, poiché la chiamata del costruttore super() o this() deve essere eseguita sulla prima riga del costruttore.

Lo stesso problema si applica se il costruttore super() o this() genera un'eccezione che voglio racchiudere in qualcos'altro.

Come dovrei risolvere? O è quello che sto cercando di fare cattive pratiche?

risposta

6

Provare quanto segue: Metodo

public class MyClass 
{ 
    private URL url; 

    public MyClass(URL url) 
    { 
    this.url = url; 
    } 

    public MyClass(String urlString) throws MyPackageSpecificException 
    { 
    this(toURL(urlString)); 
    } 

    private static URL toURL(String urlString) throws MyPackageSpecificException 
    { 
    try 
    { 
     return new URL(urlString)); 
    } 
    catch (MalformedURLException e) 
    { 
     throw new MyPackageSpecificException(e); 
    } 
    } 
} 
+0

Non posso credere di non aver pensato a questo. Semplice e fa esattamente quello che voglio. – Alderath

3

Se si inserisce il codice, è possibile utilizzare un metodo creatore statico invece:

private MyClass(String urlString) { ... } 

public static MyClass createMyClass(String urlString) throws MyPackageSpecificException { 
    try { 
    new MyClass(urlString); 
    catch (Exception e) { 
    throw new MyPackageSpecificException(e); 
    } 
} 
+1

Questo in realtà è meglio che la risposta accettata, perché si lavorerà per il caso generico, mentre la risposta accettata funziona solo se è possibile trovare (e "Convert" per) un costruttore della superclasse che non buttare eccezioni indesiderabili. Modello di fabbrica FTW, immagino. – Coderer

0

Invece di utilizzare questo() hanno un init comune() che accetta l'argomento URL in questo modo non è necessario che sia la prima riga del costruttore.

public MyClass(String url) throws MyPackageSpecificException 
{ 
    try 
    { 
    init(new URL(url)); 
    } 
    catch (MalformedURLException e) 
    { 
    throw new MyPackageSpecificException(e); 
    } 
} 

public MyClass(URL url) 
{ 
    init(url); 
} 

private void init(URL url) 
{ 
    // do constructor work here 
} 
+1

Ciò impedisce di assegnare i parametri del costruttore ai campi finali, il che rende più difficile la creazione di classi immutabili. L'assegnazione dei campi finali può essere effettuata solo nel costruttore. –

+0

Essendo una soluzione valida all'esempio che ho postato, questo tuttavia non funziona se l'url deve essere passato a un super costruttore, motivo per cui ho preferito le altre soluzioni. – Alderath