¿Cuál es el Throwable preferido para usar en un constructor de la clase utilidad privada?

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

  •  29-08-2019
  •  | 
  •  

Pregunta

Effective Java (Segunda Edición) , punto 4, discute el uso de constructores privados a cumplir noninstantiability. Aquí está el ejemplo de código del libro:

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

Sin embargo, AssertionError no parece ser lo correcto para lanzar. Nada está siendo "afirmado", que es como la API define el uso de AssertionError .

¿Hay una Throwable diferente que es típicamente en esta situación? ¿Uno por lo general sólo un tiro de un Exception general, con un mensaje? O es común escribir un Exception personalizado para esto?

Es bastante trivial, pero más que nada supongo que soy sólo curiosidad al respecto desde una perspectiva de estilo y estándares.

¿Fue útil?

Solución

Hay una afirmación: "Estoy afirmando que este constructor no se llamará". Así que, de hecho, AssertionError es correcto en este caso.

Otros consejos

Me gusta que incluye el comentario de Bloch:

// Suppress default constructor for noninstantiability

O todavía mejor ponerlo en el error:

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

UnsupportedOperationException suena como la mejor en forma, a través de una excepción comprobada sería aún mejor, ya que podría advertir a alguien erróneamente crear instancias de la clase en tiempo de compilación.

¿Qué hay de IllegalAcessError ? :)

No no no, con el debido respeto a Josh Bloch, Nunca arroje un AssertionError a menos que sea a partir de una afirmación. Si desea una AssertionError aquí, a la basura con assert(false). Entonces alguien que lee el código puede encontrarlo más tarde.

Aún mejor, definir su propia excepción, dicen CantInstantiateUtilityClass. entonces tendrá código que dice

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

para que el lector del receptor sabe lo sucedió.

Actualizar

De vez en cuando algún idiota se pasea por aquí y downvotes esto otra vez, casi cuatro años después del hecho. Por lo tanto, permítanme señalar que la norma Todavía define AssertionError como el resultado de una aserción fallida, no como lo que piense un poco de principiante debéis para ser lanzado en lugar de un bien excepción informativa definida. Lamentablemente, una buena disciplina excepción es quizás la habilidad menos alentado en programación Java.

Cuando el código requiere la inclusión de la JUnit como una dependencia tal como dentro del alcance <scope>test</scope> prueba experto, a continuación, ir directamente a Assertion.fail() método y beneficiarse de una mejora significativa en la claridad.

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

Cuando esté fuera del alcance de prueba, usted podría utilizar algo como lo siguiente, lo que requeriría una importación estática para el uso como la de arriba. 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
    }
}

Lo que el siguiente uso.

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

En su forma más idiomática, todas se reducen a esto:

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

Uno de los incorporados en las excepciones, UnsupportedOperationException puede ser arrojado a indican que 'la operación solicitada no es compatible'.

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

Una afirmación rota significa que usted ha roto una especificación del contrato de su código. Por lo que es lo correcto.

Sin embargo, como supongo podrás crear instancias de una instancia privada, sino que también llamar al constructor de errores y causar una menos que tenga otro constructor?

Usted puede crear su propia Throwable extender la clase, por ejemplo:.

class NoninstantiabilityError extends Throwable

Esto tiene las siguientes ventajas:

  • El nombre indica que el problema
  • Debido a que se extiende directamente Throwable es poco probable que será capturado por accidente
  • Debido a que se extiende directamente Throwable se comprueba y llamando al constructor respectiva por accidente requeriría agarrar la excepción

Ejemplo de uso:

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

    ...
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top