In this article, we will first explore some background concepts involving Java’s type system. Then, we will formally introduce the instanceof operator. After that, we will touch on a minor instanceof gotcha to be aware of. We will then conduct an imaginary design review on everything up to that point and consider whether there might be a better alternative to instanceof. If you want to dive deeper into this Java concept, consider taking this advanced Java programming course to take your skills to the next level.
Types in Java
Java embodies an object oriented paradigm. It allows you to define arbitrary class hierarchies, where virtually any two classes can have an inheritance relationship, with one being the parent and one being the child. Naturally, the child inherits attributes from the parent.
As an example, we will define a base class called Employee and define two subclasses called EngineeringEmployee and MarketingEmployee, both of which inherit from Employee. This allows us to define the majority of the employee data and business logic inside Employee. At the same time, we can define data and business logic that is specific to engineers and marketing in their respective classes: EngineeringEmployee and MarketingEmployee.
We can create an instance of MarketingEmployee, and it will have all of the basic Employee data and functionality.
In the above example, we say that myMarketingEmployee is an instance of MarketingEmployee, and, it is also an instance of Employee. This is how Java’s type system, including inheritance, works.
Now imagine a scenario where we have a reference to an object, and all we know at compile-time is that it’s an Employee. Imagine, though, that we need to determine whether it’s an engineer or someone in marketing so that we can perform the appropriate action for either. Because situations like this occur often enough, Java provides the instanceof operator.
Using Eclipse? Check out this course on how to write Java programs using Eclipse!
The instanceof Operator
The instanceof operator is relatively straightforward. You would use it when you have a reference to an object, and you want to know if that object is an instance of a particular type.
In the above example, we had a reference to an Employee, but, due to hypothetical requirements, we needed to determine whether it was also either an EngineeringEmployee or a MarketingEmployee. The instanceof operator allowed us to make this determination.
Note how in the above example we were able to put the salary business logic inside the ProcessEmployee() method, rather than inside various hypothetical role-specific methods such as ProcessEngineeringEmployee(), ProcessHREmployee(), ProcessManagementEmployee(), etc. This is a very common advantage in object oriented programming: you tend to write less code to do repetitive tasks.
Want to create web programs? Check out this tutorial on web programming with Java Spring framework.
Gotcha: Testing a null Object
Let’s look at one gotcha. When you have a reference to an object (that happens to be an instance of a particular type), and you then set that reference to null, the Java type system will report that that object is not an instance of the expected type.
instanceof = Indicator of Bad Software Design?
Now let’s take a step back for a moment, look at our class hierarchy, and consider whether we should even be writing code that necessitates the use of the instanceof operator. Although the trivial examples given above do illustrate basic instanceof usage correctly, the software as a whole is actually a classic example of poor software design. Just looking at the code, and without a set of real world software requirements, it would seem safe to get rid of the instanceof checks. The recommended design pattern in this case tends to be the usage of virtual methods (which is another topic in itself – you can explore it in this course on Java fundamentals).
Moving forward with this train of thought, the first change we could make is the addition of a PerformTask() method to the Employee class.
In Java, methods are virtual by default. To override a method in a child class, you would simply add a method with the same name.
Now, when PerformTask() is called on an Employee reference, the corresponding overridden methods will be called, assuming the Employee reference is really pointing to either an instance of EngineeringEmployee or an instance of MarketingEmployee.
As you can see, we have condensed the code even further. It’s starting to look like instanceof can be done away with altogether.
However, if you remember, a few paragraphs up we said this hypothetical piece of software lacked “a set of real world software requirements”. The truth is, real world software requirements are rather unforgiving and have little regard for the time constraints a software development team is usually under. Sometimes using instanceof, although imperfect in terms of design – in an academic setting at least, is the correct way to complete a project on time. Other times, the software requirements are so extraordinarily complex, that there is no obvious way to solve the problem more elegantly. Ultimately, the instanceof operator is simply another tool in the software engineer’s toolbox that you must use judiciously. It might make the purists scoff, but it’ll at least make the code work.
At the same time, you must be familiar with software design best practices. Besides being the right thing to do, it also has practical applications. Unless you are working in complete isolation (highly unlikely), your code will be read, shared and probably refactored by other developers. Knowing best practices can often be the different between a successful project, and a project that fails to take off.
You can learn more about best practices in Java in this course on Java fundamentals.
Did we miss something about instanceof in this lesson? Tell us in the comments below!