此时,Java的公共领域是否只是一个悲剧的历史设计缺陷?[关闭]


17

在这一点上,Java似乎是正统的,基本上不应将公共字段用于对象状态。(我不一定同意,但这与我的问题无关。)考虑到这一点,可以说从今天开始的今天,很显然Java的公共领域是语言设计的错误/缺陷?还是有一个合理的论据,即使在今天,它们仍然是语言的有用和重要的一部分?

谢谢!

更新:我知道更优雅的方法,例如C#,Python,Groovy等。我不是直接在寻找这些示例。我真的只是想知道是否还有人在掩体深处,喃喃地谈论着真正的公共场所有多美妙,群众如何全都是羊,等等。

更新2:显然,静态的最终公共字段是创建公共常量的标准方法。我指的是将公共字段用于对象状态(甚至是不可变状态)。我认为应该将公共字段用作常量而不是状态,这似乎是一种设计缺陷,一种语言的规则应自然而然地通过语法而不是准则来强制执行。


2
您认为它们确实是缺陷的依据是什么?
亚伦·麦克弗

1
现在有没有其他方法可以在Java中创建符号常量表达式?
爱德华·

@Aaron我不是在说它们是一个缺陷,而是在说我认为这是正统的,因此永远不要使用公共领域。这种看法可能是错误的,但确实是我所理解的。
Avi Flax

@Crazy Eddie我忘记了这种用法,我在想更多的字段,状态的更常见用法。我将编辑问题。
Avi Flax

Answers:


14

我喜欢它们,只要该字段是最终字段,并且仅在应用程序内部使用,而不在其他应用程序的API中公开。这样可以使您的代码更短,更易读。

您不应该公开API中的公共字段,因为通过公开公共字段,您还可以公开实现。如果getXXX()改为将其公开为方法,则可以在不更改API接口的情况下更改实现。例如,您可以更改并从远程服务中获取价值,但是使用API​​的应用程序不需要知道这一点。

这是不可变类中public final字段的可行设计。

有效的Java中

项目14:在公共类中,使用访问器方法,而不是公共字段

...如果一个类是程序包私有的或私有嵌套的类,则公开其数据字段没有内在的错误。与访问器方法相比,此方法产生的混乱更少。

虽然公开类直接公开字段从来都不是一个好主意,但是如果字段是不可变的,则危害较小。

另请参见为什么我不应该使用不可变的POJO而不是JavaBean?


只是想知道,您没有在API中公开它的原因是什么?
史蒂文·杰里斯

2
@Steven:因为通过公开公共字段,您还公开了实现。如果getXXX()改为将其公开为方法,则可以在不更改API接口的情况下更改实现。例如,您可以更改并从远程服务中获取价值,但是使用API​​的应用程序不需要知道这一点。
乔纳斯(Jonas)

@Jonas:通常,这些通常不是常量的候选对象。
史蒂文·杰里斯

@Steven:我不是在首先讨论常量,而是在不可变类中公开final字段。例如,为什么我不应该使用不可变的POJO而不是JavaBean?
乔纳斯(Jonas)

@Jonas:这也是一个很好的用例!也许可以对答案进行一些澄清以帮助您。
史蒂文·杰里斯

9

获取/设置方法对的使用是悲惨的历史设计缺陷。我想不出另一种语言来冗长和低效地实现属性。


1
的确如此,这与问题的要点相切,(基本上)鉴于给定了设置/获取方法和公共字段之间的选择,在某些情况下是否有充分的理由偏爱字段?在我看来,其他语言为该问题提供更好的解决方案似乎无关紧要。
Jules

5

我认为,对于本质上是诸如复数或点之类的值类型的类而言,公共字段是可以的,其中该类所做的不过是像C型结构那样将原始类型组合在一起,并可能定义了一些运算符。


2
java.awt.Point和朋友有点噩梦。
Tom Hawtin-大头钉

@ TomHawtin-tackline:问题在于类型变量Point是否应该封装位置,或者应该使用可以更改的位置封装实体的身份,这是模棱两可的。从概念上讲,我认为传递的代码很像传递数组的代码。PointPoint
2013年

因此,如果得到Point并修改它,我应该期望它所指向的对象在屏幕上干净地更新吗?不,问题Point在于它是可变的。我们有String/ StringBuffer但这个想法似乎没有成功。/传递数组确实有类似的问题。
汤姆·霍顿

5

定义公共常量仍然有用。例如

public static final int DAYS_IN_WEEK = 7;

但是,在可能的情况下,仍请选择枚举。例如

public enum Day {
    SUNDAY, MONDAY, TUESDAY, WEDNESDAY, 
    THURSDAY, FRIDAY, SATURDAY 
}

为了模拟简单的结构类,也是有用的。无论如何,当每个领域都是公开的时候,没有理由为每个领域创建一个getter和setter方法。

class Point
{
    public int x, y;
    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }
}

但话又说回来,许多人会认为结构在Java之类的语言中没有地位...

1
@delnan:它们几乎与JavaBeans相同,但是JavaBeans更加冗长,而且不是线程安全的。请参阅为什么不使用不可变的POJO而不是JavaBean?
乔纳斯(Jonas)

Android的一些特定观察结果:枚举的计算速度比整数慢,应避免使用。同样,设置者和获取者经常在紧密循环中访问的字段也可以从公开中受益。
Nailer

2

在IDE普及之前,将所有领域公开都是一种快速创建概念原型/证明的强大工具。

如今,当您可以通过单击鼠标来生成一个getter / setter对时,几乎没有使用它们的借口。


4
但是10个public final字段比10个getXXX()方法更具可读性。
乔纳斯(Jonas)

1
@Jonas是的,但我们在这里不讨论最终领域。如果您的public final字段也是静态的,则它们是常量,并且const关键字就足够了;如果它们不是静态的,则它们严重违反了封装。
biziclop 2011年

3
根据Wikipedia的 @biziclop :“尽管在Java中保留为关键字,但未使用const并且没有任何功能”
Avi Flax

@Avi Flax是的,但是它本可以用来标记常量,因此不需要将常量声明为公共字段。
biziclop 2011年

2
即,假设一对getter / setter对完全合适。通常不是。
David Thornley

2

这是主观的,但我认为整个公共/私人概念已经过时和落后。

在python中没有公共/私有;一切基本上都是公开的。并没有引起很多问题。

在Java中,您倾向于为每个字段创建无意义的getter / setter,以避免将它们标记为“ public”的罪过。(恕我直言,如果您发现自己这样做,则应将其标记为公开)。


Python确实允许您通过在名称前加上__来将其标记为私有。它不是100%私有的,因为仍有访问这些变量和方法的方法,但是在C#中,您可以使用反射来做类似的事情。
亚当李尔
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.