为什么Java中的属性可以公开?
正如大家所知,Java遵循面向对象的范式,数据封装说,对象的字段(属性)应该为外部世界隐藏,只能通过方法访问,或者方法是外部类的唯一接口世界。 那么为什么有可能将Java中的一个字段声明为public,这将违背数据封装的范式?
我认为这是可能的,因为每个规则都有其例外,在某些情况下,每个最佳做法都可以被忽略。
例如,我经常公开公共静态最终数据成员(例如,常量)。 我不认为这是有害的。
我会指出这种情况在Java以外的其他语言中也是如此:C ++,C#等
语言不一定总是保护我们自己。
在奥利的例子里,如果我这样写,有什么害处呢?
public class Point { public final int x; public final int y; public Point(int p, int q) { this.x = p; this.y = q; } }
它是不可变的,线程安全的。 数据成员可能是公开的,但是你不能伤害他们。
另外,在Java中,“私有”并不是私有的,这是一个肮脏的小秘密。 你总是可以使用reflection来解决它。
所以放松一下 也不是那么坏。
为了灵活性。 如果我不能写,那将是一个巨大的痛苦:
class Point { public int x; public int y; }
把这个隐藏在吸气人员和安装人员身后是没有什么好处的。
因为刚性的“数据封装”不是唯一的范例,也不是面向对象的强制性特征。
而且,更重要的是,如果一个数据属性具有公共setter方法和一个公共getter方法,并且这些方法除了实际设置/获取属性之外什么都不做,那么保持私有性的意义何在?
并不是所有的类都遵循封装范例(例如工厂类)。 对我来说,这增加了灵活性。 无论如何,程序员的责任,而不是语言,适当的范围。
讨论公共variables的好方面…喜欢它… 🙂
使用public
variables可能有很多原因。 让我们逐个检查一下:
性能
虽然很less见,但会有一些重要的情况。 在某些情况下,方法调用的开销将不得不被避免。
常量
我们可以使用公共variables作为常量,在构造函数中初始化后不能改变。 它也有助于性能。 有时这些可能是静态常量,比如连接数据库的string。 例如,
public static final String ACCEPTABLE_PUBLIC = "Acceptable public variable";
其他情况
有些情况下, public
没有区别,或者有一个吸气器,二传手是不必要的。 Point
一个很好的例子就是作为答案。
面向对象的devise不需要封装。 对于像Java这样的语言来说,这是一个最好的实践,与OO相比,这个语言的devise更为重要。
出于一个简单的原因,总是封装在Java中是最好的做法。 如果你不封装,你不能以后改变对象的签名封装。 例如,如果你的员工有一个名字,并且公开,那么它是employee.name。 如果你以后想要封装它,你最终会得到employee.getName()和employee.setName()。 这当然会破坏使用你的Employee类的任何代码。 因此,在Java中,封装所有内容是最好的做法,这样就不必更改对象的签名。
一些其他OO语言(ActionScript3,C#等)支持真正的属性,添加getter / setter不会影响签名。 在这种情况下,如果你有一个getter或者setter,它会用相同的签名replace公有属性,所以你可以很容易地来回切换而不会破坏代码。 在这些语言中,总是封装的做法不再是必要的。
Java是C风格语法语言的一个分支。 这些语言支持struct
,这些struct
是通常被认为是“单项”的内存块的固定偏移别名。 换句话说,数据结构是用struct
来实现的。
虽然使用struct直接违反了面向对象编程的封装目标,但是当Java被首次发布时,大多数人在迭代(过程)编程方面胜任了很多。 通过将成员public
你可以像使用C struct
一样有效地使用Java类,尽pipe这两个环境的底层实现是完全不同的。
有一些情况下,你甚至可以用适当的封装来做到这一点。 例如,许多数据结构由两个或多个指针的节点组成,一个指向“包含”的数据,一个或多个指向其他数据结构的“其他”连接。 在这种情况下,你可能会创build一个在“数据结构”类(比如内部类)之外没有可见性的私有类,因为所有的代码都是包含在同一个.java
文件中的,删除内部类的.getNext()
方法作为性能优化。
我相信数据封装更像是一个附加function,而不是一个强制性的要求或规则,因此编码者可以自由地运用他/她的智慧来应用这些function,并根据他们的需要调整它们。因此,灵活是!
一个相关的例子可以是@Oli Charlesworth给出的例子
我只是一个初学者,但如果公开声明不存在,Java开发将是非常复杂的理解。 因为我们使用公共,私人和其他语句来简化代码的理解,就像我们使用和其他人创build的jar子一样。 我想说的是,我们不需要发明,我们需要学习,继续下去。
我希望从我的英语道歉,我正在努力改善,我希望在未来写清楚。
可访问性修饰符是OO语言中封装概念的一个实现(我将这种实现看作是放宽这个概念并允许一些灵活性的一种方式)。 有纯粹的面向对象语言,没有可访问性修饰符,即Smalltalk。 在这种语言中,所有的状态(实例variables)都是私有的,所有的方法都是公共的,唯一的办法就是通过实例方法修改或者查询对象的状态。 方法缺less可接受性修饰符迫使开发人员采用某些约定,例如,私有协议中的方法(协议是组织类中的方法的一种方法)不应该在类之外使用,但是不会在语言结构中使用执行这个,如果你想你可以调用这些方法。
使用公有与否真的取决于是否有一个不变的维护。 例如,纯数据对象不以任何方式限制状态转换,因此使用一堆访问器封装成员是没有意义的,这些访问器不提供将数据成员公开的function。
如果您为特定的非私有数据成员同时拥有getter和setter,而这些数据成员不提供比获取和设置function更多的function,那么您可能需要重新评估devise或使其成为公共成员。
除了懒惰之外,我真的不能想到一个不使用getter和setter的好理由。 有效的Java被广泛认为是有史以来最好的Java书籍之一,它总是使用getter和setter。 如果你不需要知道为什么你总是使用getter和setter,那么跳过这一段。 我不同意1号答案的一个例子,不要使用getter和setter。 这有几个问题。 如果你需要改变号码的types怎么办? 例如,有一次当我用graphics进行实验的时候,我发现自己经常改变主意,想要将位置存储在Java Shape中,或者直接将其存储为int。 如果我没有使用getter和setter,并且我改变了这个,我将不得不改变所有使用该位置的代码。 但是,如果我没有,我只能改变getter和setter。
吸气和安装人员是Java的痛苦。 在Scala中,您可以创build公共数据成员,然后创buildgetter和or setter,而不必更改API。 这给你两全其美! 也许,Java有一天会解决这个问题。