Faster Java coding in Eclipse Galileo

Using the new toString() generator

Learn how to use the new toString() code-generation ability in Eclipse Galileo along with hashCode(), equals(), and setter/getter generation to cut down on the amount of work that goes into building the foundation of a Java™ class.

Share:

Nathan A. Good, Senior Information Engineer, Freelance Developer

Nathan GoodNathan A. Good lives in the Twin Cities area of Minnesota. Professionally, he does software development, software architecture, and systems administration. When he's not writing software, he enjoys building PCs and servers, reading about and working with new technologies, and trying to get his friends to make the move to open source software. He's written and co-written many books and articles, including Professional Red Hat Enterprise Linux 3, Regular Expression Recipes: A Problem-Solution Approach, and Foundations of PEAR: Rapid PHP Development.



18 August 2009

Also available in Japanese Vietnamese Portuguese

This tip for generating code uses new features introduced in Eclipse Galileo. However, you can use some of the techniques covered here — such as generating getters and setters — in older versions of Eclipse, such as Ganymede, as well.

Code-generation overview

Of the features I use daily in Eclipse, the items in the Source menu for code generation are at the top of the list. It took me a while to learn how to use them effectively, but when I did, I could build Java classes very quickly.

For instance, when I create a new class, I no longer spend any time writing setters and getters (accessors). I don't write most of the constructors. Instead, I create the class and quickly type the private variables I'll be using in the class, like those in Listing 1.

Listing 1. Private variables
public class Automobile {

    private String make;
    private String model;
    private String year;

}

When I'm done, I click Source > Generate Getters and Setters, then select the private variables I just typed that I want to expose using public accessors. To initialize some of them using a constructor, I click Source > Generate Constructor using Fields to quickly create them. Within just a few mouse clicks, I have a class that can be nearly complete, depending on what I want to do with it (see Listing 2). Best of all, the newly created code will respect the code formatting rules I've set up in my Eclipse preferences.

Listing 2. Auto-creating constructors and accessors
public class Automobile {

    private String make;
    private String model;
    private String year;

    public String getMake() {
        return make;
    }

    public Automobile(String make, String model, String year) {
        super();
        this.make = make;
        this.model = model;
        this.year = year;
    }

    public void setMake(String make) {
        this.make = make;
    }

    public String getModel() {
        return model;
    }

    public void setModel(String model) {
        this.model = model;
    }

    public String getYear() {
        return year;
    }

    public void setYear(String year) {
        this.year = year;
    }

}

In addition to the code you can generate with the items in the Source menu, you can generate a lot of code by using the Ctrl+Space shortcut for writing many common blocks of code. To figure out the names you need to use to generate specific blocks, look in the Preferences window. For instance, typing lazy, then pressing Ctrl+Space generates Java code you can use for lazy loading.


Settings for code generation

You modify settings for code generation of new methods in the Preferences window, under Java > Code Style > Code Templates.

Figure 1. The Java > Code Style > Code Templates preferences
Java/Code Style/Code Templates preferences

Codify your best practices

As a technical lead on a few projects, I've identified certain best practices that I wanted our project to use. I put them in the Java code templates and made them available for importing by the members of the team.

The Java > Editor > Code Templates settings in the Preferences window lists the templates by name (see Figure 2). Look through the templates that come with Eclipse. You can add your own and even import them, as well.

Figure 2. The Java > Editor > Code Templates preferences
Java/Editor/Templates preferences

Using toString() generation

A new feature in Eclipse Galileo is the ability to generate toString() methods. By default, the toString() method prints a representation of the class that may not really show the properties you want to see. Consider the main method in Listing 3.

Listing 3. Printing the Automobile using toString()
public class Main {
    public static void main(String[] args) {
        Automobile auto = new Automobile("Toyota", "Corolla", "1993");
        System.out.println(auto.toString());
    }
}

The output from this application is shown in Listing 4.

Listing 4. Output from the Main method
Automobile@77df38fd

Before Galileo, I would have to write the toString() method by hand. Although it's not that prohibitive for this small class, if the class had many more fields, it would take a while. I might want to do more than simply concatenate the values: I might want to check for nulls. Maybe I want to use a StringBuilder to get better performance. But with Galileo, I can do all this with Source > Generate toString(), as Figure 3 shows.

Figure 3. Generate toString()
Generate toString()

After clicking Finish, the new toString() method looks likes Listing 5.

Listing 5. Automatically generated toString() method
...
    @Override
    public String toString() {
        return "Automobile [" + (make != null ? "make=" + make + ", " : "")
                + (model != null ? "model=" + model + ", " : "")
                + (year != null ? "year=" + year : "") + "]";
    }
...

Now, when the main method runs, the output looks like that in Listing 6.

Listing 6. Output from the auto-generated toString() method
Automobile [make=Toyota, model=Corolla, year=1993]

Formatting the string

Even though the output shown in Listing 6 is a lot more descriptive than the original output in Listing 4, it might be even better to adjust the format a bit to make it even more readable, like "1993 Toyota Corolla (Automobile)." Custom templates allow you to adjust the output generated for the toString() method.

