为什么Java中的属性是公开的?

str*_*rry 43 java oop visibility

众所周知,Java遵循面向对象的范式,数据封装说,对象的字段(属性)应该为外部世界隐藏,只能通过方法访问,或者方法是外部类的唯一接口世界.那么为什么有可能将Java中的字段声明为public,这会违反数据封装范例呢?

duf*_*ymo 74

我认为这是可能的,因为每个规则都有其例外,在某些情况下可以覆盖每个最佳实践.

例如,我经常将公共静态最终数据成员公开为公共(例如,常量).我不认为这有害.

我要指出,除了Java之外,其他语言中也存在这种情况:C++,C#等.

语言不一定总能保护我们自己.

在Oli的例子中,如果我这样写它会有什么危害?

public class Point {
   public final int x;
   public final int y;

   public Point(int p, int q) {
      this.x = p;
      this.y = q;
   } 
}
Run Code Online (Sandbox Code Playgroud)

它是不可变的和线程安全的.数据成员可能是公开的,但你不能伤害他们.

此外,这是一个肮脏的小秘密,"私人"在Java中并不是真正私密的.你总是可以用反射来绕过它.

所以放松一下 也不是那么坏.

  • "语言不一定能保护我们自己." 我喜欢 :-) (17认同)

Oli*_*rth 52

为了灵活性.如果我不能写,那将是一个巨大的痛苦:

class Point {
    public int x;
    public int y;
}
Run Code Online (Sandbox Code Playgroud)

将这隐藏在吸气剂和制定者背后,有一点宝贵的好处.

  • @HenrikPaul:同意.这是一个例子,而不是世界上最完美的代码! (6认同)
  • 我认为这是一件危险的事情,因为你的Point现在是可变的(并且线程不安全).接受的答案的版本是不可变的,这通常是"更好"的方式. (3认同)

Hot*_*cks 12

因为僵化的"数据封装"不是唯一的范例,也不是面向对象的强制性特征.

而且,更重要的是,如果一个数据属性具有公共setter方法和公共getter方法,并且这些方法除了实际设置/获取属性之外什么都不做,那么将它保密是什么意思呢?

  • 嗯......"封装"正是这一点?你通常关心getter和setter方法,并且这些方法应该保持不变,因为它们是类合同的一部分.如何在内部存储值是任何人的业务,可能会随版本而变化.即使您不再使用它,也必须永远拖动公共属性. (2认同)
  • 不,"封装"不是重点.OO背后的主要(但不仅仅是)"点"是将行为与数据联系起来.无论你是否使用setter/getter,你仍然必须永远"拖拽"一个未使用的属性,如果兼容性是一个问题(它可能不是98%的情况). (2认同)
  • @HotLicks:这取决于您对面向对象的定义。如果你问 Alan Kay(并且 [他确实创造了这个词](http://c2.com/cgi/wiki?HeInventedTheTerm)),他 [说](http://www.purl.org/stefan_ram/pub/ doc_kay_oop_en),“OOP 对我来说仅意味着消息传递、**本地保留和保护以及状态过程的隐藏**,以及所有事物的极端后期绑定。” (2认同)

mre*_*mre 5

并非所有类都遵循封装范例(例如工厂类).对我来说,这增加了灵活性.无论如何,程序员而不是语言的责任是适当的范围.

  • `无论如何,程序员而不是语言的责任是适当的范围.你可以对内存管理提出同样的要求,知道给定机器上整数的字节数等等.一些语言设计者不同意什么属于语言的责任. (3认同)