17

It seems to be Java orthodoxy at this point that one should basically never use public fields for object state. (I don't necessarily agree, but that's not relevant to my question.) Given that, would it be right to say that from where we are today, it's clear that Java's public fields were a mistake/flaw of the language design? Or is there a rational argument that they're a useful and important part of the language, even today?

Thanks!

Update: I know about the more elegant approaches, such as in C#, Python, Groovy, etc. I'm not directly looking for those examples. I'm really just wondering if there's still someone deep in a bunker, muttering about how wonderful public fields really are, and how the masses are all just sheep, etc.

Update 2: Clearly static final public fields are the standard way to create public constants. I was referring more to using public fields for object state (even immutable state). I'm thinking that it does seem like a design flaw that one should use public fields for constants, but not for state… a language's rules should be enforced naturally, by syntax, not by guidelines.

Avi Flax
  • 297
  • 2
  • 7
  • 2
    What is your basis that they are indeed a flaw? – Aaron McIver Feb 21 '11 at 18:48
  • 1
    Is there a different way to create symbolic constant expressions in Java now? – Edward Strange Feb 21 '11 at 18:53
  • @Aaron I wasn't stating that they're a flaw, I was stating that I've perceived it to be orthodoxy at this point that one should never use public fields. That perception may be wrong, but it is indeed what I've perceived. – Avi Flax Feb 21 '11 at 20:44
  • @Crazy Eddie I forgot about that use, I was thinking more of the more common use of fields, state. I'll edit the question. – Avi Flax Feb 21 '11 at 20:45

6 Answers6

17

I like them, as long as the field is final and is only used internally in the application, not exposed in an API for other applications. This keeps your code shorter and more readable.

You should not expose public fields in an API because by exposing public fields, you also expose the implementation. If you expose it as a getXXX() method instead, you could change the implementation without changing the API interface. E.g. you could change and get the value from a remote service, but the applications that uses the API doesn't need to know this.

This is a viable design for public final fields in immutable classes.

From Effective Java:

Item 14: In public classes, use accessor methods, not public fields

...if a class is package-private or is a private nested class, there is nothing inherently wrong with exposing its data fields. This approach generates less clutter than the accessor-method approach.

While it's never a good idea for a public class to expose fields directly, it is less harmful if the fields are immutable.

See also Why shouldn't I use immutable POJOs instead of JavaBeans?

