DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Last call! Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • How to Convert XLS to XLSX in Java
  • Recurrent Workflows With Cloud Native Dapr Jobs
  • Java Virtual Threads and Scaling
  • Java’s Next Act: Native Speed for a Cloud-Native World

Trending

  • Java Virtual Threads and Scaling
  • Immutable Secrets Management: A Zero-Trust Approach to Sensitive Data in Containers
  • A Modern Stack for Building Scalable Systems
  • Microsoft Azure Synapse Analytics: Scaling Hurdles and Limitations
  1. DZone
  2. Coding
  3. Java
  4. Using InstanceOf and Alternatives Within Java

Using InstanceOf and Alternatives Within Java

After reviewing a processing approach that utilized the InstanceOf operator, a Zone Leader began to wonder if better alternatives could be employed.

By 
John Vester user avatar
John Vester
DZone Core CORE ·
Sep. 24, 19 · Analysis
Likes (9)
Comment
Save
Tweet
Share
97.9K Views

Join the DZone community and get the full member experience.

Join For Free

Java InstanceOf and Alternatives

Learn more about using InstanceOf and Alternatives in Java

While reviewing a customer code base, there was a situation where JSON data was mapped into a collection of POJOs (plain old Java objects) for processing. Part of the JSON payload included a  List<Base>  — where Base is a custom Java parent class that was created to house all of the common attributes maintained by the elements, which could be part of the simple List.

You may also like: The InstanceOf Code Smell and One Way to Get Around It

To make things simple, let's assume a scenario where the following objects extend the Base object:

  •  Circle

  •  Rectangle 

  •  Triangle 

Of the three classes above, all the attributes for each class are distinct and are not shared by the other two. Instead, those attributes are part of the Base class.

When processing the  List<Base>, there was a need to perform the following logic:

private void processBaseObjects(List<Base> baseObjects) throws InvalidBaseException {
   for (Base base : baseObjects) {
      if (base instanceof Circle) {
         handleCircle(base);
      } else if (base instanceof Rectangle) {
         handleRectangle(base);
      } else if (base instanceof Triangle) {
         handlerTriangle(base);
      } else {
         // Throw some custom exception here
         throw new InvalidBaseException();
      }
   }
}


Two things gained my interest in the approach noted above:

  1. The use of multiple else if   statements

  2. The use of the InstanceOf operator to make processing decisions

As I took using Google to gain a better understanding of how others have handled such a situation, I was surprised at the high level of discussions/debates at play.

Below are some alternative approaches that can be employed in this scenario.

Apply Polymorphism

If it is possible to change the Circle, Rectangle, and Triangle  classes to implement an Interface; the Interface class could implemented as shown below:

public interface BaseProcessor {
void handleObject();
}


From there, the Circle class (as an example) can be updated, as shown below:

public class Circle extends Base implements BaseProcessor {
@Overload
handleObject() {
// start processing logic here ...
}
}


At this point, the original logic becomes simplified, as shown below:

private void processBaseObjects(List<Base> baseObjects) throws InvalidBaseException {
   baseObjects.forEach(base -> base.handleObject());
}


The one reservation I have with this approach is that the POJOs is currently a collection of attributes. If the handleObject() logic requires integration with a given service, the complexity behind the Circle class (as an example) increases — which might not be desirable.

Of course, if it is not possible to change the Circle, Rectangle, and Triangle classes, this is not an ideal solution.

Use getClass()

Another option is to use the object's getClass() method to make a test similar to using InstanceOf. In the original code, this would be updated as shown below:

   for (Base base : baseObjects) {
      if (base.getClass().equals(Circle.class)) {
         handleCircle(base);
      } else if (base.getClass().equals(Rectangle.class)) {
         handleRectangle(base);
      } else if (base.getClass().equals(Triangle.class)) {
         handlerTriangle(base);
      } else {
         // Throw some custom exception here
         throw new InvalidBaseException(base.getType());
      }
   }


While this approach will work, it is important to keep in mind that getClass() will return the runtime class object — making it impossible to determine if the object falls within a specific inheritance hierarchy.

Implement an Enum

An additional option is to create an enum as shown below:

public enum ShapeActionEnum {
  Circle {
     @Override
     void handleObject() {
       // start processing logic here ...
     }
  }, 
  Rectangle {
     @Override
     void handleObject() {
       // start processing logic here ...
     }
  },  
  Triangle {
     @Override
     void handleObject() {
       // start processing logic here ...
     }
  };

  abstract void handleObject();
}


From there, the parent Base class will include the following property, which would be set during the mapping process:

ShapeActionEnum shapeActionEnum;


As a result, the original processing code would be simplified, as shown below:

private void processBaseObjects(List<Base> baseObjects) throws InvalidBaseException {
   baseObjects.forEach(base -> .getShapeActionEnum().handleObject());
}


The challenge I have with this approach is that the processing logic is getting buried inside an enum class — which also introduces similar issues if service interaction is required.

Additional Options

Some additional approaches that could also be applied are noted below:

  • Visitor Pattern — an example can be found here.

  • Use a  Map<Class, Runnable> where the Runnable contains a lamba function on what action needs to be performed for the mapped Class.

  • Implement Pattern Matching — JEP Draft can be found here.

Conclusion

I was surprised at the level of information that exists from the concept of using InstanceOf to determine a logic path.

Given this is a popular zone at DZone, I am interested in what implementations that have also been considered ... outside the examples I provided. Be sure to let me know in the comments section.

Have a really great day!

Further Reading

The InstanceOf Code Smell and One Way to Get Around It

Why the Instance Variable of the Super Class Is Not Overridden in the Sub Class

Java (programming language)

Opinions expressed by DZone contributors are their own.

Related

  • How to Convert XLS to XLSX in Java
  • Recurrent Workflows With Cloud Native Dapr Jobs
  • Java Virtual Threads and Scaling
  • Java’s Next Act: Native Speed for a Cloud-Native World

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!