Was ist die bevorzugte Throwable in einer privaten Utility-Klasse Konstruktor zu benutzen?

StackOverflow https://stackoverflow.com/questions/398953

  •  29-08-2019
  •  | 
  •  

Frage

Effective Java (Second Edition) , Punkt 4, bespricht mit privaten Konstruktoren erzwingen noninstantiability. Hier ist der Code Probe aus dem Buch:

public final class UtilityClass {
    private UtilityClass() {
        throw new AssertionError();
    }
}

Allerdings AssertionError scheint nicht, wie das Richtige zu werfen. Nichts ist „behauptet“ ist, das ist, wie die API die Verwendung von AssertionError .

Gibt es eine andere Throwable die in dieser Situation normalerweise ist? Hat man in der Regel nur eine allgemeine Exception mit einer Botschaft werfen? Oder ist es üblich, eine benutzerdefinierte Exception für diese zu schreiben?

Es ist ziemlich trivial, aber mehr als alles, was ich denke, ich, wenn ich nur neugierig bin von einem Stil und Standards Perspektive.

War es hilfreich?

Lösung

Es ist eine Behauptung: „Ich bin zu behaupten, dass dieser Konstruktor wird nie genannt werden“. Also, in der Tat, AssertionError ist richtig hier.

Andere Tipps

Ich mag einschließlich Blochs Kommentar:

// Suppress default constructor for noninstantiability

Oder noch besser in den Fehlern setzen:

private UtilityClass()
{
    throw new AssertionError("Suppress default constructor for noninstantiability");
}

UnsupportedOperationException klingt wie die beste fit, wenn eine geprüfte Ausnahme wäre noch besser, da es jemand fälschlicherweise instanziieren die Klasse bei der Kompilierung warnen könnte.

Nein, nein, nein, mit Verlaub zu Josh Bloch, nie eine AssertionError werfen, wenn es von einer Behauptung ist. Wenn Sie einen AssertionError hier wollen, werfen Sie es mit assert(false). Dann hat jemand den Code lesen kann es später finden.

Noch besser ist, definieren Sie Ihre eigene Ausnahme, sagt CantInstantiateUtilityClass. dann werden Sie Code haben, der sagt

try {
    // some stuff
} catch (CantInstantiateUtilityClass e) {
    // react
}

, so dass der Leser des Fängers weiß was passiert ist.

Aktualisieren

Jeder so oft einige verdammter Narr wandert von hier und diese wieder downvotes, fast vier Jahre nach der Tat. Also, lassen Sie mich nur beachten Sie, dass die Standard- noch AssertionError als Ergebnis einer verfehlten Behauptung definiert, nicht als das, was einige Anfänger denkt sollte anstelle eines gut geworfen werden definiert informative Ausnahme. Leider Disziplin gut Ausnahme ist vielleicht die am wenigsten ermutigt Geschick in Java-Programmierung.

Wenn der Code die Aufnahme des JUnit als eine Abhängigkeit wie im <scope>test</scope> Maven Prüfumfang erfordert, dann geradeaus gehen Methode und profitieren von signifikanten Verbesserung der Klarheit Assertion.fail().

public final class UtilityClass {
    private UtilityClass() {
        fail("The UtilityClass methods should be accessed statically");
    }
}

Wenn außerhalb des Testumfang, könnten Sie so etwas wie die folgenden verwenden, die einen statischen Import erfordern würden, wie oben zu verwenden. import static pkg.Error.fail;

public class Error {
    private static final Logger LOG = LoggerFactory.getLogger(Error.class);
    public static void fail(final String message) {
        LOG.error(message);
        throw new AssertionError(message);
        // or use your preferred exception 
        // e.g InstantiationException
    }
}

Welche die folgende Nutzung.

public class UtilityClassTwo {
    private UtilityClassTwo() {
        Error.fail("The UtilityClass methods should be accessed statically");
    }
}

In seiner idiomatischen Form, sie alle dazu einkochen:

public class UtilityClassThree {
    private UtilityClassThree() {
        assert false : "The UtilityClass methods should be accessed statically";
    }
}

Einer der eingebauten Ausnahmen können UnsupportedOperationException zu werfen zeigen an, dass ‚die angeforderte Operation nicht unterstützt wird.‘

 private Constructor() {
    throw new UnsupportedOperationException(
            "Do not instantiate this class, use statically.");
}

Eine gebrochene Behauptung bedeutet, dass Sie einen Vertrag Spezifikation des Codes gebrochen haben. So ist es das Richtige ist hier.

Aber, wie ich nehme an, Sie werden privat sein, eine Instanz instanziiert wird, wird es auch den Konstruktor aufrufen und eine fehler- verursachen, wenn Sie einen anderen Konstruktor haben?

Sie können Ihre eigene Klasse erweitern Throwable, z erstellen.

class NoninstantiabilityError extends Throwable

Dies hat folgende Vorteile:

  • Der Name zeigt an, das Problem
  • Weil es Throwable direkt erstreckt es ist unwahrscheinlich, dass es durch Zufall gefangen werden
  • Da es sich direkt Throwable geprüft wird, und den jeweiligen Konstruktor durch Zufall Aufruf erfordern würde die Ausnahme abfangen

Anwendungsbeispiel:

public final class UtilityClass {
    private UtilityClass() throws NoninstantiabilityError {
        throw new NoninstantiabilityError();
    }

    ...
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top