简体   繁体   English

对于 public class 直接公开字段从来都不是一个好主意,但如果字段是不可变的,为什么危害较小呢?

[英]It''s never a good idea for a public class to expose fields directly, but why it is less harmful if the fields are immutable?

I'm reading an article from Effective Java Item 14 - In public classes, use accessor methods, not public fields.我正在阅读 Effective Java 第 14 项中的一篇文章 - 在公共课程中,使用访问器方法,而不是公共字段。 In the book it says: While it's never a good idea for a public class to expose fields directly, it is less harmful if the fields are immutable.在书中它说:虽然公共 class 直接公开字段绝不是一个好主意,但如果字段是不可变的,则危害较小。

My question is why it's less harmful if the fields are immutable?我的问题是,如果字段是不可变的,为什么危害较小? Could you give a real-life example to justify?你能举一个现实生活中的例子来证明吗? Here is the code example in the book.这是书中的代码示例。

/ Encapsulation of data by accessor methods 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 void setX(double x) { this.x = x; }

   public double getY() { return y; }
   public void setY(double y) { this.y = y; }
}

While it's never a good idea for a public class to expose fields directly, it is less harmful if the fields are immutable.虽然公共 class 直接公开字段绝不是一个好主意,但如果字段是不可变的,则危害较小。

// Public class with exposed immutable fields - questionable
public final class Time {
   public final int hour;
   public final int minute;

   public Time(int hour, int minute) {
      this.hour = hour;
      this.minute = minute;
   }
}

If your object has solely immutable fields, most likely that object itself can be regarded immutable.如果您的 object 只有不可变字段,那么 object 本身很可能被认为是不可变的。

Which means: upon creation, that object will never change its content.这意味着:创建后,object 将永远不会更改其内容。 Thus you can reference to that object from any number of places.因此,您可以从任何地方引用 object。 And no other object needs to worry that the corresponding data will magically change, because some other code did something.并且没有其他 object 需要担心相应的数据会神奇地改变,因为其他一些代码做了一些事情。

Essentially, the difference between direct field access and providing a setter method isn't what matters: The only thing that makes a huge conceptual difference.本质上,直接字段访问和提供 setter 方法之间的区别并不重要:唯一产生巨大概念差异的是。 mutable vs immutable.可变与不可变。

And note: ideally, the public methods of a class provide you behavior that client code can use!并注意:理想情况下,class 的公共方法为您提供客户端代码可以使用的行为!

It's explained clearly in the following sentence and then he gives an example.下面的句子解释得很清楚,然后他举了一个例子。 I have the second edition, maybe you have the first edition and it's missing from it?我有第二版,也许你有第一版,但它不见了?

While it's never a good idea for a public class to expose fields directly, it is less harmful if the fields are immutable.虽然公共 class 直接公开字段绝不是一个好主意,但如果字段是不可变的,则危害较小。 You can't change the representation of such a class without changing its API, and you can't take auxiliary actions when a field is read, but you can enforce invariants .你不能在不改变它的 API 的情况下改变这样的 class 的表示,并且你不能在读取字段时采取辅助操作,但你可以强制执行不变量 (emphasis mine) (强调我的)

The enforcing invariants example given in the book:书中给出的强制不变量示例:

For example, this class guarantees that each instance represents a valid time:例如,这个 class 保证每个实例代表一个有效时间:

// Public class with exposed immutable fields - questionable
public final class Time {
    private static final int HOURS_PER_DAY = 24;
    private static final int MINUTES_PER_HOUR = 60;

    public final int hour;
    public final int minute;

    public Time(int hour, int minute) {
        if (hour < 0 || hour >= HOURS_PER_DAY)
            throw new IllegalArgumentException("Hour: " + hour);
        if (minute < 0 || minute >= MINUTES_PER_HOUR)
            throw new IllegalArgumentException("Min: " + minute);
        this.hour = hour;
        this.minute = minute;
    }
// Remainder omitted
}
// Public class with exposed immutable fields - questionable
public final class Time {
   public final int hour;
   public final int minute;

   public Time(int hour, int minute) {
      this.hour = hour;
      this.minute = minute;
   }
}

With the above code, the Class which is creating the object of the above class must have knowledge about the fields.使用以上代码,正在创建上述 class 的 object 的 Class 必须了解这些字段。 This introduces a tight coupling.这引入了紧耦合。

Also, if you are coding to interfaces when the object is declared using the interface name all the implementations will implement the methods and it will be easier for the developer to access the value using methods and every implementation can use these class level variables and return as per the implementation details.此外,如果您在使用接口名称声明 object 时对接口进行编码,则所有实现都将实现这些方法,开发人员将更容易使用方法访问该值,并且每个实现都可以使用这些 class 级别变量并返回为根据实施细节。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM