Classes in Java
[S1E4]
Introduction to Classes
All programs require one or more classes that act as a model for the world.
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
The fundamental concept of object-oriented programming is the class.
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
We create objects (instances of a class) using a constructor method. The constructor is defined within the class.
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:
- Running the program invokes
main()
- We create an instance so we move from
main()
toStore()
- The code inside
Store()
runs - When
Store()
finishes execution, we return tomain()
Classes: Instance Fields
Our last exercise ended with printing an instance of Store
, which looked something like Store@6bc7c054
. The first part, Store
, refers to the class, and the second part @6bc7c054
refers to the instance’s location in the computer’s memory.
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’ll use a combination of constructor method and instance field to create instances with individual state.
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 constructornew 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
Now that our constructor has a parameter, we must pass values into the method call. These values become the state of the instance.
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
Objects are not limited to a single instance field. We can declare as many fields as are necessary for the requirements of our program.
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
Java is an object-oriented programming language where every program has at least one class. Programs are often built from many classes and objects, which are the instances of a class.
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