<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>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                ## Chapter 4. Classes and Interfaces(類和接口) ### Item 15: Minimize the accessibility of classes and members(盡量減少類和成員的可訪問性) The single most important factor that distinguishes a well-designed component from a poorly designed one is the degree to which the component hides its internal data and other implementation details from other components. A welldesigned component hides all its implementation details, cleanly separating its API from its implementation. Components then communicate only through their APIs and are oblivious to each others’ inner workings. This concept, known as information hiding or encapsulation, is a fundamental tenet of software design [Parnas72]. 要將設計良好的組件與設計糟糕的組件區別開來,最重要的因素是:隱藏內部數據和其他實現細節的程度。設計良好的組件隱藏了所有實現細節,將 API 與實現完全分離。組件之間只通過它們的 API 進行通信,而不知道彼此的內部工作方式。這個概念被稱為信息隱藏或封裝,是軟件設計的基本原則 [Parnas72]。 Information hiding is important for many reasons, most of which stem from the fact that it decouples the components that comprise a system, allowing them to be developed, tested, optimized, used, understood, and modified in isolation.This speeds up system development because components can be developed in parallel. It eases the burden of maintenance because components can be understood more quickly and debugged or replaced with little fear of harming other components. While information hiding does not, in and of itself, cause good performance, it enables effective performance tuning: once a system is complete and profiling has determined which components are causing performance problems (Item 67), those components can be optimized without affecting the correctness of others. Information hiding increases software reuse because components that aren’t tightly coupled often prove useful in other contexts besides the ones for which they were developed. Finally, information hiding decreases the risk in building large systems because individual components may prove successful even if the system does not. 由于許多原因,信息隱藏是重要的,其中大部分原因源于這樣一個事實:它解耦了組成系統的組件,允許它們被獨立開發、測試、優化、使用、理解和修改。這加快了系統開發進度,因為組件可以并行開發。也減輕了維護的負擔,因為組件可以被更快地理解、調試或替換,而不必擔心會損害其他組件。雖然信息隱藏本身不會獲得良好的性能,但它可以實現有效的性能調優:一旦系統完成,概要分析確定了哪些組件會導致性能問題([Item-67](/Chapter-9/Chapter-9-Item-67-Optimize-judiciously.md)),就可以在不影響其他組件正確性的情況下對這些組件進行優化。信息隱藏增加了軟件的復用性,因為沒有緊密耦合的組件在其他場景中通常被證明是有用的,除了開發它們時所在的場景之外。最后,信息隱藏降低了構建大型系統的風險,因為即使系統沒有成功,單個組件也可能被證明是成功的。 Java has many facilities to aid in information hiding. The access control mechanism [JLS, 6.6] specifies the accessibility of classes, interfaces, and members. The accessibility of an entity is determined by the location of its declaration and by which, if any, of the access modifiers (private,protected, and public) is present on the declaration. Proper use of these modifiers is essential to information hiding. Java 有許多工具來幫助隱藏信息。訪問控制機制 [JLS, 6.6] 指定了類、接口和成員的可訪問性。實體的可訪問性由其聲明的位置以及聲明中出現的訪問修飾符(private、protected 和 public)決定。正確使用這些修飾符是信息隱藏的關鍵。 The rule of thumb is simple: make each class or member as inaccessible as possible. In other words, use the lowest possible access level consistent with the proper functioning of the software that you are writing. 經驗法則很簡單:讓每個類或成員盡可能不可訪問。換句話說,在不影響軟件正常功能時,使用盡可能低的訪問級別。 For top-level (non-nested) classes and interfaces, there are only two possible access levels: package-private and public. If you declare a top-level class or interface with the public modifier, it will be public; otherwise, it will be package-private. If a top-level class or interface can be made package-private, it should be. By making it package-private, you make it part of the implementation rather than the exported API, and you can modify it, replace it, or eliminate it in a subsequent release without fear of harming existing clients. If you make it public, you are obligated to support it forever to maintain compatibility. 對于頂級(非嵌套)類和接口,只有兩個可能的訪問級別:包私有和公共。如果用 public 修飾符聲明一個頂級類或接口,它將是公共的;否則,它將是包私有的。如果頂級類或接口可以設置為包私有,那么就應該這么做。通過將其設置為包私有,可以使其成為實現的一部分,而不是導出的 API 的一部分,并且可以在后續版本中修改、替換或刪除它,而不必擔心損害現有的客戶端。如果將其公開,就有義務永遠提供支持,以保持兼容性。 If a package-private top-level class or interface is used by only one class,consider making the top-level class a private static nested class of the sole class that uses it (Item 24). This reduces its accessibility from all the classes in its package to the one class that uses it. But it is far more important to reduce the accessibility of a gratuitously public class than of a package-private top-level class: the public class is part of the package’s API, while the package-private top-level class is already part of its implementation. 如果包級私有頂級類或接口只被一個類使用,那么可以考慮:在使用它的這個類中,將頂級類設置為私有靜態嵌套類([Item-24](/Chapter-4/Chapter-4-Item-24-Favor-static-member-classes-over-nonstatic.md))。對于包中的所有類以及使用它的類來說,這降低了它的可訪問性。但是,降低公共類的可訪問性比減少包級私有頂級類的可訪問性重要得多:公共類是包 API 的一部分,而包級私有頂級類已經是實現的一部分。 For members (fields, methods, nested classes, and nested interfaces), there are four possible access levels, listed here in order of increasing accessibility: 對于成員(字段、方法、嵌套類和嵌套接口),有四個可能的訪問級別,這里按可訪問性依次遞增的順序列出: - **private** —The member is accessible only from the top-level class where it is declared. **私有**,成員只能從聲明它的頂級類內部訪問。 - **package-private** —The member is accessible from any class in the package where it is declared. Technically known as default access, this is the access level you get if no access modifier is specified (except for interface members,which are public by default). **包級私有**,成員可以從包中聲明它的任何類訪問。技術上稱為默認訪問,即如果沒有指定訪問修飾符(接口成員除外,默認情況下,接口成員是公共的),就會得到這個訪問級別。 - **protected** —The member is accessible from subclasses of the class where it is declared (subject to a few restrictions [JLS, 6.6.2]) and from any class in the package where it is declared. **保護**,成員可以通過聲明它的類的子類(會受一些限制 [JLS, 6.6.2])和聲明它的包中的任何類訪問。 - **public** —The member is accessible from anywhere. **公共**,該成員可以從任何地方訪問。 After carefully designing your class’s public API, your reflex should be to make all other members private. Only if another class in the same package really needs to access a member should you remove the private modifier, making the member package-private. If you find yourself doing this often, you should reexamine the design of your system to see if another decomposition might yield classes that are better decoupled from one another. That said, both private and package-private members are part of a class’s implementation and do not normally impact its exported API. These fields can, however, “leak” into the exported API if the class implements Serializable (Items 86 and 87). 在仔細設計了類的公共 API 之后,你應該本能的使所有成員都是私有的。只有當同一包中的另一個類確實需要訪問一個成員時,你才應該刪除 private 修飾符,使成員變為包級私有。如果你發現自己經常這樣做,那么你應該重新確認系統的設計,看看是否有其他方式能產生更好地相互解耦的類。也就是說,私有成員和包級私有成員都是類實現的一部分,通常不會影響其導出的 API。但是,如果類實現了 Serializable([Item-86](/Chapter-12/Chapter-12-Item-86-Implement-Serializable-with-great-caution.md) 和 [Item-87](/Chapter-12/Chapter-12-Item-87-Consider-using-a-custom-serialized-form.md)),這些字段可能會「泄漏」到導出的 API 中。 For members of public classes, a huge increase in accessibility occurs when the access level goes from package-private to protected. A protected member is part of the class’s exported API and must be supported forever. Also, a protected member of an exported class represents a public commitment to an implementation detail (Item 19). The need for protected members should be relatively rare. 對于公共類的成員來說,當訪問級別從包級私有變為保護時,可訪問性會有很大的提高。保護成員是類導出 API 的一部分,必須永遠支持。此外,導出類的保護成員表示對實現細節的公開承諾([Item-19](/Chapter-4/Chapter-4-Item-19-Design-and-document-for-inheritance-or-else-prohibit-it.md))。需要保護成員的場景應該相對少見。 There is a key rule that restricts your ability to reduce the accessibility of methods. If a method overrides a superclass method, it cannot have a more restrictive access level in the subclass than in the superclass [JLS, 8.4.8.3]. This is necessary to ensure that an instance of the subclass is usable anywhere that an instance of the superclass is usable (the Liskov substitution principle, see Item15). If you violate this rule, the compiler will generate an error message when you try to compile the subclass. A special case of this rule is that if a class implements an interface, all of the class methods that are in the interface must be declared public in the class. 有一個關鍵規則限制了你降低方法的可訪問性。如果一個方法覆蓋了超類方法,那么它在子類中的訪問級別就不能比超類 [JLS, 8.4.8.3] 更嚴格。這對于確保子類的實例在超類的實例可用的任何地方都同樣可用是必要的(Liskov 替換原則,請參閱 [Item-15](/Chapter-4/Chapter-4-Item-15-Minimize-the-accessibility-of-classes-and-members.md))。如果違反此規則,編譯器將在嘗試編譯子類時生成錯誤消息。這個規則的一個特例是,如果一個類實現了一個接口,那么該接口中的所有類方法都必須在類中聲明為 public。 To facilitate testing your code, you may be tempted to make a class, interface,or member more accessible than otherwise necessary. This is fine up to a point. It is acceptable to make a private member of a public class package-private in order to test it, but it is not acceptable to raise the accessibility any higher. In other words, it is not acceptable to make a class, interface, or member a part of a package’s exported API to facilitate testing. Luckily, it isn’t necessary either because tests can be made to run as part of the package being tested, thus gaining access to its package-private elements. 為了便于測試代碼,你可能會試圖使類、接口或成員更容易訪問。這在一定程度上是好的。為了測試,將公共類成員由私有變為包私有是可以接受的,但是進一步提高可訪問性是不可接受的。換句話說,將類、接口或成員作為包導出 API 的一部分以方便測試是不可接受的。幸運的是,也沒有必要這樣做,因為測試可以作為包的一部分運行,從而獲得對包私有元素的訪問權。 **Instance fields of public classes should rarely be public** (Item 16). If an instance field is nonfinal or is a reference to a mutable object, then by making it public, you give up the ability to limit the values that can be stored in the field. This means you give up the ability to enforce invariants involving the field. Also, you give up the ability to take any action when the field is modified, so **classes with public mutable fields are not generally thread-safe.** Even if a field is final and refers to an immutable object, by making it public you give up the flexibility to switch to a new internal data representation in which the field does not exist. **公共類的實例字段很少采用 public 修飾**([Item-16](/Chapter-4/Chapter-4-Item-16-In-public-classes-use-accessor-methods-not-public-fields.md))。如果實例字段不是 final 的,或者是對可變對象的引用,那么將其公開,你就放棄了限制字段中可以存儲的值的能力。這意味著你放棄了強制包含字段的不可變的能力。此外,你還放棄了在修改字段時采取任何操作的能力,因此 **帶有公共可變字段的類通常不是線程安全的。** 即使一個字段是 final 的,并且引用了一個不可變的對象,通過將其公開,你放棄了切換到一個新的內部數據表示的靈活性,而該字段并不存在。 The same advice applies to static fields, with one exception. You can expose constants via public static final fields, assuming the constants form an integral part of the abstraction provided by the class. By convention, such fields have names consisting of capital letters, with words separated by underscores (Item 68). It is critical that these fields contain either primitive values or references to immutable objects (Item 17). a field containing a reference to a mutable object has all the disadvantages of a nonfinal field. While the reference cannot be modified, the referenced object can be modified—with disastrous results. 同樣的建議也適用于靜態字段,只有一個例外。你可以通過公共靜態 final 字段公開常量,假設這些常量是類提供的抽象的組成部分。按照慣例,這些字段的名稱由大寫字母組成,單詞以下劃線分隔([Item-68](/Chapter-9/Chapter-9-Item-68-Adhere-to-generally-accepted-naming-conventions.md))。重要的是,這些字段要么包含基本數據類型,要么包含對不可變對象的引用([Item-17](/Chapter-4/Chapter-4-Item-17-Minimize-mutability.md))。包含對可變對象的引用的字段具有非 final 字段的所有缺點。雖然引用不能被修改,但是引用的對象可以被修改會導致災難性的后果。 Note that a nonzero-length array is always mutable, so it is wrong for a class to have a public static final array field, or an accessor that returns such a field. If a class has such a field or accessor, clients will be able to modify the contents of the array. This is a frequent source of security holes: 請注意,非零長度的數組總是可變的,因此對于類來說,擁有一個公共靜態 final 數組字段或返回該字段的訪問器是錯誤的。如果一個類具有這樣的字段或訪問器,客戶端將能夠修改數組的內容。這是一個常見的安全漏洞來源: ``` // Potential security hole! public static final Thing[] VALUES = { ... }; ``` Beware of the fact that some IDEs generate accessors that return references to private array fields, resulting in exactly this problem. There are two ways to fix the problem. You can make the public array private and add a public immutable list: 要注意的是,一些 IDE 生成了返回私有數組字段引用的訪問器,這恰恰會導致這個問題。有兩種方法可以解決這個問題。你可以將公共數組設置為私有,并添加一個公共不可變 List: ``` private static final Thing[] PRIVATE_VALUES = { ... }; public static final List<Thing> VALUES = Collections.unmodifiableList(Arrays.asList(PRIVATE_VALUES)); ``` Alternatively, you can make the array private and add a public method that returns a copy of a private array: 或者,你可以將數組設置為私有,并添加一個返回私有數組副本的公共方法: ``` private static final Thing[] PRIVATE_VALUES = { ... }; public static final Thing[] values() { return PRIVATE_VALUES.clone(); } ``` To choose between these alternatives, think about what the client is likely to do with the result. Which return type will be more convenient? Which will give better performance? 如何在這些備選方案中進行選擇,請考慮客戶可能會如何處理結果。哪種返回類型更方便?哪種表現會更好? As of Java 9, there are two additional, implicit access levels introduced as part of the module system. A module is a grouping of packages, like a package is a grouping of classes. A module may explicitly export some of its packages via export declarations in its module declaration (which is by convention contained in a source file named module-info.java). Public and protected members of unexported packages in a module are inaccessible outside the module; within the module, accessibility is unaffected by export declarations. Using the module system allows you to share classes among packages within a module without making them visible to the entire world. Public and protected members of public classes in unexported packages give rise to the two implicit access levels, which are intramodular analogues of the normal public and protected levels. The need for this kind of sharing is relatively rare and can often be eliminated by rearranging the classes within your packages. 對于 Java 9,作為模塊系統的一部分,還引入了另外兩個隱式訪問級別。模塊是包的分組單位,就像包是類的分組單位一樣。模塊可以通過模塊聲明中的導出聲明顯式地導出它的一些包(按照約定包含在名為 `module-info.java` 的源文件中)。模塊中未導出包的公共成員和保護成員在模塊外不可訪問;在模塊中,可訪問性不受導出聲明的影響。通過使用模塊系統,你可以在模塊內的包之間共享類,而不會讓整個世界看到它們。未導出包中的公共類和保護成員產生了兩個隱式訪問級別,它們是正常公共級別和保護級別的類似物。這種共享的需求相對較少,通常可以通過重新安排包中的類來解決。 Unlike the four main access levels, the two module-based levels are largely advisory. If you place a module’s JAR file on your application’s class path instead of its module path, the packages in the module revert to their nonmodular behavior: all of the public and protected members of the packages’ public classes have their normal accessibility, regardless of whether the packages are exported by the module [Reinhold, 1.2]. The one place where the newly introduced access levels are strictly enforced is the JDK itself: the unexported packages in the Java libraries are truly inaccessible outside of their modules. 與四個主要的訪問級別不同,這兩個基于模塊的級別在很大程度上是建議級別。如果將模塊的 JAR 文件放在應用程序的類路徑上,而不是模塊路徑上,模塊中的包將恢復它們的非模塊行為:包的公共類的所有公共成員和保護成員都具有正常的可訪問性,而不管模塊是否導出包 [Reinhold,1.2]。嚴格執行新引入的訪問級別的一個地方是 JDK 本身:Java 庫中未導出的包在其模塊之外確實不可訪問。 Not only is the access protection afforded by modules of limited utility to the typical Java programmer, and largely advisory in nature; in order to take advantage of it, you must group your packages into modules, make all of their dependencies explicit in module declarations, rearrange your source tree, and take special actions to accommodate any access to non-modularized packages from within your modules [Reinhold, 3]. It is too early to say whether modules will achieve widespread use outside of the JDK itself. In the meantime, it seems best to avoid them unless you have a compelling need. 對于典型的 Java 程序員來說,訪問保護不僅是有限實用的模塊所提供的,而且本質上是建議性的;為了利用它,你必須將包以模塊分組,在模塊聲明中顯式地聲明它們的所有依賴項,重新安排源代碼樹,并采取特殊操作以適應從模塊中對非模塊化包的任何訪問 [Reinhold, 3]。現在說模塊能否在 JDK 之外得到廣泛使用還為時過早。與此同時,除非你有迫切的需求,否則最好還是不使用它們。 To summarize, you should reduce accessibility of program elements as much as possible (within reason). After carefully designing a minimal public API, you should prevent any stray classes, interfaces, or members from becoming part of the API. With the exception of public static final fields, which serve as constants,public classes should have no public fields. Ensure that objects referenced by public static final fields are immutable. 總之,你應該盡可能減少程序元素的可訪問性(在合理的范圍內)。在仔細設計了一個最小的公共 API 之后,你應該防止任何游離的類、接口或成員成為 API 的一部分。除了作為常量的公共靜態 final 字段外,public 類應該沒有公共字段。確保公共靜態 final 字段引用的對象是不可變的。 --- **[Back to contents of the chapter(返回章節目錄)](/Chapter-4/Chapter-4-Introduction.md)** - **Next Item(下一條目):[Item 16: In public classes use accessor methods not public fields(在公共類中,使用訪問器方法,而不是公共字段)](/Chapter-4/Chapter-4-Item-16-In-public-classes-use-accessor-methods-not-public-fields.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>

                              哎呀哎呀视频在线观看