Remove the toString() method and click Source > Generate toString() again. This time:

  1. Click Edit next to the String format drop-down list.
  2. Click New.
    Figure 4. Adding a new format
    Adding a new format
  3. Type something like ${member.value} ${otherMembers} (${object.className}) in Pattern, give it a name, and click OK.

With the new pattern selected, click OK on Generate toString(). The new code looks like that in Listing 7.

Listing 7. Updated toString() method
...
    @Override
    public String toString() {
        return (make != null ? make + " " : "")
                + (model != null ? model + " " : "")
                + (year != null ? year : "") + " (Automobile)";
    }
...

Now, when you run the main method, the Automobile object's toString() output looks like Listing 8.

Listing 8. Output from the Automobile object's toString() method
Toyota Corolla 1993 (Automobile)

Working with arrays

The toString() generator also gives you the ability to handle arrays. Consider Listing 9, which shows a new array of strings called options.

Listing 9. The options string array
        Automobile auto = new Automobile("Toyota", "Corolla", "1993");
        String[] options = new String[] {
                "Automatic Transmission",
                "Power Brakes",
                "Power Windows"
        };
        // new generated method after adding private String[] options;
        auto.setOptions(options);
        System.out.println(auto.toString());
        // prints this:
        // Toyota Corolla [Ljava.lang.String;@defb836 1993 (Automobile)

Normally, the native toString() method prints a representation of the array just like the original representation of the object, without really showing the contents. However, the option List contents of arrays instead of using native toString changes that. With that option selected, the toString() method can be regenerated, and the new output looks like Listing 10.

Listing 10. Output from the regenerated toString() method
Toyota Corolla [Automatic Transmission, Power Brakes, Power Windows] 1993 (Automobile)

Limiting the output

If some of the arrays are very large, you can limit the contents printed by selecting Limit number of items in arrays/collections/maps and setting the limit (see Figure 5). Doing so prevents the toString() method from printing a lot of output.

Figure 5. Printing array contents but limiting them
Limiting array contents

See Listing 11 as an example of the limit set to 2.

Listing 11. Limiting array contents to 2
Toyota Corolla [Automatic Transmission, Power Brakes] 1993 (Automobile)

Using hashCode() and equals()

Using the Eclipse Galileo hashCode() and equals() generation really comes in handy when you want to create rules that make your objects equal based on the actual values in the fields. This is different from the default equals() behavior because even objects with identical values by default won't be equal. Consider the code in Listing 12.

Listing 12. The default behavior of the equals() method
public class Main {
    public static void main(String[] args) {
        Automobile auto = new Automobile("Toyota", "Corolla", "1993");
        String[] options = new String[] {
                "Automatic Transmission",
                "Power Brakes",
                "Power Windows"
        };
        auto.setOptions(options);
        
        Automobile auto2 = new Automobile("Toyota", "Corolla", "1993");
        String[] options2 = new String[] {
                "Automatic Transmission",
                "Power Brakes",
                "Power Windows"
        };
        auto2.setOptions(options2);
        
        System.out.println("Autos 1 and 2 are equal():  " + auto.equals(auto2));
        
    }
}

Even though all the properties are set to identical values, the code prints Auto 1 and 2 are equal(): false when executed.

To change this behavior, click Source > Generate hashCode() and equals() to generate a new version of the equals() method that compares all the fields, like the one shown below.

Listing 13. Comparing all fields in the new equals() method
    @Override
    public int hashCode() {
        // snipped...
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Automobile other = (Automobile) obj;
        if (make == null) {
            if (other.make != null)
                return false;
        } else if (!make.equals(other.make))
            return false;
        if (model == null) {
            if (other.model != null)
                return false;
        } else if (!model.equals(other.model))
            return false;
        if (!Arrays.equals(options, other.options))
            return false;
        if (year == null) {
            if (other.year != null)
                return false;
        } else if (!year.equals(other.year))
            return false;
        return true;
    }

Now, when you execute the code, the two objects are compared using the overridden equals() method, and they are equal.

Another new feature in Eclipse Galileo is the ability to generate blocks for the if statement. It's nice to have this new feature if you don't already have Source > Clean Up configured to change single-line if statements to blocks. Avoiding single-line if statements is usually considered a best practice, so many people like to make sure they do this in their code.


Conclusion

The new features in Galileo for generating toString() methods add to the existing ability in Eclipse to generate a lot of the Java code. With practice, you can learn which code you have to type and which code you can generate, making a lot less work for you.

Resources

Learn

Get products and technologies

Discuss

  • The Eclipse Platform newsgroups should be your first stop to discuss questions regarding Eclipse. (Selecting this will launch your default Usenet news reader application and open eclipse.platform.)
  • The Eclipse newsgroups has many resources for people interested in using and extending Eclipse.
  • Participate in developerWorks blogs and get involved in the developerWorks community.

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into Open source on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Open source
ArticleID=421331
ArticleTitle=Faster Java coding in Eclipse Galileo
publish-date=08182009