不可变类型:公共最终字段与 getter
我需要一个小的容器类来存储一些应该不可变的字符串。由于 String 本身是不可变的类型,我想到了类似的事情:
public final class Immu
{
public final String foo;
public final String bar;
public Immu(final String foo, final String bar)
{
this.foo = foo;
this.bar = bar;
}
}
许多人似乎根本反对使用公共字段并使用 Getters 代替。恕我直言,在这种情况下这只是样板,因为字符串本身是不可变的。
我对此可能缺少其他想法吗?
I need a small Container-Class for storing some Strings which should be immutable. As String itself is an immutable type, I thought of something like that:
public final class Immu
{
public final String foo;
public final String bar;
public Immu(final String foo, final String bar)
{
this.foo = foo;
this.bar = bar;
}
}
Many people seem to object using public fields at all and use Getters instead. IMHO this would be just boilerplate in this case, because String itself is immutable.
Other thoughts I may be missing on this one?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
我会做你认为最简单、最清晰的事情。如果您有一个仅由有限数量的类使用的数据值类。 esp 是一个包本地类。那么我会避免 getter/setter 并使用包本地或公共字段。
如果您有一个希望其他模块/开发人员使用的类,从长远来看,遵循 getter/setter 模型可能是更安全的方法。
I would do what you believe is simplest and clearest. If you have a data value class which is only used by a restricted number of classes. esp a package local class. then I would avoid getter/setters and use package local or public fields.
If you have a class which you expect other modules/developers to use, following a getter/setter model may be a safer approach in the long run.
问题在于统一访问原则。您稍后可能需要修改
foo
,以便通过方法获取而不是修复它,并且如果您公开该字段而不是 getter,则需要破坏您的 API。The problem is the uniform access principle. You may later need to modify
foo
so that it's obtained through a method instead of being fixed, and if you exposed the field instead of a getter, you'll need to break your API.这个答案被排除了:
为什么不呢?
This answer is obviated:
Why not
我发现这个帖子希望得到一些实际的论点,但我在这里看到的答案对我没有多大帮助。经过更多的研究和思考,我认为必须考虑以下几点:
public final
看起来最干净。如果您处于开发中期,并且没有任何指导方针阻止您,并且项目是孤立的,或者您可以控制所有涉及的项目,我建议对不可变类型使用
public final
。如果您稍后决定需要 getter,Eclipse 会提供Refactor
->Encapsulate Field...
自动创建这些字段并调整对该字段的所有引用。I found this thread hoping for some actual arguments, but the answers I've seen here didn't help me all that much. After some more research and thinking I think the following has to be considered:
public final
looks cleanest for immutable types.public final
clearly tells the programmer that no hidden magic is occuring and the object is inherently dumb :)If you're mid development and no guideline is stopping you and the project is isolated or you have control over all involved projects I'd suggest using
public final
for immutable types. If you decide you need getters later on, Eclipse offersRefactor
->Encapsulate Field...
which automatically creates these and adjusts all references to the field.我在家庭项目中使用 public-final-field (反?)模式,这些类基本上是带有构造函数的不可变数据结构,以及绝对基础知识,如 equals()、hashCode()、toString() 等(如果需要) 。 (我避免使用“结构”这个词,因为它有各种不同的语言解释。)
我不会将这种方法带到其他人的代码库(工作、公共项目等)中,因为它可能与其他代码不一致,优先考虑“在罗马时”或“最少惊喜”等原则。
也就是说,对于 Daniel C. Sobral 和 aioobe 的回答,我的态度是,如果类设计由于不可预见的发展而成为问题,那么只需在 IDE 中花费 30 秒即可将字段私有化并添加访问器,仅此而已除非有数百个引用,否则修复损坏的引用的时间不会超过 5 或 10 分钟。任何失败的结果都会得到它应该首先进行的单元测试。:-)
[编辑:Effective Java 非常坚决地反对这个想法,同时指出它对不可变字段“危害较小”。]
I use the public-final-field (anti?)pattern on home projects for classes which are basically an immutable data structure with a constructor, along with absolute basics like equals(), hashCode(), toString(), etc. if required. (I'm avoiding the word "struct" because of the various different language interpretations of it.)
I wouldn't bring this approach to someone else's codebase (work, public project, etc) because it would likely be inconsistent with other code, and principles like When In Rome or Least Surprise take priority.
That said, with regard to Daniel C. Sobral's and aioobe's answers, my attitude is that if the class design becomes a problem because of unforeseen developments, it's the work of 30 seconds in an IDE to privatise the fields and add accessors, and no more than 5 or 10 minutes to fix broken references unless there are hundreds of them. Anything that fails as a result gets the unit test it should have had in the first place.:-)
[Edit: Effective Java is quite firmly against the idea, while noting that it's "less harmful" on immutable fields.]
忘记封装、不变性、优化和所有其他大词。如果你想编写好的java代码,我建议你只使用getter,因为它是java友好的,最重要的是它可以节省大量的时间来搜索原因。
例如,您在编写代码时可能不会期望使用流,但后来您发现
这个列表可长可短,或者可能对您的用例没有任何意义。但你必须花时间说服自己(或你的代码审查者)为什么你可以或应该反抗 Java 正统观念。
最好只编写 getter/setter 并花时间做一些更有用的事情:比如抱怨 java
Forget about encapsulation, immutability, optimization and all other big words. If you are trying to write good java code, I would recommend you just use getter simply because it is java friendly, and most importantly it saves ton of time googling why.
For example, you probably would not expect using streams when you write the code, but later you found
This list can be long or short or may be none of them makes any sense to your use case. But you have to spend time convincing yourself (or your code reviewers) why you can or should rebel against java orthodoxy.
It is better to just write the getter/setter and spent the time for something more useful: like complaining java
从 Java 16 开始,您可以使用记录。
记录的所有属性都自动为最终属性,并且它自动具有
equals(…)
和toString()
等方法以及构造函数。属性的 getter 与属性具有相同的名称,在本例中,它们是
foo()
和bar()
。这些方法可以被覆盖,更多信息文档中。
Since Java 16, you can use records.
All of a record's attributes are automatically final and it automatically has methods like
equals(…)
andtoString()
and the constructor.The getters of the attributes have the same name as the attributes, in this case, they are
foo()
andbar()
.The methods can be overridden, more information is in the documentation.
目前尚不清楚是否有人会通过 API 使用您的代码。
如果您稍后需要验证输入,您也会错过验证输入的机会。
It is not very clear if someone is going to use your code through an API.
You are also missing an opportunity to validate the input, if you are going to require some later.
对于这样的小工作,使用 public Final 可能没问题,但是它不能作为标准做法,
请考虑下面的情况。
当然,由于是不可变的,这个对象是通过构造函数初始化的,然后直接访问。我必须告诉你其中的问题吗?很明显!
考虑您的客户编写如下代码 -
这可行吗?您的客户端库能够操纵对象的状态,或者更确切地说能够侵入您的运行时表示。这是一个巨大的安全风险,当然像 SONAR 这样的工具可以预先发现它。但只有当你使用 getter-setter 时它才可以管理。
如果您正在使用 getters,您可以很好地编写
这可以防止您受到潜在的安全威胁。
查看上面的示例,如果您使用数组,则强烈建议不要使用
public final
。在这种情况下,它就不能成为标准。像我这样的人将避免使用无法成为所有数据类型统一标准的代码实践。你呢?Using public final may be fine for such small job, but it cannot be adapted as a standard practice,
Consider the situation below.
Of course, being immutable, this object is initialized vis constructor, and then accessed directly. Do I have to tell you the problem in it? It’s evident!
Consider your client writing the code like below -
Is this doable? Your client libraries are able to manipulate the state of your objects, or rather able to hack within your runtime representation. This is a huge security risk, and of course tools like SONAR catch it upfront. But its manageable only if you are using getter-setters.
If you are using getters, you can very well write
This prevents you from potential security threat.
Looking at the above example, using
public final
is strongly discouraged if you are using arrays. In such case, it cannot become a standard. A person like me, will refrain from using a code practice that cannot become a uniform standard across all data types. What about you?