1. Overview
In this article, we'll explore the different ways of finding an object's class in Java.
2. Using the getClass() Method
The first method that we'll check is the getClass() method.
First, let's take a look at our code. We'll write a User class:
public class User { // implementation details }
Now, let's create a Lender class that extends User:
public class Lender extends User { // implementation details }
Likewise, we'll create a Borrower class that extends User as well:
public class Borrower extends User { // implementation details }
The getClass() method simply returns the runtime class of the object we are evaluating, hence, we don't consider inheritance.
As we can see, getClass() shows that our lender object's class is of type Lender but not of type User:
@Test public void givenLender_whenGetClass_thenEqualsLenderType() { User lender = new Lender(); assertEquals(Lender.class, lender.getClass()); assertNotEquals(User.class, lender.getClass()); }
3. Using the isInstance() Method
When using the isInstance() method, we're checking if an object is of a particular type, and by type, we are either talking about a class or an interface.
This method will return true if our object sent as the method's argument passes the IS-A test for the class or interface type.
We can use the isInstance() method to check the class of an object at runtime. Furthermore, isInstance() handles autoboxing as well.
If we check the following code, we'll find that the code doesn't compile:
@Ignore @Test public void givenBorrower_whenDoubleOrNotString_thenRequestLoan() { Borrower borrower = new Borrower(); double amount = 100.0; if(amount instanceof Double) { // Compilation error, no autoboxing borrower.requestLoan(amount); } if(!(amount instanceof String)) { // Compilation error, incompatible operands borrower.requestLoan(amount); } }
Let's check the autoboxing in action using the isInstance() method:
@Test public void givenBorrower_whenLoanAmountIsDouble_thenRequestLoan() { Borrower borrower = new Borrower(); double amount = 100.0; if(Double.class.isInstance(amount)) { // No compilation error borrower.requestLoan(amount); } assertEquals(100, borrower.getTotalLoanAmount()); }
Now, let's try to evaluate our object at run time:
@Test public void givenBorrower_whenLoanAmountIsNotString_thenRequestLoan() { Borrower borrower = new Borrower(); Double amount = 100.0; if(!String.class.isInstance(amount)) { // No compilation error borrower.requestLoan(amount); } assertEquals(100, borrower.getTotalLoanAmount()); }
We can also use isInstance() to verify whether an object can be cast to another class before casting it:
@Test public void givenUser_whenIsInstanceOfLender_thenDowncast() { User user = new Lender(); Lender lender = null; if(Lender.class.isInstance(user)) { lender = (Lender) user; } assertNotNull(lender); }
When we make use of the isInstance() method, we protect our program from attempting illegal downcasts, although, using the instanceof operator will be smoother in this case. Let's check it next.
4. Using the instanceof Operator
Similarly to the isInstance() method, the instanceof operator returns true if the object being evaluated belongs to the given type — in other words, if our object referred to on the left side of the operator passes the IS-A test for the class or interface type on the right side.
We can evaluate if a Lender object is type Lender and type User:
@Test public void givenLender_whenInstanceOf_thenReturnTrue() { User lender = new Lender(); assertTrue(lender instanceof Lender); assertTrue(lender instanceof User); }
To get an in-depth look at how the instanceof operator works, we can find more information in our Java instanceOf Operator article.
5. Conclusion
In this article, we reviewed three different ways of finding an object's class in Java: the getClass() method, the isInstance() method, and the instanceof operator.
As usual, the complete code samples are available over on GitHub.