Jonas
  • 14,867
  • 9
  • 69
  • 102
  • Just wondering, what are your reasons for not exposing it in an API? – Steven Jeuris Feb 21 '11 at 19:20
  • 2
    @Steven: Because by exposing public fields, you also expose the implementation. If you expose it as a `getXXX()` method instead, you could change the implementation without changing the API interface. E.g. you could change and get the value from a remote service, but the applications that uses the API doesn't need to know this. – Jonas Feb 21 '11 at 19:37
  • @Jonas: Those are generally not candidates for constants in the first place. – Steven Jeuris Feb 21 '11 at 19:39
  • @Steven: I'm not talking about constants in the first place but **public final** fields in **immutable** classes. E.g. see [Why shouldn't I use immutable POJOs instead of JavaBeans?](http://stackoverflow.com/questions/3511120/why-shouldnt-i-use-immutable-pojos-instead-of-javabeans) – Jonas Feb 21 '11 at 19:41
  • @Jonas: That's a nice use case as well! Perhaps it's helpful to update your answer a bit to clarify. – Steven Jeuris Feb 21 '11 at 20:27
  • @Jonas I agree. While it's sensible not to use public fields for mutable state in an API, it's perfectly fine in application-level code. It does lead to fairly tightly-coupled code, but that's often OK. – Avi Flax Feb 22 '11 at 17:54
  • @Avi: Yes, with all good refactoring tools in e.g. Eclipse, that is not a problem as long as it is in your code. – Jonas Feb 22 '11 at 18:05
9

The use of get/set method pairs is the tragic historical design flaw. I can't think of another language that implements properties as verbosely and inefficiently.

kevin cline
  • 33,608
  • 3
  • 71
  • 142
  • 1
    While true, this is somewhat tangential to the point of the question, which is (essentially) that given the choice between set/get methods and public fields, are there any good reasons to prefer fields in some situation? That other languages offer better solutions to the problem seems to me to be irrelevant. – Jules Apr 18 '17 at 21:12
  • Uh, doesn't c++? – Shanteva Apr 23 '21 at 02:14
  • @Shanteva: C++ templates are quite powerful. It should be straightforward to write a Property template class that allows fetching but not updating, so that one can write: public: Property mass. Java is statically typed but suffers greatly from it's lack of a metalanguage and compile-time type calculus. In C++ it's fairly straightforward to create classes to support compile-time type checking of physical units. In Java, for all it's vaunted safety advantages over C++, that's impossible. – kevin cline Apr 24 '21 at 04:10
  • Annotation processors like Lombok fill that niche – Shanteva Apr 25 '21 at 12:40
  • @Shanteva: Are you referring to annotation processors that massage the emitted byte code? That's hardly comparable to in-built meta-programming like the C++ template processor. Java annotation processors are written at a low level, require specialized knowledge of the JVM byte code, require a separate build and deployment. and must be updated with each release of the Java compiler. I've never seen a project that included it's own annotation processor. – kevin cline Apr 27 '21 at 01:17
5

I think public fields are okay for a class that is essentially a value type like a complex number or a point, where the class does little more than group primitive types together like a C-style struct and maybe define a few operators.

Karl Bielefeldt
  • 146,727
  • 38
  • 279
  • 479
  • 2
    `java.awt.Point` and friends are a bit of a nightmare. – Tom Hawtin - tackline Feb 22 '11 at 02:22
  • @TomHawtin-tackline: The problem with `Point` is that it's ambiguous whether a *variable* of type `Point` is supposed to encapsulate a locations, or is supposed to encapsulate the identity of an entity with a location that can change. Conceptually, I would regard code which passes around `Point` to be much like code which passes around arrays. – supercat Dec 23 '13 at 20:33
  • So if I get a `Point` and modify it, I should expect the object it refers to to cleanly update on screen? No, the problem with `Point` is that it is mutable. We had `String`/`StringBuffer` but the idea didn't seem to get through. / Passing arrays around does have similar problems. – Tom Hawtin - tackline Dec 24 '13 at 08:42
  • Now that I'm looking at this, it would be horrible to have a mutable 'Complex' class, just as it was horrible for java.util.Date to be mutable. – kevin cline Apr 24 '21 at 04:14
5

To define public constants it is still useful. E.g.

public static final int DAYS_IN_WEEK = 7;

However, do still prefer enum's where possible. E.g.

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

To simulate simple struct classes it is also useful. No reason to create a getter and setter for every field, when they are all public anyhow.

class Point
{
    public int x, y;
    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }
}
Steven Jeuris
  • 5,804
  • 1
  • 30
  • 52
  • But then again, many would argue structs have no place in a language like Java... –  Feb 21 '11 at 19:22
  • 1
    @delnan: They are almost the same as JavaBeans, but JavaBeans is much more verbose and not threadsafe. See [Why shouldn't I use immutable POJOs instead of JavaBeans?](http://stackoverflow.com/questions/3511120/why-shouldnt-i-use-immutable-pojos-instead-of-javabeans) – Jonas Feb 21 '11 at 21:20
  • Some Android specific observations: Enums are slower to evaluate than ints and should be avoided . Also, fields frequently accessed by setters and getters in tight loops can also benefit from being public. – Nailer Feb 22 '11 at 08:37
3

Before IDEs became widespread, making all your fields public was a powerful tool to create prototypes/proofs of concepts quickly.

Nowadays there's very little excuse for using them, when you can generate a getter/setter pair with a click of the mouse.

biziclop
  • 3,351
  • 21
  • 22
  • 4
    But 10 `public final` fields is more readable than 10 `getXXX()` methods. – Jonas Feb 21 '11 at 19:44
  • 1
    @Jonas Yeah, but we're not talking about final fields here. If your public final fields are also static, they are constants, and a `const` keyword would be enough, if they aren't static, they are a serious violation of encapsulation. – biziclop Feb 21 '11 at 20:04
  • 3
    @biziclop according to [Wikipedia](http://en.wikipedia.org/wiki/List_of_Java_keywords): "although reserved as a keyword in Java, const is not used and has no function" – Avi Flax Feb 21 '11 at 20:51
  • @Avi Flax Yeah, but it could have been used to mark constants, thus eliminating the need to declare constants as public fields. – biziclop Feb 21 '11 at 20:59
  • 2
    Assuming a getter/setter pair is at all appropriate, that is. It often isn't. – David Thornley Feb 21 '11 at 21:15
  • @biziclop agreed – Avi Flax Feb 22 '11 at 01:50
2

This is subjective, but my opinion is that the whole public/private notion is outdated and backwards.

In python there's no public/private; everything is public basically. Hasn't caused many problems.

In Java you tend to create pointless getters/setters for each field to avoid the sin of marking them "public". (IMHO if you find yourself doing that you should just mark them public).

hasen
  • 1,389
  • 1
  • 13
  • 15
  • Python does allow you to mark things as private by prefixing the names with __. It's not 100% private, since there are still ways to access those variables and methods, but then in C# you can do similar things with reflection. – Adam Lear Feb 22 '11 at 06:22