CHAPTER 8
Java is an object-oriented language. It contains mechanisms that allow us to program hierarchies of our own data types called classes. A class is a blueprint—it is a description of a type of object in terms of which variables the objects own and which methods (functions) the objects are able to perform. We can create objects from these class blueprints—the objects are called instances of the class. Objects are a collection of variables called member variables and methods called member methods. For instance, you can create a Circle class with radius as a variable. And the methods might compute things such as computePerimiter and computerArea.
There are three key concepts for understanding the basics of classes and objects in Java:
In order to begin describing a new class, first add it to your project in exactly the same way we added the MainClass to our first project (click the File > New > Class). You must give your class a unique name in the New Java Class dialog box. We will first build a simple circle class, and I have named my class Circle in Code Listing 8.0. Note that the name of the class should match the name of the file, which means the file for this particular class is Circle.java (this will be automatic when we use the class wizard to add our classes to our projects).
Code Listing 8.0: Empty Circle Class
public class Circle { } |
We have defined many variables already, but in each case we have defined inside a method (specifically, inside the main method). Such variables have a scope (or visibility) that only lasts for a code block of the method. Variables that are defined inside a method and that have a scope that only lasts for the duration of the method are called local variables. In contrast to local variables, member variables have a scope that lasts for the lifetime of the object.
Each of the objects built from a class has member variables. In order to create a member variable, we define the variable inside the class’s body but outside of any methods. In addition to having a data type and name, member variables can also have an access modifier. Access modifiers describe the visibility for the member variable to the outside world, i.e. they define whether objects can access this member variable or whether it is private.
Code Listing 8.1: Circle Class Member Variables
public class Circle { public float radius; private String name; protected float lineWidth; private static int circleCount; } |
In Code Listing 8.1, there are four member variables defined for our Circle class. Notice that there are terms next to the data types public, private, protected, and static. These are the access modifiers. They are placed to the left of the data type.
public: All classes have access to member variables and methods marked public.
protected: Classes and objects that belong to same package are allowed access to protected member variables.
private: Member variables marked private are only accessible by members of the class itself—that is, objects built from the class.
static: Members marked as static belong to the class rather than to the objects created from the class. If we mark a member variable as static, there will be one copy of the variable shared by all objects in the class. Members marked as static can also be referenced with the class instead of an object, as we shall see.
Note: The keyword final is another access modifier. Members and local variables marked final can have their value specified only once. The final keyword is useful for defining constants such the mathematical constants PI and E. Final variables are usually named with all capital letters, such as PI and DAYS_IN_JUNE. For more information on the final keyword, visit https://docs.oracle.com/javase/tutorial/java/javaOO/classvars.html.
We have defined a class called Circle, and we can now begin constructing objects from it. Move back to the MainClass.java file in your project. Code Listing 8.2 shows how to create an object from our Circle class using the new operator.
Code Listing 8.2: Creating an Object from a Class
public class MainClass { public static void main(String[] args) { Circle c = new Circle(); c.radius = 100.0f; System.out.println("Circle radius is " + c.radius); } } |
The most important line in Code Listing 8.2 is Circle c = new Circle();. This line creates a new Circle object from our class blueprint and assigns it to the object c. We begin with the class name, Circle, followed by the name we want for the object, c. Next, we use the assignment operator, =, followed by the new keyword. The new keyword is followed by what looks like a function call, but this is actually a very special function. Circle() is a constructor. It is a function used to initialize an object from a class. We did not supply any constructors in our Circle class, so Java has provided us with the default one, Circle() (we will define some constructors ourselves in a moment).
The object c is an instance of the Circle class. It owns a copy of each of the member variables specified in the Circle class. We can change the public member variables of c. In order to change the object’s radius member variable, we use “c.radius = 100.0f”. The period after the object’s name means that the radius token belongs to the c instance. We can set the radius member variable as illustrated in Code Listing 8.2, but we cannot set the name or the circleCount member variables. If we try to, with “c.name = "Sirkl";” or “c.circleCount = 100;”, you will notice that Eclipse underlines and states that these members are not visible because they are marked private and the main method is not part of the Circle class, therefore it cannot see these member variables.
Note: The main method is within the same package as the Circle class, so you will find that altering the lineWidth member variable is perfectly legal with “c.lineWidth = 23;”. This is quite different from the protected modifier in C and C++ that means visible to child classes.
We can create many objects from a class. If we create a second Circle and call it b, the c Circle and the b Circle will both have their own member variables (see Code Listing 8.3).
Code Listing 8.3: Creating Multiple Instances
public class MainClass { public static void main(String[] args) { Circle c = new Circle(); Circle b = new Circle(); c.radius = 100.0f; b.radius = 900.0f; System.out.println("Radius of c: " + c.radius); // Prints 100 System.out.println("Radius of b: " + b.radius); // Prints 900 } } |
Code Listing 8.4 shows that we can very quickly create an entire array of object instances from our class. Note that when we declare an array of type Circle, all elements of the array are initialized to null. We must call the constructor for each instance in order to instantiate the objects.
Code Listing 8.4: Creating an Array of Objects
public class MainClass { public static void main(String[] args) { // Declare array of 100 Circles objects. Circle[] circleArray = new Circle[100]; // Use a loop to call new and set radiuses. for(int i = 0; i < 100; i++) { circleArray[i] = new Circle(); circleArray[i].radius = (float)i; } // Print out a radius as an example. System.out.println ("circleArray[20] Radius: " + circleArray[20].radius); } } |
Member methods are functions of a class. A function is a reusable block of code that we can invoke or call. In Code Listing 8.5, I have changed all the member variables to private. Marking all member variables as private and providing getters and setters as member methods (which enables us to alter the inner workings of the member variables with the knowledge that no external classes are accessing them directly) is common practice. The Circle class has also been expanded to include a number of member methods. The member methods included in Code Listing 8.5 are setRadius, getRadius, print, zeroCount, and setLineWidth.
Code Listing 8.5: Member Methods
public class Circle { private float radius; private String name; private float lineWidth; private static int circleCount; // Constructors:
// Default Constructor public Circle() { this.radius = 0.0f; this.name = "No name"; this.lineWidth = 0.0f; circleCount++; } // Two argument constructor public Circle(String name, float radius) { this.radius = radius; this.name = name; this.lineWidth = 0.0f; circleCount++; } // Methods public void setRadius(float radius) { this.radius = radius; } public float getRadius() { return radius; } public void print(){ System.out.println("Circle: " + name + " Rad: " + radius); } protected void setLineWidth(float newWidth) { this.lineWidth = newWidth; } public static void zeroCount() { circleCount = 0; } public static int getCount() { return circleCount; } } |
Member methods begin with access modifiers such as public, private, and static. These access modifiers behave in exactly the same way as when we mark member variables. The public designation means all external objects can invoke the method, while private means that only members of the class can invoke the method, etc. Following the access modifiers, we supply an identifier name for our method, then the parameters that the method requires.
The first two methods in Code Listing 8.5 are constructors. Constructors have no return type, and they share exactly the same name as the class. When we create an object from our class, we use the new keyword and call a constructor. The first constructor specified in Code Listing 8.5 takes no parameters. This is called a default constructor. The second constructor takes two parameters, a name and a radius, and sets the object’s member variables based on the value of these parameters.
Note: Notice the use of the keyword this in the methods of a class. The keyword means “the current object.” We can use the keyword this to differentiate between parameters being passed to a method and member variables with the same name. The second constructor in Code Listing 8.5 shows an example of this—we pass a parameter called name and we use it to set the value of this.name, which is the member variable called name.
Note: When a member method or constructor takes more than one parameter, we separate the parameters in the parameter list with commas. This can be seen in the second constructor from Code Listing 8.5, which takes two parameters—a string called name and a float called radius.
The methods setRadius, getRadius, and setLineWidth are called getters and setters. They are member methods that allow external objects to change the values of the corresponding private variables. A getter is used to read a variable’s value. Getters take no arguments, and they return whichever type the variable happens to be. Getters generally consist of nothing but a single line that returns the variable’s value. A setter is used to set the value of a private member variable. Setters typically take a single parameter of the same name and type as the variable they are used to set. Setters usually consist of a single line that is used to assign the new value to the member variable.
After we supply a class with member methods, we can create an object and call the methods using the instance. Code Listing 8.6 shows how to create a Circle object and call the member methods specified.
Code Listing 8.6: Calling Member Methods
public class MainClass { public static void main(String[] args) { // Create a circle with the default constructor. Circle c = new Circle();
// Create a circle with the (String, radius) constructor. Circle b = new Circle("Dennis", 55.0f);
// See how many circles we've counted with getCount. System.out.println("Number of circles created: " + Circle.getCount()); b.print(); // Call the print method of b.
c.setRadius(27.0f);// Call setRadius to set c.radius to 27.0f. c.setLineWidth(100.6f); // set c.lineWidth to 100.6f. System.out.println("Radius of C: " + c.getRadius()); Circle.zeroCount(); // Calling a static method. System.out.println( "Number of circles created: " + Circle.getCount());
} } |
To call a member method, we supply the object’s name, followed by the dot operator, followed by the name of the method (e.g., c.setRadius(100.0f)). In the brackets to a method call, we supply the parameters.
Note: In Java classes, we can have multiple methods with exactly the same names so long as each method takes a different number of arguments, or arguments with different data types, as input. This is called method overloading, and Code Listing 8.6 shows an example of overloading with the constructors. Notice that there are two methods called Circle, and they take different parameters. When we call one of these constructors, Java will know which one we mean by the parameters we pass. We can also overload nonconstructor methods—e.g., we have multiple setRadius methods: one that takes a double, one that takes an int, etc.
Inheritance saves us time. We want to type as little code as possible, and we do not want to rewrite the same code more than once. Inheritance allows us to program classes with a parent/child relationship. The objective is to describe the attributes of a parent class in broadly applicable terms. From the parent class, we can create more specific child classes.
The following class is called Animal. It will be used as a parent class, and it describes aspects applicable to all animals. Animals possess voluntary motion, and they ingest some form of sustenance for energy, so I have included two boolean variables in Code Listing 8.7 and set them to true in a default constructor. You can add this new class to the existing project in the same way that we added the MainClass and the Circle class previously, or you might begin a new project.
Code Listing 8.7: Animal Parent Class
public class Animal { public boolean voluntaryMotion; public boolean requiresFood;
public Animal(){ voluntaryMotion = true; requiresFood = true; } } |
An insect is a type of Animal. All insects have six legs, antennas, and an exoskeleton. Some insects have wings, so we will include a boolean for wings, and set it to true by default in the constructor. But because all insects are animals, we can inherit from the Animal parent class instead of adding the member variables for voluntaryMotion and requiresFood. Code Listing 8.8 shows the syntax for inheriting from the Animal parent class using the extends keyword.
Code Listing 8.8: Insect Child Class
public class Insect extends Animal {
public boolean antennas; public String skeleton; public int numberOfLegs; public boolean wings;
public Insect(){ super(); antennas = true; skeleton = "Exosketon"; numberOfLegs = 6; wings = true; } public void Print() { System.out.println("Antennas: " + antennas + " Skeleton: " + skeleton + " Number of Legs: " + numberOfLegs + " Wings: " + wings + " Voluntary Motion: " + voluntaryMotion + " Requires Food: " + requiresFood); } } |
The most important syntax in Code Listing 8.8 is highlighted in yellow. The Insect class a derived class, or a child class, and Animal class is a super class, or a parent class. The first line of Code Listing 8.8 shows the use of the keyword extends. This keyword means the Insect class extends, or inherits, from the original traits specified in the Animal class.
Also notice the call to a method super() in Code Listing 8.8. This is a call to the Animal class’s constructor. From a child class, we can use the term super to mean the parent class, and by supplying an empty parameter list, we are calling the default constructor of the Animal class. In Code Listing 8.8, we see that the default constructor sets the boolean variables voluntaryMotion and requiresFood to true.
Note: It is not necessary to call a parent’s constructor in a child class, but if the parent’s constructor is called, it must be called on the first line of the child class constructor.
Code Listing 8.9: Insect Class
public class MainClass { public static void main(String[] args) { // Create an instance of Insect called i. Insect i = new Insect(); // Change the insect class's members: i.antennas = false; i.numberOfLegs = 100; // Call the Insect's Print method: i.Print(); // Change the parent class's requiresFood member: i.requiresFood = false; } } |
Code Listing 8.9 shows an example of creating an Insect object and calling some of its members.
We could then go on to define an Ant class. Ants are insects, therefore they have six legs, an exoskeleton, and antennas, but they do not have wings (at least not typically). Therefore, we can create a new child class called Ant that inherits from the Insect parent but that has the wings boolean set to false, as in Code Listing 8.10.
Code Listing 8.10: Ant Child Class
public class Ant extends Insect { public Ant() { super(); wings = false; } } |
In Code Listing 8.10, notice that we call the parent constructor with super() before setting wings to false. The parent constructor must be called as the first statement of a child constructor. However, the parent constructor sets the wings boolean to true, and we want our ants to be wingless.
We could easily add more classes, such as Mammals and Elephants, to this hierarchy. Each time we add a new derived class, we need only specify how it differs from the parent or super class (Figure 42 is an example hierarchy).

Figure 42: Animal Class Hierarchy
There is a lot more to object-oriented programming—such as abstract classes, interfaces, and polymorphism. These are advanced topics, and we will cover them in the next book, Java Succinctly Part 2.