Anatomy of a Java class
Part I — Declaration
What is a class
in Java?
Java code exists inside classes and interfaces, nowhere else. Between classes and interfaces, classes do most of the work when it comes to Java programs. Interfaces are there to outline behaviors for one or more sub-classes. Interfaces can’t create objects since they don’t contain any implementation.
For start, I would like to analogize classes to paper forms, like the ones that are filled out and have a separate section titled “for official use only”. A form neatly portrays the concept of a class
.
Let’s picture a driving licence application form, it has named fields, which an applicant has to fill. i.e. Name, Address, Date of birth, etc. In a class
such the equivalent of named spaces are the instance variables.
Likewise, in our paper application form, the “official use” section may contain other named spaces whose values might be derived from a series of operations. For example, deriving a person’s age from their date of birth, recording their name in the organ donors database, or assessing their driving record for DUI and points. Therefore, even though in the application form the “official use” section may look similar to the “non-official use” section, they could be different in a sense. The values in the “official use” section are the output of some sort of an operation.
In a Java class
such operations are performed by its member methods. With one type of a form we can serve thousands of driving licence applicants. Each filled-out paper form records some type of coherent data at a given time. In Java an object is the equivalent of a filled-out form, we also call it an instance of a class.
An object is a state-ful entity that is created off of a class’s blueprint and it occupies its own memory space. Meaning, it was created from a class
template.
A class
in programming defines a new abstract data type. Just like an int
variable stores integers, an instance of an Employee
class stores objects of type employee. Java allows us to declare classes, methods, and variables in several ways. And how we declare them significantly affects the code’s behavior.
Since we are on the topic of classes, following are some rules associated with declaring classes:
- There can only be one public class per source code file.
- If there is a public class in a file, the class name and filename must match.
- A source file can have more than one non-public class.
- A source file with no public class can have a name that does not match any of the classes inside.
- Comments are independent of any of the positioning rules.
- If the class is part of a package, the package statement should be the first line in the source code file.
- import statements go after the package statement and before the class declaration.
Declaring a class
and setting up its access level
The bare bone class
declaration looks like this: class Foo {}
. A keyword, an identifier, and a pair of braces. Technically all classes have access modifiers. class Foo {}
has an invisible one, which we call the default modifier.
Generally there are four types of access modifiers, three of them are explicitly declared using keywords: public
, protected
, and private
. Plus the default modifier which fires up when we don’t explicitly mention any access modifier.
It is important to note that classes can only have one of the two access modifiers, public
and default. Other modifiers are used for the class members, they are not class-level modifiers.
Accessing a class
We can do three things with a class:
1. Make objects with it. A class is a blueprint and we utilize that feature and create objects off of that blueprint. Or in technical terms, we create an instance of a class.
2. Extend it. Meaning we can take a class and add to or redefine its features.
3. Access certain members of it. We can access members of a class by whichever method their modifiers allow us to do so, remember those members have their own access and non-access modifiers.
All in all, an access modifier determines from how far out can a class be reachable. The table below is the summary of it:
Note: these declarations are only for top-level classes. Read on nested classes or inner classes over here.
Other class modifiers (Non-access)
You can modify a class
declaration by using the keyword final
, abstract
, and strictfp
. These modifiers are in addition to the access modifiers. strictfp
has a very particular and specialized use, it makes sure that any method inside that class strictly conforms to the IEEE 754 standard rules for floating points. Without this modifier the floating point accuracy will be dependent on the platform the Java code runs on. If you work with a lot of floating point numbers, it is very important that you understand why this feature exists. Read more here. But, for our purpose, we will only discuss final
and abstract
classes.
final class
When used in a class
declaration, the final
key word means the class
cannot be sub classed. Note that, it doesn’t mean that it cannot be instantiated, it only means that “this blueprint cannot be edited!”. If you really are certain that a class
is in its final form and no one should edit its implementation — declare it final
. Imagine if we could change the implementation of some of the Java API classes. A developer down the chain would be using Arrays
class thinking it is still zero-indexed, without knowing that for some unknown reason you had decided to change it to one-indexed.
In contrast it is useful to let other classes inherit from a given class
. It helps maintain a clean code base and avoid unnecessary redundancy. Imagine an HR application having an overarching Employee class
and then all the sub classes of Executive
, Auxiliary
, and Contractor
extending from it, and then each of these having their own sub classes of Manager
, President
, Carpenter
etc. They all fit in a tree but they don’t have to repeat the implementation of the same fields and methods over and over.
abstract class
An abstract class
, just like an interface
, can never be instantiated, its sole purpose is to set a guideline for what its sub classes should do. It sounds a lot like an interface
, but they are not the same. Why do we need abstract
classes? Because, sometimes if we arrange our applications in a pure hierarchical way, it gets hard to create objects off of some classes, yet they are important to maintain their position in a chain of inheritance in order to separate its sub classes. For example, in a construction company’s application, it is hard to directly create an object of a class
named Building
, however it is crucial for this class to exist in order to separate its non-abstract sub classes: School
, Hospital
, and Apartment
from other classes of the same application like: Road
, Airport
, and ParkingLot
etc.
abstract class Building {
public abstract floors();
public abstract rooms();
public abstract bathrooms();
}
The code above defines a ground rule for all sub classes, “if you can implement these methods, then you are a building type”.