为什么一个类的实例可以访问另一个同类型实例的私有字段?

23

在Java中,类的一个实例可以访问其自身类型的另一个实例的私有字段,例如以下列表中所示:

public class Foo {
  private int secret;
  public void bar(final Foo foo) {
    foo.secret = 100;
  }
}

设计语言时,这样的语义学有什么论据?


好的,这都是一个类,所以你可以访问自己的私有成员。如果你不想更新secret,那就不要更新它。编程不能保护你免受自己的伤害。 - markspace
6
“private”的定义表示只有“Foo”的实例才能访问它。由于你在“Foo”中,所以可以访问它。 - Elliott Frisch
4
语言的语义允许这样做,我在问为什么。 - Pétur Ingi Egilsson
阻止一个类访问同一类的另一个实例的字段会带来什么好处?Java不会问“为什么现在”,它只试图拥有一些具有价值的功能。 - Peter Lawrey
1
没有这个,你怎么实现一个 equals(Foo other) 方法呢? - Thilo
显示剩余3条评论
3个回答

18

首先,你必须问自己“为什么需要私有字段?”

私有字段主要是用于封装:类的消费者不应该知道该类实现的内部细节,事实上,这些细节应该被积极地隐藏。否则,如果用户依赖于这些内部细节,则实现者将被迫支持它们或破坏向后兼容性。换句话说,它保护了类的用户和设计者:

  • 用户受到保护,防止实现更改破坏其代码
  • 设计者受到保护,不必永远保持实现细节特性不变

但是,一个类不需要保护自身;它不需要担心其代码中的某一部分发生更改,而另一部分(使用第一部分)无法更改的情况。向后兼容性不是问题,因为该类作为单个原子代码块开发和部署。换句话说,以上两种保护都不是必需的。

由于没有必要保护字段,并且通常需要查看它们(例如,比较两个对象是否相等),所以它们在类内部可见。


为什么一个类的代码不能在版本中更改?(可能是我没有理解你。)我会说:“类内部的更改可以轻松地由设计师修改以支持任何更改。公共字段则不行,因为它可能会破坏作者范围之外的代码。” - Mordechai
由于内部可能会更改,请勿使用 @MouseEvent。想象一下,如果您依赖于 FileInputStream 类的内部字段,而突然出现了 NIO,其中 FileInputStream 完全更改以利用本机 io 操作,那么您的代码读取的字段现在突然不再存在,因为它是在本地代码中实现的。 - RecursiveExceptionException

6

private字段的作用是告诉其他程序员不要操作它。

可以想象,在同一个类中工作的所有人都知道所有变量的作用。 private字段并没有将您自己的代码隐藏,只是隐藏了外部的访问。


1
您可以在不使用额外getter的情况下复制/比较值,并在不使用setter的情况下更改字段。不知道在JVM中是否以任何方式优化这样的简单方法调用,但如果没有,则会产生一些开销。
有人可能认为保持这种“开放”访问可能会导致某些安全问题,但是当实现类时,您提供了所有用于操作这些变量的方法。没有人可以从扩展此类的类中更改它们。实际上,它们仍然是私有的-仅从您的代码中可访问。
还要记住,逻辑上一个类通常注定要做一件事。在需要生成大量实例的情况下,共享一些信息并简化访问可能是有益的。在需要更多控制的情况下,可以始终使用包访问修饰符(在某种意义上更加“私有”...)或使用单例/工厂模式限制实例计数。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接