A class in object-oriented programming is a collection of data and methods to act on said data.

Let’s consider a basic class called Mechanical Pencil:

public class MechanicalPencil{
	private String color;
	private double leadSize;
	private double springWeight;
 
	public MechanicalPencil(){
	}
 
	public MechanicalPencil(String color, double leadSize, double springWeight){
		this.color = color;
		this.leadSize = leadSize;
		this.springWeight = springWeight;
	}
 
	public void setColor(String color){
		this.color = color;	
	}
 
	public void setLeadSize(double leadSize){
		this.leadSize = leadSize;
	}
 
	public void setSpringWeight(double springWeight){
		this.springWeight = springWeight;
	}
 
	public String getColor(){
		return this.color;
	}
 
	public double getLeadSize(){
		return this.leadSize;
	}
 
	public double getSpringWeight(){
		return this.springWeight;
	}
}

Classes, like above, allow us to represent entities with code in a cohesive manner. To come up with the MechanicalPencil class, I asked myself, “What properties make up a mechanical pencil?” Those properties are the instance variables. Instance variables describe the state of an object; they tell you what makes up a given object. In this case, we have:

  • private String color;
  • private double leadSize;
  • private double springWeight;

Each variable declaration consists of an access modifier, a data type, and a variable name. For now, let’s just look at the variable names. These names can be anything, and thus we use them to identify the most important parts of the object/entity we are trying to represent. It is important to remember, variables you define mean nothing to the compiler until you assign a value to them.

I chose color, leadSize, and springWeight because they are the basic components of a mechanical pencil, as far as I’m concerned. You can choose to model an object in any way that fits your requirements. Java doesn’t consider MechanicalPencil a physical mechanical pencil, it considers it as a collection of data (instance variables) and the ways to manipulate that data. Because of this abstractness, it’s possible to represent just about anything in OOP.

The compiler can’t just be handed a bunch of text or numbers and be left to figure out what to do with it. We need to let Java know what to expect when we tell it the pencil is blue. This is accomplished through the use of data types, written immediately to the left of the variable name. In the case of MechanicalPencil, we told the compiler that color is a String, leadSize is a double, and springWeight is also a double.

Now that Java knows what to call our variables and how to store them, it needs to know who gets access to them. Three access modifiers exist:

  • private
  • public
  • protected

Because multiple objects of the same class can exist at once, we want to make sure that the color of one MechanicalPencil doesn’t get mixed up with another MechanicalPencil. In fact, we don’t want anything to interact with the color of a given pencil unless we specifically call for it. This is accomplished in two parts. The first is using the private access modifier. This “hides” the instance variable from every piece of code except for its own classes methods. The second part is accomplished by writing methods to interact with instance variables in predefined ways. We don’t want someone to change the color of the MechanicalPencil in a way that breaks something else about the object.

Speaking of methods, it’s about time we look at the rest of the code. Let’s focus on these first few lines first:

// trim
	public MechanicalPencil(){
	}
 
	public MechanicalPencil(String color, double leadSize, double springWeight){
		this.color = color;
		this.leadSize = leadSize;
		this.springWeight = springWeight;
	}
// trim

These are our constructors. Constructors allow us to create object instances of our MechanicalPencil class. The first constructor, public MechanicalPencil(){}, doesn’t accept any parameters; if it did, they would go in the parentheses. When default constructors like this are called, you can think of it as a blank object. Until we actually define the color, leadSize, and springWeight, they will sit as empty values. They are also public, meaning they can be access outside of our class. This makes sense, we want to make MechanicalPencils in more than one place.

The second constructor allows us to create a MechanicalPencil and define it’s instance variables all at once. Let’s say we want a pencil that’s purple, uses 0.5 lead, and has a spring weight of 6:

MechanicalPencil myPencil = new MechanicalPencil("purple", 0.5, 6);

On the right hand side of the =, we see our constructor. We don’t need to type out what each variable is called, we just need be make sure that our parameters are passed in the same order the constructor is expecting. On the left hand side, we have MechanicalPencil myPencil. At first glance, you may not realize that this is a simple variable declaration. We have our data type, MechanicalPencil, and our variable name, myPencil. Remember, we need to tell Java what to expect when we assign myPencil to a value. In this case, we are setting myPencil to a new MechanicalPencil object. Thus, we define it’s data type as MechanicalPencil. Now, Java knows how to handle our new variable.

Let’s move along to our methods. Consider:

// trim
	public void setColor(String color){
		this.color = color;	
	}
 
	public void setLeadSize(double leadSize){
		this.leadSize = leadSize;
	}
 
	public void setSpringWeight(double springWeight){
		this.springWeight = springWeight;
	}
 
	public String getColor(){
		return this.color;
	}
 
	public double getLeadSize(){
		return this.leadSize;
	}
 
	public double getSpringWeight(){
		return this.springWeight;
	}
// trim

Methods are defined similar to constructors. They’re public, so that we can use them outside of this file, and sometimes they accept parameters. There are two major differences:

  • Each method has a data type
  • Methods are written in camelCase

The data type of a given method depends entirely on the purpose of said function. There are two major purpose categories: accessors and mutators (or getters and setters, if you’d like). Accessors allow us to get the current value of an instance variable, its state. Because they return a value, we need to tell Java, yet again, what to expect. If we want to know the color of a given MechanicalPencil, the compiler should expect a String in return, a double for leadSize, and a double for springWeight. Again, they are public so that we can use them outside of this class file.

An important note: you may notice that the accessors use this. in their return statement. this. points to the instance variable of that name. Imagine that you’re holding a mechanical pencil and someone asks you “what color is your mechanical pencil?” You reply “this is purple.” this.color is purple. Using this shorthand also lets you be lazy, if you will, with your parameter variables. Instead of having to say:

public void setColor(String newColor){
	this.color = newColor;

I can just say:

public void setColor(String color){
	this.color = color;
}

So the assignment statement can be read as follows, ”this color is the passed color.” And because we don’t need a value to be returned from our mutators, we set their return type to void, telling Java to expect nothing.