<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                ## Chapter 9. General Programming(通用程序設計) ### Item 65: Prefer interfaces to reflection(接口優于反射) The core reflection facility, java.lang.reflect, offers programmatic access to arbitrary classes. Given a Class object, you can obtain Constructor, Method, and Field instances representing the constructors, methods, and fields of the class represented by the Class instance. These objects provide programmatic access to the class’s member names, field types, method signatures, and so on. 核心反射機制 `java.lang.reflect` 提供對任意類的編程訪問。給定一個 Class 對象,你可以獲得 Constructor、Method 和 Field 實例,分別代表了該 Class 實例所表示的類的構造器、方法和字段。這些對象提供對類的成員名、字段類型、方法簽名等的編程訪問。 Moreover, Constructor, Method, and Field instances let you manipulate their underlying counterparts reflectively: you can construct instances, invoke methods, and access fields of the underlying class by invoking methods on the Constructor, Method, and Field instances. For example, Method.invoke lets you invoke any method on any object of any class (subject to the usual security constraints). Reflection allows one class to use another, even if the latter class did not exist when the former was compiled. This power, however, comes at a price: 此外,Constructor、Method 和 Field 實例允許你反射性地操作它們的底層對應項:你可以通過調用 Constructor、Method 和 Field 實例上的方法,可以構造底層類的實例、調用底層類的方法,并訪問底層類中的字段。例如,Method.invoke 允許你在任何類的任何對象上調用任何方法(受默認的安全約束)。反射允許一個類使用另一個類,即使在編譯前者時后者并不存在。然而,這種能力是有代價的: - **You lose all the benefits of compile-time type checking,** including exception checking. If a program attempts to invoke a nonexistent or inaccessible method reflectively, it will fail at runtime unless you’ve taken special precautions. 你失去了編譯時類型檢查的所有好處,包括異常檢查。如果一個程序試圖反射性地調用一個不存在的或不可訪問的方法,它將在運行時失敗,除非你采取了特殊的預防措施。 - **The code required to perform reflective access is clumsy and verbose.** It is tedious to write and difficult to read. 執行反射訪問所需的代碼既笨拙又冗長。寫起來很乏味,讀起來也很困難。 - **Performance suffers.** Reflective method invocation is much slower than normal method invocation. Exactly how much slower is hard to say, as there are many factors at work. On my machine, invoking a method with no input parameters and an int return was eleven times slower when done reflectively. 性能降低。反射方法調用比普通方法調用慢得多。到底慢了多少還很難說,因為有很多因素在起作用。在我的機器上,調用一個沒有輸入參數和返回 int 類型的方法時,用反射執行要慢 11 倍。 There are a few sophisticated applications that require reflection. Examples include code analysis tools and dependency injection frameworks. Even such tools have been moving away from reflection of late, as its disadvantages become clearer. If you have any doubts as to whether your application requires reflection, it probably doesn’t. 有一些復雜的應用程序需要反射。包括代碼分析工具和依賴注入框架。即使是這樣的工具,隨著它的缺點變得越來越明顯,人們也在逐漸遠離并反思這種用法。如果你對應用程序是否需要反射有任何疑問,那么它可能不需要。 **You can obtain many of the benefits of reflection while incurring few of its costs by using it only in a very limited form.** For many programs that must use a class that is unavailable at compile time, there exists at compile time an appropriate interface or superclass by which to refer to the class (Item 64). If this is the case, you can **create instances reflectively and access them normally via their interface or superclass.** **通過非常有限的形式使用反射,你可以獲得反射的許多好處,同時花費的代價很少。** 對于許多程序,它們必須用到在編譯時無法獲取的類,在編譯時存在一個適當的接口或超類來引用該類([Item-64](/Chapter-9/Chapter-9-Item-64-Refer-to-objects-by-their-interfaces.md))。如果是這種情況,**可以用反射方式創建實例,并通過它們的接口或超類正常地訪問它們。** For example, here is a program that creates a `Set<String>` instance whose class is specified by the first command line argument. The program inserts the remaining command line arguments into the set and prints it. Regardless of the first argument, the program prints the remaining arguments with duplicates eliminated. The order in which these arguments are printed, however, depends on the class specified in the first argument. If you specify java.util.HashSet, they’re printed in apparently random order; if you specify java.util.TreeSet, they’re printed in alphabetical order because the elements in a TreeSet are sorted: 例如,這是一個創建 `Set<String>` 實例的程序,類由第一個命令行參數指定。程序將剩余的命令行參數插入到集合中并打印出來。不管第一個參數是什么,程序都會打印剩余的參數,并去掉重復項。然而,打印這些參數的順序取決于第一個參數中指定的類。如果你指定 `java.util.HashSet`,它們顯然是隨機排列的;如果你指定 `java.util.TreeSet`,它們是按字母順序打印的,因為 TreeSet 中的元素是有序的: ``` // Reflective instantiation with interface access public static void main(String[] args) { // Translate the class name into a Class object Class<? extends Set<String>> cl = null; try { cl = (Class<? extends Set<String>>) // Unchecked cast! Class.forName(args[0]); } catch (ClassNotFoundException e) { fatalError("Class not found."); } // Get the constructor Constructor<? extends Set<String>> cons = null; try { cons = cl.getDeclaredConstructor(); } catch (NoSuchMethodException e) { fatalError("No parameterless constructor"); } // Instantiate the set Set<String> s = null; try { s = cons.newInstance(); } catch (IllegalAccessException e) { fatalError("Constructor not accessible"); } catch (InstantiationException e) { fatalError("Class not instantiable."); } catch (InvocationTargetException e) { fatalError("Constructor threw " + e.getCause()); } catch (ClassCastException e) { fatalError("Class doesn't implement Set"); } // Exercise the set s.addAll(Arrays.asList(args).subList(1, args.length)); System.out.println(s); } private static void fatalError(String msg) { System.err.println(msg); System.exit(1); } ``` While this program is just a toy, the technique it demonstrates is quite powerful. The toy program could easily be turned into a generic set tester that validates the specified Set implementation by aggressively manipulating one or more instances and checking that they obey the Set contract. Similarly, it could be turned into a generic set performance analysis tool. In fact, this technique is sufficiently powerful to implement a full-blown service provider framework (Item 1). Usually, this technique is all that you need in the way of reflection. 雖然這個程序只是一個小把戲,但它演示的技術非常強大。這個程序可以很容易地轉換成一個通用的集合測試器,通過積極地操作一個或多個實例并檢查它們是否遵守 Set 接口約定來驗證指定的 Set 實現。類似地,它可以變成一個通用的集合性能分析工具。事實上,該技術足夠強大,可以實現一個成熟的服務提供者框架([Item-1](/Chapter-2/Chapter-2-Item-1-Consider-static-factory-methods-instead-of-constructors.md))。 This example demonstrates two disadvantages of reflection. First, the example can generate six different exceptions at runtime, all of which would have been compile-time errors if reflective instantiation were not used. (For fun, you can cause the program to generate each of the six exceptions by passing in appropriate command line arguments.) The second disadvantage is that it takes twenty-five lines of tedious code to generate an instance of the class from its name, whereas a constructor invocation would fit neatly on a single line. The length of the program could be reduced by catching ReflectiveOperationException, a superclass of the various reflective exceptions that was introduced in Java 7. Both disadvantages are restricted to the part of the program that instantiates the object. Once instantiated, the set is indistinguishable from any other Set instance. In a real program, the great bulk of the code is thus unaffected by this limited use of reflection. 這個例子也說明了反射的兩個缺點。首先,該示例可以在運行時生成六個不同的異常,如果沒有使用反射實例化,所有這些異常都將是編譯時錯誤。(有趣的是,你可以通過傳入適當的命令行參數,使程序生成六個異常中的每一個。)第二個缺點是,根據類的名稱生成類的實例需要 25 行冗長的代碼,而構造函數調用只需要一行。通過捕獲 ReflectiveOperationException(Java 7 中引入的各種反射異常的超類),可以減少程序的長度。這兩個缺點都只限于實例化對象的程序部分。實例化后,與任何其他 Set 實例將難以區分。在實際的程序中,通過這種限定使用反射的方法,大部分代碼可以免受影響。 If you compile this program, you’ll get an unchecked cast warning. This warning is legitimate, in that the cast to `Class<? extends Set<String>>` will succeed even if the named class is not a Set implementation, in which case the program with throw a ClassCastException when it instantiates the class. To learn about suppressing the warning, read Item 27. 如果編譯此程序,將得到 unchecked 的強制轉換警告。這個警告是合法的,即使指定的類不是 Set 實現,`Class<? extends Set<String>>` 也會成功,在這種情況下,程序在實例化類時拋出 ClassCastException。要了解如何抑制警告,請閱讀 [Item-27](/Chapter-5/Chapter-5-Item-27-Eliminate-unchecked-warnings.md)。 A legitimate, if rare, use of reflection is to manage a class’s dependencies on other classes, methods, or fields that may be absent at runtime. This can be useful if you are writing a package that must run against multiple versions of some other package. The technique is to compile your package against the minimal environment required to support it, typically the oldest version, and to access any newer classes or methods reflectively. To make this work, you have to take appropriate action if a newer class or method that you are attempting to access does not exist at runtime. Appropriate action might consist of using some alternate means to accomplish the same goal or operating with reduced functionality. 反射的合法用途(很少)是管理類對運行時可能不存在的其他類、方法或字段的依賴關系。如果你正在編寫一個包,并且必須針對其他包的多個版本運行,此時反射將非常有用。該技術是根據支持包所需的最小環境(通常是最老的版本)編譯包,并反射性地訪問任何較新的類或方法。如果你試圖訪問的新類或方法在運行時不存在,要使此工作正常進行,則必須采取適當的操作。適當的操作可能包括使用一些替代方法來完成相同的目標,或者使用簡化的功能進行操作。 In summary, reflection is a powerful facility that is required for certain sophisticated system programming tasks, but it has many disadvantages. If you are writing a program that has to work with classes unknown at compile time, you should, if at all possible, use reflection only to instantiate objects, and access the objects using some interface or superclass that is known at compile time. 總之,反射是一種功能強大的工具,對于某些復雜的系統編程任務是必需的,但是它有很多缺點。如果編寫的程序必須在編譯時處理未知的類,則應該盡可能只使用反射實例化對象,并使用在編譯時已知的接口或超類訪問對象。 --- **[Back to contents of the chapter(返回章節目錄)](/Chapter-9/Chapter-9-Introduction.md)** - **Previous Item(上一條目):[Item 64: Refer to objects by their interfaces(通過接口引用對象)](/Chapter-9/Chapter-9-Item-64-Refer-to-objects-by-their-interfaces.md)** - **Next Item(下一條目):[Item 66: Use native methods judiciously(明智地使用本地方法)](/Chapter-9/Chapter-9-Item-66-Use-native-methods-judiciously.md)**
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看