Pregunta

Ryan Delucchi preguntó aquí en el comentario # 3 a La respuesta de Tom Hawtin :

  

¿por qué es Class.newInstance () " evil " ;?

esto en respuesta a la muestra de código:

// Avoid Class.newInstance, for it is evil.
Constructor<? extends Runnable> ctor = runClass.getConstructor();
Runnable doRun = ctor.newInstance();

entonces, ¿por qué es malo?

¿Fue útil?

Solución

La documentación de la API de Java explica por qué ( http://java.sun.com/javase/6/docs/api/java/lang/Class.html#newInstance () ):

  

Tenga en cuenta que este método propaga cualquier excepción lanzada por el constructor nular, incluida una excepción marcada. El uso de este método omite de manera efectiva la comprobación de excepciones en tiempo de compilación que de lo contrario realizaría el compilador. El método Constructor.newInstance evita este problema envolviendo cualquier excepción lanzada por el constructor en una InvocationTargetException (marcada).

En otras palabras, puede vencer al sistema de excepciones marcadas.

Otros consejos

Una razón más:

Los IDE modernos le permiten encontrar usos de clase: es útil durante la refactorización, si usted y su IDE saben qué código está usando la clase que planea cambiar.

Cuando no hace un uso explícito del constructor, sino que usa Class.newInstance (), corre el riesgo de no encontrar ese uso durante la refactorización y este problema no se manifestará cuando compile.

No sé por qué nadie proporcionó una explicación simple basada en un ejemplo de esto, en comparación con Constructor :: newInstance por ejemplo, ya que finalmente Clase :: newInstance quedó en desuso desde java-9.

Suponga que tiene esta clase muy simple (no importa que esté rota):

static class Foo {
    public Foo() throws IOException {
        throw new IOException();
    }
}

E intentas crear una instancia a través de la reflexión. Primera Class :: newInstance :

    Class<Foo> clazz = ...

    try {
        clazz.newInstance();
    } catch (InstantiationException e) {
        // handle 1
    } catch (IllegalAccessException e) {
        // handle 2
    }

Llamar a esto dará como resultado una IOException : el problema es que su código no lo maneja, ni handle 1 ni handle 2 lo atrapará.

En contraste cuando se hace a través de un Constructor :

    Constructor<Foo> constructor = null;
    try {
        constructor = clazz.getConstructor();
    } catch (NoSuchMethodException e) {
        e.printStackTrace();
    }

    try {
        Foo foo = constructor.newInstance();
    } catch (InstantiationException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (InvocationTargetException e) {
        System.out.println("handle 3 called");
        e.printStackTrace();
    }

ese manejador 3 se llamará, por lo que lo manejará.

Efectivamente, Class :: newInstance omite el manejo de excepciones, que realmente no desea.

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