2016-07-27 7 views
3

Es gibt eine Übung von Denken in Java:Ist das die richtige Übungslösung?

eine Klasse FailingConstructor mit einem Konstruktor aufgerufen erstellen, die scheitern könnte teilweise durch den Bauprozess und eine Ausnahme werfen. Geben Sie unter main() einen Code ein, der diesen Fehler ordnungsgemäß verhindert.

Das ist meine Lösung ist:

class E1 extends Exception { 
    private FailingConstructor f; 
    E1(FailingConstructor f) { this.f = f; } 
    FailingConstructor getF() { return f; } 
} 

class FailingConstructor { 
    private Integer value; 
    FailingConstructor(int i) throws E1 { 
     if (i < 0) throw new E1(this); 
     value = i; 
    } 
    void set(int value) { this.value = value; } 
    public String toString() { return value.toString(); } 
} 

public class Program { 
    public static void main(String[] args) { 
     try { 
      FailingConstructor f2 = new FailingConstructor(-11); 
     } catch (E1 e) { 
      e.getF().set(0); 
      System.out.println(e.getF()); 
     } 
    } 
} 

Könnten Sie mir bitte sagen, das ist die richtige Übung Lösung? Lösung, die ich gefunden habe (here) sieht ziemlich seltsam und unlogisch aus und ich denke, dass meine Lösung besser ist als das.

+2

scheinen beide gut. In Ihrer Lösung wird eine benutzerdefinierte Ausnahme ausgelöst, wenn die von Ihnen implementierte Validierung fehlschlägt. Im anderen Beispiel wird eine ArrayIndexOutOfBoundsException ausgelöst, weil sie versuchen, ein drittes Element in einem Array mit zwei Elementen zu speichern. – Stultuske

+0

Ich bin nicht sicher, dass 'e.getF(). Set (0);' eine korrekte Möglichkeit ist, diese Ausnahme zu behandeln. Wenn es im Konstruktor andere Initialisierungsanweisungen gäbe, die wegen der Ausnahme niemals aufgerufen worden wären, könnte das Objekt in einem undefinierten/unerwarteten Zustand sein. Außerdem wäre 'f2' immer noch null, da die Zuweisung nicht stattgefunden hat. Ich würde lieber eine neue Instanz mit einem korrekten Wert erstellen, anstatt die fehlgeschlagene erneut zu verwenden. – Thomas

+3

Der Verweis auf die teilweise konstruierte Instanz über das 'neue E1 (this)' ist eine * schreckliche * Idee. Schließlich können Sie 'e.getF(). Set (-1)' aufrufen und anschließend die Instanz verwenden - und genau dafür wird die Ausnahme ausgelöst. –

Antwort

6

Das Übergeben eines Verweises der halb konstruierten Instanz an den Konstruktor der Ausnahme scheint mir eine schlechte Idee zu sein.

Und die Mutation dieser Instanz in der catch-Klausel hat keinen Zweck, da der Code nach der Ausführung der catch-Klausel sowieso keinen Verweis auf diese Instanz enthält. Die catch-Klausel sollte entweder melden, dass eine Ausnahme aufgetreten ist (eine Fehlermeldung oder Stack-Trace ausgeben), ggf. eine abweichende Ausnahme auslösen oder - wenn properly guards against this failure bedeutet, dass die erfolgreiche Erstellung einer Instanz sichergestellt sein muss - eine neue Instanz erstellen von FailingConstructor, deren Erstellung garantiert keine Ausnahme auszulösen. Wenn Sie den letzten Ansatz wählen, sollten Sie die FailingConstructor-Variable vor dem try-Block deklarieren, damit sie nach dem try-catch-Block im Gültigkeitsbereich bleibt.

public class Program { 
    public static void main(String[] args) { 
     FailingConstructor f2 = null; 
     try { 
      f2 = new FailingConstructor(-11); 
     } catch (E1 e) { 
      f2 = new FailingConstructor(); // one way to recover from the exception 
              // is to use a different constructor 
              // that doesn't throw an exception 
     } 
     // now you can access f2 
    } 
} 
+0

Sind Sie sicher, dass eine Variable zu deklarieren, bevor der try-Block eine gute Idee ist? Konstruktor kann die ungeprüfte Ausnahme auslösen – luckystrrrike

+0

@luckystrrrike Wenn der Konstruktor die Ausnahme auslöst und die Variable nicht initialisiert wird, bleibt sie null (vorausgesetzt, Sie setzen sie auf null, wenn Sie sie deklarieren). Sie müssen es vor dem try-Block deklarieren, wenn Sie außerhalb des try-Blocks darauf zugreifen wollen. – Eran

+0

aber IDE erlaubt dies nicht zu tun - es sagt 'Unhandled Ausnahme' P.S. im ersten Kommentar meinte ich 'unbehandelt' – luckystrrrike

2

den Verweis auf die teilweise aufgebauten Instanz über die throw new E1(this) Undichte ist schlecht beraten.

Sie können e.getF().set(-1) anrufen, und verwenden Sie die Instanz danach - das ist genau das, was gegen die Ausnahme geworfen wird.

Es gibt kein Problem mit dem Auslösen einer Ausnahme - das Problem ist der Verweis auf FailingConstructor, mit dem es erstellt wird. Entfernen Sie diese (und die Methode usw.), und es ist in Ordnung.

+0

Dies ist ein Beispiel für Studie, können Sie einen beliebigen Wert nach dem Erstellen, aber die wesentliche Bedingung ist es, nicht eine Instanz mit einem negativen Wert – luckystrrrike

+2

machen Richtig - aber mein Punkt ist, dass Sie * kann * eine Instanz mit einem negativen Wert erzeugen, indem man 'e.getF(). set (-1)' aufruft. –

Verwandte Themen