zoukankan      html  css  js  c++  java
  • Effective Java:Ch4_Class:Item14_在public类中应该使用访问方法而不是public域

            你可能偶尔需要编写退化类,目的只是为了集中实例域:

    // Degenerate classes like this should not be public!
    class Point {
      public double x;
      public double y;
    }


            由于这种类的数据域是可以直接访问的,所以他们不能提供“封装”带来的好处。如果不改变API,就不能改变其数据表示法,不能强加任何约束,当域被访问时不能采取任何辅助行为。强硬派的面向对象程序员会非常厌恶这种类,认为这种类应该被包含private域和public访问方法(getter)的类替代。对于可变类,还应该包含setter。

    // Encapsulation of data by accessor and mutators
    class Point {
      private double x;
      private double y;
    
      public Point(double x, double y) {
        this.x = x;
        this.y = y;
      }
    
      public double getX() { return x; }
      public double getY() { return y; }
      public void setX(double x) { this.x = x; }
      public void setY(double y) { this.y = y; }
    }

            毫无疑问,强硬派的观点在public类上是正确的:如果一个类可以被包外访问,那么就要提供访问方法,以便可以灵活地改变类的内部表示。如果public类暴露了其数据域,则要想在将来改变内部表示是不可能的,因为他的客户端代码可能已经遍布各处了。

            然而,如果类是package-private或是private嵌套类,那么把数据域暴露出去并没有本质的错误——假设这些数据域充分描述了该类提供的抽象。无论是在类定义中,还是在客户端代码中,这种方法相对于访问方法更不会产生视觉混乱。虽然客户端代码与类的内部表示紧密相连,但这些代码被限定在同一个包中。如果需要改变内部数据表示,你不必修改包外的任何代码。如果是private嵌套类,则甚至不需要修改类外的任何代码。


            JDK中的几个类违反了“public类不应该直接暴漏其字段”这个告诫。最显著的例子是java.awt包中的Point类和Dimension类。正如Item55中讲的,决定暴露Dimentsion类的内部实现造成了严重的性能问题,而且这个问题至今还存在。

    ——Component.getSize()返回Dimension,每次调用都要new一个新的对象。


            虽然直接暴露public类的字段永远都不是个好主意,但是如果该域是不可变的(immutable),则危害性就小得多。除非修改其API,否则你不能修改其内部数据表示,而且当别人读取该字段时 你不能采取任何附加行动,但是你可以强加约束条件——因为只有你自己可以set该字段)。例如,下面这个类保证了每个实例都表示一个合法的时间。

    // public class with exposed immutable fields - questionable
    public final class Time {
      private static final int HOUR_PER_DAY = 24;
      private static final int MINUTES_PER_HOUR = 60;
    
      public final int hour;
      public final int minute;
    
      public Time() {
        //强加约束条件
        if (hour < 0 || hour >= HOUR_PER_DAY) {
           throw new IllegalArgumentException();
        if (minute < 0 || minute >= MINUTES_PER_HOUR) {
           throw new IllegalArgumentException();
        
        this.hour = hour;
        this.minute = minute;
      }
    
    }


             总之,public类永远不要暴露其可变的字段。而public类暴露其不可变字段随然是有问题,但危害性要小一些。然而,package-private或者private的嵌套类暴露其字段则是可行的,无论该字段是可变还是非可变。




  • 相关阅读:
    剑指offer——最小的K个数和数组中第K大的元素
    Leetcode刷题指南链接整理
    160. Intersection of Two Linked Lists
    100. Same Tree
    92. Reverse Linked List II
    94. Binary Tree Inorder Traversal
    79. Word Search
    78,90,Subsets,46,47,Permutations,39,40 DFS 大合集
    0x16 Tire之最大的异或对
    0x16 Tire
  • 原文地址:https://www.cnblogs.com/jiangu66/p/3221894.html
Copyright © 2011-2022 走看看