Home Object fields
Minimize your fields
You should keep the number of fields in your class to a bare minimum needed to successfully complete your assignment without compromising on the other principles of style. If it is possible to perform a task via passing data around via parameters and returns instead of using a field, you should do so.
The reasons why we want you to minimize the number of fields you need to use are identical to those outlined in the section on Minimizing scope – the more fields you have, the more potential interactions there are between methods, and the higher the odds are of your program developing bugs.
Having multiple fields unnecessary fields also starts to violate the principle of modularity. If your method is dependent on 5-6 different fields to be in some particular state in order to function effectively, we really cannot say that the method is all that modular. Parameters and returns are the key mechanisms we should be using to pass data back and forth.
Fields should be reserved to store data which must be persisted between multiple independent calls to that method or other methods within the class, or when not using a field would result in drop in efficiency.
Make all fields private
You should always make all your fields private. This prevents the client from looking at and tinkering with the internal details of your code. The client should only ever interact with your object through a carefully-defined set of public methods to prevent subtle bugs from occurring.
There are a few exceptions to this rule, but we will explicitly tell you when that is the case.
While making fields public may seem convenient at first, it frequently results in the
client and implementor classes becoming tangled together. For example, say I wanted to
create a Point
class to represent an x-y pair of coordinates. In that case, I
could naively do something like this:
Point class:
public class Point { public double x; public double y; public Point(double x, double y) { this.x = x; this.y = y; } public double getMagnitude() { return Math.sqrt(x * x + y * y); } public double getAngle() { return Math.atan2(this.y, this.x); } }
Client usage:
Point p = new Point(3.2, -6.6); double newX = p.x * 2; p.y = foo(p, bar);
And this might work, for a little while. But then, let's say that as I kept working on my program, I slowly started to realize that it would have been better for me to store the data directly as a magnitude and value – doing so would dramatically simply the math and angle calculations I'm doing.
But now I'm stuck. If change my fields to magnitude
and angle
,
all of the client code I wrote before would no longer work since they were all directly
accessing those fields. If I keep the x and y fields, and add the magnitude and angle
fields on top of that, then my data would fall out of sync since some clients would modify
some the data, but not all of them.
However, if I had forced the clients to manipulate my class exclusively through public methods, then this problem would have been a much easier problem to solve:
public class Point { private double magnitude; private double angle; public Point(int x, int y) { this.setXY(x, y); } public getMagnitude() { return this.magnitude; } public setMagnitude(double magnitude) { this.magnitude = magnitude; } public getAngle() { return this.angle; } public setAngle(double angle) { this.angle = angle; } public getX() { return Math.cos(angle) * magnitude; } public setX(int x) { this.setXY(x, this.getY()); } public getY() { return Math.sin(angle) * magnitude; } public setY(int y) { this.setXY(this.getX(), y); } public setXY(int x, int y) { this.magnitude = Math.sqrt(x * x + y * y); this.angle = Math.atan2(y, x); } }
Now, no matter what fields we use, we can always adjust our methods so that they
continue work and the client can still use our Point
class uninterrupted. If
the client wants to do mostly x/y manipulations, they can still do so.
Unfortunately, in the pursuit of good style, we've ended up making our code fairly bloated, and a common question many students will have is if there's a way of accomplishing the same thing without having to tediously write multiple getter and setter methods.
There is such a way in other programming languages using something called properties, but alas, Java currently doesn't have properties, so we're stuck with writing out getters and setters for the foreseeable future.
Because writing getters and setters can often be tedious, we will on occasion explicitly
grant you permission to make classes with public fields when the vast majority of the
manipulations you do to that class is on those fields. Usually, we allow public fields on
classes such as LinkedListNode
or TreeNode
which are primarily
implementation detail anyway, are likely to be private inner classes to some
LinkedList
or Tree
class, and so do not need a stringent interface.
Field initialization
Always initialize your fields inside your constructor, not outside.
You should never directly initialize your field, like so:
public class Foo { private int myField = 3; private Random rand = new Random(); public Foo() { // ... } // ... }
Rather, you should initialize everything inside of your constructor, like so:
public class Foo { private int myField; private Random rand; public Foo() { this.myField = 3; this.rand = new Random(); } // ... }
There are several reasons for this. One reason is that it's not always possible to directly declare and initialize certain fields, especially when our initialization code requires some additional logic.
The other reason is for consistency. In many cases, we need to initialize fields based on parameters that we pass into our constructor. In those cases, the only place where we can initialize our fields is inside the constructor itself, and having some fields be initialized in the constructor vs directly looks inconsistent:
public class Foo { private Scanner input; private int size; private Random rand = new Random(); public Foo(Scanner input, int size) { this.input = input; this.size = size; } // ... }
Again, an important aspect of style is consistency. If some of our fields need to be initialized in the constructor, then it's best to make all of them be initialized there:
public class Foo { private Scanner input; private int size; private Random rand; public Foo(Scanner input, int size) { this.input = input; this.size = size; this.rand = new Random(); } // ... }
However, do note that it is ok to directly declare constants like we always have been doing so far:
public class Foo { public static final int MY_CONSTANT_VALUE = 42; private Scanner input; private int size; private Random rand; public Foo(Scanner input, int size) { this.input = input; this.size = size; this.rand = new Random(); } // ... }
The reason for this is because there's no other way to do this: it's impossible to set a constant inside a constructor, or any other method (if you could, they wouldn't be constants).
Using 'this'
You should always use the this
keyword when using a non-static field to
help make the difference between local variables/static methods vs fields/instance
methods as clear as possible.
For example, we would consider the following to be bad style:
public class Foo { private int myField; public class Foo(int data) { myField = transform(data); } private int transform(int data) { // ... } }
The corrected version would look like this:
public class Foo { private int myField; public class Foo(int data) { this.myField = this.transform(data); } private int transform(int data) { // ... } }
Both the field and the method belong to the instance, so we'll use the this
keyword to explicitly indicate so.
The reason we are making you do this is because doing so will force you to explicitly
think about what exactly an object is and how it works whereas omitting the
this
keyword will make it easier to forget.
However, suppose our class also happened to contain some static attribute, such as
a public static final
constant. In this case, since the field is static,
it does NOT belong to the instance, so we would NOT use the this
keyword:
public class Foo { public static final int MY_CONSTANT = 10; private int myField; private int otherField; public class Foo(int data) { this.myField = this.transform(data); this.otherField = this.transform(MY_CONSTANT); } private int transform(int data) { // ... } }
You may choose to access any static attributes either by using the unqualified name, or via the class name. For example, it would also be acceptable to write the above code like so:
public class Foo { public static final int MY_CONSTANT = 10; private int myField; private int otherField; public class Foo(int data) { this.myField = this.transform(data); this.otherField = this.transform(Foo.MY_CONSTANT); } private int transform(int data) { // ... } }
That is, using MY_CONSTANT
and Foo.MY_CONSTANT
are both
acceptable.