簡體   English   中英

為什么Class.newInstance()“邪惡”?

[英]Why is Class.newInstance() “evil”?

瑞安DELUCCHI這里的評論#3 湯姆Hawtin的回答是:

為什么Class.newInstance()“邪惡”?

這是為了響應代碼示例:

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

那么,為什么它是邪惡的?

Java API文檔解釋了原因( http://java.sun.com/javase/6/docs/api/java/lang/Class.html#newInstance() ):

請注意,此方法傳播由Nullary構造函數拋出的任何異常,包括已檢查的異常。 使用此方法可以有效地繞過編譯時異常檢查,否則將由編譯器執行。 Constructor.newInstance方法通過在(已檢查的) InvocationTargetException包裝構造函數拋出的任何異常來避免此問題。

換句話說,它可以擊敗已檢查的例外系統。

還有一個原因:

現代IDE允許您查找類用法 - 如果您和您的IDE知道哪些代碼正在使用您計划更改的類,則它在重構期間會有所幫助。

如果不明確使用構造函數,而是使用Class.newInstance(),則可能無法在重構期間找到該用法,並且在編譯時此問題不會顯現。

我不知道為什么沒有人提供一個簡單的基於示例的解釋,例如與Constructor::newInstance相比,因為最終 Class::newInstance自java-9以來已被棄用。

假設你有這個非常簡單的類(無論它是否被破壞):

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

並且您嘗試通過反射創建它的實例。 Class::newInstance

    Class<Foo> clazz = ...

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

調用此方法將導致拋出IOException - 問題是您的代碼無法處理它, handle 1handle 2都不會捕獲它。

相比之下,通過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();
    }

將調用句柄3,因此您將處理它。

實際上, Class::newInstance繞過了異常處理 - 你真的不想要它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM