Pergunta

Ryan Delucchi perguntou aqui no comentário # 3 a resposta Tom Hawtin 's:

porque é Class.newInstance () "mal"?

este em resposta à amostra de código:

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

então, por que é mal?

Foi útil?

Solução

A documentação da API Java explica por que ( http://java.sun.com/javase/6/docs/api/java/lang/Class.html#newInstance () ):

Note que este método propaga qualquer exceção lançada pelo construtor nullary, incluindo uma exceção verificada. O uso deste método ignora efetivamente a verificação de exceção em tempo de compilação que seriam realizadas pelo compilador. O método Constructor.newInstance evita este problema envolvendo qualquer exceção lançada pelo construtor em um InvocationTargetException (marcada).

Em outras palavras, ele pode derrotar o sistema de exceções verificadas.

Outras dicas

Mais uma razão:

IDEs modernos permitem que você encontrar usos de classe -. Ajuda durante a refatoração, se você e seu IDE saber o que o código está usando classe que você pretende mudar

Quando você não fizer um uso explícito do construtor, mas o uso Class.newInstance () em vez disso, você corre o risco de não achar que o uso durante a refatoração e este problema não vai se manifestar quando você compilar.

Eu não sei por que ninguém forneceu um exemplo simples baseado explicação para isso, em comparação com Constructor::newInstance por exemplo, desde finalmente Class::newInstance foi reprovado desde o java-9.

Suponha que você tenha essa classe muito simples (não importa que ele está quebrado):

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

E você tentar criar uma instância dele através de reflexão. Primeiro Class::newInstance:

    Class<Foo> clazz = ...

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

Chamar isso irá resultar em um IOException ser jogado -. Problema é que seu código não lidar com isso, nem handle 1 nem handle 2 vai pegá-lo

Em contraste ao fazê-lo através de um 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();
    }

que pega 3 será chamado, assim você vai lidar com isso.

Efetivamente, Class::newInstance ignora o tratamento de exceção -. Que você realmente não quer

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top