Domanda

Sono stato sorpreso di recente per scoprire che è possibile avere un ritorno economico in un blocco finally in Java.

Sembra che un sacco di persone pensano che sia una brutta cosa da fare, come descritto in 'Non tornare in una clausola finally'.Grattando un po 'di più, ho anche trovato"Java ritorno non sempre'che mostra alcuni piuttosto orribile esempi di altri tipi di controllo di flusso finalmente blocchi.

Allora la mia domanda è, qualcuno mi può dare un esempio in cui un ritorno economico (o di altri controllo di flusso) in un blocco finally produce di meglio / più leggibile il codice?

È stato utile?

Soluzione

Gli esempi che hai fornito sono una ragione sufficiente per non utilizzare il controllo di flusso da finalmente.

Anche se c'è un esempio artificioso in cui è "meglio", prendere in considerazione lo sviluppatore che ha per mantenere il codice più tardi e che potrebbe non essere a conoscenza di sfumature.Che il povero sviluppatore potrebbe anche essere....

Altri suggerimenti

Ho avuto un momento DAVVERO difficile rintracciare un bug anni fa, che è stato causato da questo.Il codice è stato qualcosa di simile a:

Object problemMethod() {
    Object rtn = null;
    try {
        rtn = somethingThatThrewAnException();
    }
    finally {
        doSomeCleanup();
        return rtn;
    }
}

Quello che è successo è che l'eccezione è stato buttato giù in un altro codice.È stato catturato e registrato e rigenerata entro il somethingThatThrewAnException() metodo.Ma l'eccezione non essere propagate passato problemMethod().Dopo un LUNGO tempo di guardare questo abbiamo finalmente rintracciato giù per il ritorno del metodo.Il ritorno di metodo nel blocco finally era fondamentalmente fermare l'eccezione che è accaduto nel blocco try propagazione anche se non è stato catturato.

Come hanno detto gli altri, mentre è legale, di ritorno da un blocco finally secondo il Java spec, è una BRUTTA cosa, e non dovrebbe essere fatto.

javac avvisa del ritorno, infine, se si utilizza il-Xlint:finalmente.Originariamente javac emesso nessun avviso - se c'è qualcosa di sbagliato con il codice, dovrebbe fallire per la compilazione.Purtroppo la compatibilità significa che imprevisti geniale follia non può essere vietato.

Eccezioni possono essere generate da finalmente blocchi, ma in questo caso esposto, il comportamento è quasi certamente quello che vuoi.

L'aggiunta di strutture di controllo e restituisce finalmente di{} blocchi sono solo un altro esempio di "solo perché si può" abusi, che sono sparsi in tutto praticamente tutti i linguaggi di sviluppo.Jason è giusto suggerendo che potrebbe facilmente trasformarsi in un incubo nella manutenzione - gli argomenti contro l'torna presto da funzioni si applicano di più-quindi per questo caso di "restituzioni".

Infine blocchi esistono per uno scopo ben preciso, che consente di ripulire dopo di te stesso, non importa quello che è successo in tutto il codice precedente.Principalmente si tratta di chiusura e rilascio di puntatori di file, connessioni di database ecc.... anche se ho potuto vedere che è teso a dire in aggiunta su misura di controllo.

Tutto ciò che riguarda il ritorno della funzione dovrebbe risiedere nella try{} blocco.Anche se si ha un metodo con cui è verificata una esterna dello stato, ha fatto un operazione che richiede molto tempo, poi controllato che stato nuovo nel caso in cui esso non è più valido, si vuole ancora il secondo controllo all'interno del try{} - se si trovava all'interno, infine, {} e la lunga operazione non riuscita, si sarebbe quindi verifica stato un secondo tempo inutilmente.

Un semplice Groovy Test:

public class Instance {

  List<String> runningThreads = new ArrayList<String>()

  void test(boolean returnInFinally) {

    println "\ntest(returnInFinally: $returnInFinally)"
    println "--------------------------------------------------------------------------"
    println "before execute"
    String result = execute(returnInFinally, false)
    println "after execute -> result: " + result
    println "--------------------------------------------------------------------------"

    println "before execute"
    try {
      result = execute(returnInFinally, true)
      println "after execute -> result: " + result
    } catch (Exception ex) {
      println "execute threw exception: " + ex.getMessage()
    }  
    println "--------------------------------------------------------------------------\n"

  }

  String execute(boolean returnInFinally, boolean throwError) {
      String thread = Thread.currentThread().getName()
      println "...execute(returnInFinally: $returnInFinally, throwError: $throwError) - thread: $thread"
      runningThreads.add(thread)
      try {
        if (throwError) {
          println "...error in execute, throw exception"
          throw new Exception("as you liked :-)")
        }
        println "...return 'OK' from execute"
        return "OK"
      } finally {
        println "...pass finally block"
        if (returnInFinally) return "return value from FINALLY ^^"
        // runningThreads.remove(thread)
      }
  }
}

Instance instance = new Instance()
instance.test(false)
instance.test(true)

Output:

test(returnInFinally: false)
-----------------------------------------------------------------------------
before execute
...execute(returnInFinally: false, throwError: false) - thread: Thread-116
...return 'OK' from execute
...pass finally block
after execute -> result: OK
-----------------------------------------------------------------------------
before execute
...execute(returnInFinally: false, throwError: true) - thread: Thread-116
...error in execute, throw exception
...pass finally block
execute threw exception: as you liked :-)
-----------------------------------------------------------------------------


test(returnInFinally: true)
-----------------------------------------------------------------------------
before execute
...execute(returnInFinally: true, throwError: false) - thread: Thread-116
...return 'OK' from execute
...pass finally block
after execute -> result: return value from FINALLY ^^
-----------------------------------------------------------------------------
before execute
...execute(returnInFinally: true, throwError: true) - thread: Thread-116
...error in execute, throw exception
...pass finally block
after execute -> result: return value from FINALLY ^^
-----------------------------------------------------------------------------

Domanda:

Un punto interessante per me è stato vedere come Groovy tratta implicita restituisce.In Groovy è possibile "ritorno" di un metodo semplicemente lasciando un valore e alla fine (senza ritorno).Che cosa pensi che succeda, se è il commento del runningThreads.rimuovere(..) linea nell'infine istruzione - sarà questo sovrascrivere il normale valore di ritorno ("OK") e coprire l'eccezione?!

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top