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.

4
  • 2
    What is your basis that they are indeed a flaw? Feb 21, 2011 at 18:48
  • 1
    Is there a different way to create symbolic constant expressions in Java now? Feb 21, 2011 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, 2011 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, 2011 at 20:45

6 Answers 6

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?

7
  • Just wondering, what are your reasons for not exposing it in an API? Feb 21, 2011 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, 2011 at 19:37
  • @Jonas: Those are generally not candidates for constants in the first place. Feb 21, 2011 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?
    – Jonas
    Feb 21, 2011 at 19:41
  • @Jonas: That's a nice use case as well! Perhaps it's helpful to update your answer a bit to clarify. Feb 21, 2011 at 20:27
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.

5
  • 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, 2017 at 21:12
  • Uh, doesn't c++?
    – Shanteva
    Apr 23, 2021 at 2: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<Gram> 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. Apr 24, 2021 at 4:10
  • Annotation processors like Lombok fill that niche
    – Shanteva
    Apr 25, 2021 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. Apr 27, 2021 at 1: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.

4
  • 2
    java.awt.Point and friends are a bit of a nightmare. Feb 22, 2011 at 2: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, 2013 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. Dec 24, 2013 at 8: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. Apr 24, 2021 at 4: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;
    }
}
3
  • But then again, many would argue structs have no place in a language like Java...
    – user7043
    Feb 21, 2011 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?
    – Jonas
    Feb 21, 2011 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, 2011 at 8: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.

6
  • 4
    But 10 public final fields is more readable than 10 getXXX() methods.
    – Jonas
    Feb 21, 2011 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, 2011 at 20:04
  • 3
    @biziclop according to Wikipedia: "although reserved as a keyword in Java, const is not used and has no function"
    – Avi Flax
    Feb 21, 2011 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, 2011 at 20:59
  • 2
    Assuming a getter/setter pair is at all appropriate, that is. It often isn't. Feb 21, 2011 at 21:15
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).

1
  • 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, 2011 at 6:22

Not the answer you're looking for? Browse other questions tagged or ask your own question.