Classes in Java

Introduction to Classes

For example, a program to track student test scores might have Student, Course, and Grade classes. Our real-world concerns, students and their grades, are inside the program as classes.

We represent each student as an instance, or object, of the Student class.

This is object-oriented programming because programs are built around objects and their interactions. An object contains state and behavior.

Classes are a blueprint for objects. Blueprints detail the general structure. For example, all students have an ID, all courses can enroll a student, etc.

An instance is the thing itself. This student has an ID of 42, this course enrolled that student, etc.

Let’s review with another example, a savings account at a bank.

What should a savings account know?

  • The balance of money available.

What should a savings account do?

  • Deposit money.
  • Withdraw money.

Imagine two people have accounts that are instances of the SavingsAccount class. They share behavior (how they deposit and withdraw) but have individual state (their balances), and even with the same balance amount these accounts are separate Entities.

Classes: Syntax

A class is the set of instructions that describe how an instance can behave and what information it contains.

Java has pre-defined classes such as System, which we’ve used in logging text to our screen, but we also need to write our own classes for the custom needs of a program.

Here’s a definition of a Java class:

public class Car {
// scope of Car class starts after curly brace
public static void main(String[] args) {
// scope of main() starts after curly brace
// program tasks }
// scope of main() ends after curly brace
}
// scope of Car class ends after curly brace

This example defines a class named Car. public is an access level modifier that allows other classes to interact with this class. For now, all classes will be public.

This class has a main() method, which lists the tasks performed by the program. main() runs when we execute the compiled Car.class file.

Classes: Constructors

Here’s the Car class with a constructor:

public class Car {
public Car() {
//constructor method starts after curly brace
//instructions for creating a Car instance }
//constructor method ends after curly brace
public static void main(String[] args) { // program tasks }
}

The constructor, Car(), shares a name with the class.

We create instances by calling or invoking the constructor within main(). This example assigns an instance to the variable ferrari:

public class Car {  public Car() {
}
public static void main(String[] args) {
/*
invoke a constructor using
'new', the name, and parentheses:
new Car()
*/
Car ferrari = new Car();
}
}

As with other variable declarations, we specify the type: Car, and name: ferrari. Variables that reference an instance have a type of the class name.

We invoke the constructor method: Car(), and use the keyword new to indicate that we’re creating an instance. Omitting new causes an error.

This is the first time we’ve called a method that we’ve also defined. main() is run automatically and we did not define the println() method.

Introducing a second method is a big step in your programming journey, congratulations!

public class Store {

// new method: constructor!

public Store() {

System.out.println(“I am inside the constructor method.”);

}

// main method is where we create instances!

public static void main(String[] args) {

System.out.println(“Start of the main method.”);

}

}

We did not see our constructor message printed because we haven’t run the code inside the constructor

public class Store {

// new method: constructor!

public Store() {

System.out.println(“I am inside the constructor method.”);

}

// main method is where we create instances!

public static void main(String[] args) {

System.out.println(“Start of the main method.”);

Store lemonadeStand = new Store();

}

}

Now -:

public class Store {

// new method: constructor!

public Store() {

System.out.println(“I am inside the constructor method.”);

}

// main method is where we create instances!

public static void main(String[] args) {

System.out.println(“Start of the main method.”);

Store lemonadeStand = new Store();

System.out.println(lemonadeStand);

}

}

Review the order of the printed messages:

  1. Running the program invokes main()
  2. We create an instance so we move from main() to Store()
  3. The code inside Store() runs
  4. When Store() finishes execution, we return to main()

Classes: Instance Fields

We don’t care about memory location, but our instances have no other characteristics!

We’ll add associated data to an object by introducing instance variables, or instance fields. Instance fields are the state in our objects.

We want Car instances of different colors, so we declare a String color instance field.

public class Car {
/*
declare fields inside the class
by specifying the type and name
*/
String color;
public Car() {
/*
instance fields available in
scope of constructor method
*/
}
public static void main(String[] args) {
// body of main method
}
}

The declaration is within the class and the instance variable will be available for assignment inside the constructor.

Fields are a type of state each instance will possess. One instance may have "red" as its color, another "blue", etc. We’ll learn how to assign values in the beloww.

Classes: Constructor Parameters

We need to alter the constructor method because now it needs to access data we’re assigning to the instance.

Our Car constructor now has a parameter: String carColor.

public class Car {
String color;
// constructor method with a parameter
public Car(String carColor) {
// parameter value assigned to the field
color = carColor;
}
public static void main(String[] args) {
// program tasks
}
}

We need a value for the instance field color, so we’ve added String carColor as a parameter.

Parameters specify the type and name of data available for reference within a method’s scope.

We’ve already seen a parameter in the main() method: String[] args, but this is the first time we’re using the parameter value within a method body.

The parameter carColor references the value passed in during a method call:

new Car("blue");
// carColor references "blue" inside constructor
new Car("yellow");
// carColor references "yellow" inside constructor

Within the constructor, we assign the parameter value to the instance field.

Instance fields are available for assignment inside the constructor because we declared them within the class.

Classes: Assigning Values to Instance Fields

Here we create an instance, ferrari, in the main() method with "red" as its color field:

public class Car {
String color;
public Car(String carColor) {
// assign parameter value to instance field
color = carColor;
}
public static void main(String[] args) {
// parameter value supplied when calling constructor
Car ferrari = new Car("red");
}
}

We pass the String value "red" to our constructor method call: new Car("red");.

The type of the value given to the invocation must match the type declared by the parameter.

Inside the constructor, the parameter carColor refers to the value passed in during the invocation: "red". This value is assigned to the instance field color.

color has already been declared, so we don’t specify the type during assignment.

The object, ferrari, holds the state of color as an instance field referencing the value "red".

We access the value of this field with the dot operator (.):

/*
accessing a field:
objectName.fieldName
*/
ferrari.color;
// "red"

Program Example-:

public class Store {

// instance fields

String productType;

// constructor method

public Store(String product) {

productType = product;

}

// main method

public static void main(String[] args) {

Store lemonadeStand = new Store(“lemonade”);

System.out.println(lemonadeStand.productType);

}

}

Classes: Multiple Fields

Let’s change Car instances so they have multiple fields.

We’ll add a boolean isRunning, that indicates the car engine is on and an int velocity, that indicates the speed at which the car is traveling.

public class Car {
String color;
// new fields!
boolean isRunning;
int velocity;
// new parameters that correspond to the new fields
public Car(String carColor, boolean carRunning, int milesPerHour) {
color = carColor;
// assign new parameters to the new fields
isRunning = carRunning;
velocity = milesPerHour;
}
public static void main(String[] args) {
// new values passed into the method call
Car ferrari = new Car("red", true, 27);
Car renault = new Car("blue", false, 70);
System.out.println(renault.isRunning);
// false
System.out.println(ferrari.velocity);
// 27
}
}

The constructor now has multiple parameters to receive values for the new fields. We still specify the type as well as the name for each parameter.

Ordering matters! We must pass values into the constructor invocation in the same order that they’re listed in the parameters.

// values match types, no error
Car honda = new Car("green", false, 0);
// values do not match types, error!
Car junker = new Car(true, 42, "brown");

Program Example-

public class Store {

// instance fields

String productType;

int inventoryCount;

double inventoryPrice;

// constructor method

public Store(String product, int count, double price) {

productType = product;

inventoryCount = count;

inventoryPrice = price;

}

// main method

public static void main(String[] args) {

Store cookieShop = new Store(“cookies”, 12, 3.75);

}

}

Classes: Review

Classes define the state and behavior of their instances. Behavior comes from methods defined in the class. State comes from instance fields declared inside the class.

Classes are modeled on the real-world things we want to represent in our program. Later we will explore how a program can be made from multiple classes. For now, our programs are a single class.

public class Dog {
// instance field
String breed;
// constructor method
public Dog(String dogBreed) {
/*
value of parameter dogBreed
assigned to instance field breed
*/
breed = dogBreed;
}
public static void main(String[] args) {
/*
create instance:
use 'new' operator and invoke constructor
*/
Dog fido = new Dog("poodle");
/*
fields are accessed using:
the instance name, `.` operator, and the field name.
*/
fido.breed;
// "poodle"
}
}

Review Example

public class Dog {

String breed;

boolean hasOwner;

int age;

public Dog(String dogBreed, boolean dogOwned, int dogYears) {

System.out.println(“Constructor invoked!”);

breed = dogBreed;

hasOwner = dogOwned;

age = dogYears;

}

public static void main(String[] args) {

System.out.println(“Main method started”);

Dog fido = new Dog(“poodle”, false, 4);

Dog nunzio = new Dog(“shiba inu”, true, 12);

boolean isFidoOlder = fido.age > nunzio.age;

int totalDogYears = nunzio.age + fido.age;

System.out.println(“Two dogs created: a “ + fido.breed + “ and a “ + nunzio.breed);

System.out.println(“The statement that fido is an older dog is: “ + isFidoOlder);

System.out.println(“The total age of the dogs is: “ + totalDogYears);

System.out.println(“Main method finished”);

}

}

Read Previous — Manipulating Variables in Java

Read Next — Methods in Java