Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the deal with Java's public fields?

Tags:

java

oop

I've been reading two articles (1)(2) on javaworld.com about how all class fields should be private and getter/setter methods are just as bad. An object should act on the data it has rather than allowing access to it.

I'm currently working on a University assignment for Connect Four. In designing the program the Agents playing the Game need access to the Board's state (so they can decide what to move). They also need to pass this move to the Game so it can validate it as a legal move. And during deciding what to move pieces are grouped into Threats with a start and end Points.

Board, Threat and Point objects don't really do anything. They are just there to store related data that can be accessed in a human readable way.

At the start of design I was representing Points on the board as two element int arrays, however that got annoying when creating points or referencing components of them.

So, the class:

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

Perfect in every way I can think of. Except it breaks every rule I've learned. Have I sinned?

like image 511
AnnanFay Avatar asked Oct 31 '11 20:10

AnnanFay


People also ask

Can fields be public in Java?

In Java, making a class field public can cause lot of issues in a program. For instance you may have a class called MyCompany. This class contains an array of String companies. You may have assume that this array will always contain 4 names of companies.

What is an instance field?

An instance field, in C#, is a variable of any type contained within a class or struct, and is used to store object data. It is a member of its containing type with one copy of the field for each instance of the containing type. Instance fields represent the data of a class that enables an object to maintain its state.

Are Java fields public by default?

No, they're not the same. The lack of an access modifier defaults to package-private. No modifier in Java is the same as protected. What is the Package?

Why should instance variables be private?

Instance variables are made private to force the users of those class to use methods to access them. In most cases there are plain getters and setters but other methods might be used as well.


1 Answers

Public fields expose the representation of an object to its callers, i.e. if the representation has to change, so do the callers.

By encapsulating the representation, you can enforce how callers interact with it, and can change that representation without having to modify the callers provided the public api is unchanged. In any non-trivial program, encapsulation is necessary to achieve reasonable maintainability. However, while you need capsules, their proper granularity may be larger than a single class. For instance, it makes little sense to encapsulate an Iterator from the internal representation of the Collection it operates on.

With that out of the way, let's look at your example:

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

The internal representation of that class is exceedingly unlikely to change, so hiding the structure of the representation by making the fields private has no benefit. However, I'd prevent callers from modifying a Point once it has been constructed:

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

so that a class that actually wishes to encapsulate its state can return its Point without leaking its internal representation, and use a given Point in its representation without capturing it. This also fits nicely with the mathematical notion of a point, which has no identity or changing state.

In designing the program the Agents playing the Game need access to the Board's state (so they can decide what to move). They also need to pass this move to the Game so it can validate it as a legal move. And during deciding what to move pieces are grouped into Threats with a start and end Points.

Board, Threat and Point objects don't really do anything. They are just there to store related data that can be accessed in a human readable way.

Now this sounds like a wasted opportunity for encapsulation: The agents should really not be permitted to arbitrarily modify the board, but be restricted to legal moves. Why is it the responsibility of class Game to decide what a legal move is, when the state being updated resides in class Board? If the Board were to validate the moves itself, no caller, and in particular no agent, could violate the rules of the game:

public class Board {     // private fields with state      // public methods to query state      public void perform(Move move) throws IllegalMoveException; } 
like image 150
meriton Avatar answered Sep 30 '22 16:09

meriton