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
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
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
  1. DZone
  2. Coding
  3. Languages
  4. A Word on toString()

A Word on toString()

If you aren't careful, careless use of toString methods and your transitive properties might lead to circular dependencies and the dreaded StackOverflowError.

Shamik Mitra user avatar by
Shamik Mitra
·
Mar. 29, 17 · Tutorial
Like (55)
Save
Tweet
Share
16.58K Views

Join the DZone community and get the full member experience.

Join For Free

Can you spot the problem?

AccountHolder.java:

package com.example.toString;

import java.util.ArrayList;
import java.util.List;

public class AccountHolder {

   private String name;
   private List<Account> accList=new ArrayList<Account>();

   public void addAccount(Account acc){
      accList.add(acc);
   }

   public String getName() {
      return name;
   }

   public void setName(String name) {
      this.name = name;
   }

   @Override
   public String toString() {
      return "AccountHolder [name=" + name + ", accList=" + accList + "]";
   }

}


Account.java:

package com.example.toString;

public class Account {

   private String accNumber;
   private String accType;
   private AccountHolder holder;
   public String getAccNumber() {
      return accNumber;
   }
   public void setAccNumber(String accNumber) {
      this.accNumber = accNumber;
   }
   public String getAccType() {
      return accType;
   }
   public void setAccType(String accType) {
      this.accType = accType;
   }
   public AccountHolder getHolder() {
      return holder;
   }
   public void setHolder(AccountHolder holder) {
      this.holder = holder;
   }
   @Override
   public String toString() {
      return "Account [accNumber=" + accNumber + ", accType=" + accType
              + ", holder=" + holder + "]";
   }




}



Testing above

Main.java

package com.example.toString;

public class Main {

   public static void main(String[] args) {
      AccountHolder ach = new AccountHolder();
      ach.setName("Shamik Mitra");
      Account acc = new Account();
      acc.setAccNumber("100sm");
      acc.setAccType("Savings");
      acc.setHolder(ach);
      ach.addAccount(acc);
      System.out.println(ach);
   }

}


You've probably found the problem by now, but if you haven't, look it over one more time.

What Is the Problem?

The above code snippet, unfortunately, gives you a StackOverflowError.

I spotted this problem while I was reviewing a junior's code. Actually, his program runs well in Dev, so he came to me to review his code.

To explain the essence of the problem, I replicated the same thing here. I have an AccountHolder Object that holds the list of Account, and on the other hand, in the Account object, we have a reference to AccountHolder.

This is a normal scenario when we design a JPA entity, but the problem is that we've blindly populated the toString method using the editor. That will create a circular call and eventually blow up the code with the StackOverflowError.

Root of StackOverflow

As in the AccountHolder toString method, it tries to print the list of Account, so it calls Account toString(). In Account toString(), it again tries to print AccountHolder, so the cycle continues until the StackOverFlowError occurs.

My junior couldn't spot the problem, as in his program, he never prints the Account or AccountHolder object, so it deployed and worked fine on the Development server.

So What Is the Point?

The point I want to convey here is that maybe this type of problem can't always be seen by the naked eye. Maybe there are transitive dependencies at a very deep level, like A class has B, B has C, and C has D, and D has A.

So:

  1. Try use tools that can point out your circular dependencies. (Though I am not using any due to some constraints).
  2. In a class, only print variables that belong to that class. For safety purposes, don't print any HAS-A relations.
Object (computer science) Dependency Design Snippet (programming) dev entity

Published at DZone with permission of Shamik Mitra, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • The Real Democratization of AI, and Why It Has to Be Closely Monitored
  • Top Five Tools for AI-based Test Automation
  • GPT-3 Playground: The AI That Can Write for You
  • Best Practices for Writing Clean and Maintainable Code

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

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

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends: