Heart containing Coding Chica Java 101

A Little Bit of This! Java’s Reference to Self

TIP: References Quick List

Table of Contents

  1. Table of Contents
  2. Introduction
  3. Example Variable Shadowing Bug
    1. Compile-Time Detection: Java’s Keyword final
    2. Option 1: Remove the Shadowing
    3. Option 2: Calling out Desired Scope
  4. Method References
  5. Constructor Calls
  6. Summary

Introduction

Even when variable shadowing occurs, such as we described in the last post, we can still access instance variables for our Java objects.

Example Variable Shadowing Bug

An example of a bug resulting from variable shadowing is when a setter method accidentally reassigns the value of an input parameter to itself, instead of the intended instance variable:

public class Pet {
    private String name = null;

    public void setName(String name) {
        // In this line, we are accidentally reassigning the input parameter, which has the same name as the instance variable.
        name = name;
    }
}

After calling the setter, the Pet object’s name would still be null. By using the same variable name in the method parameter and the assignment we could easily over look this bug, which could cause our code to behave in unexpected ways during execution.

Compile-Time Detection: Java’s Keyword final

By adding the final keyword to the setter’s input parameter called name, the Java compiler can try to help us detect these types of accidental assignment bugs.

public class Pet {
    private String name = null;

    public void setName(final String name) {
        // Because we have added the final keyword above, the following line will no longer compile, 
        // alerting us to the accidental input parameter assignment.
        name = name;
    }
}

However, how do we fix these types of issues?

Option 1: Remove the Shadowing

If we rename one of the variables, then there is no longer variable shadowing occurring, and we can reference each variable by a now-unique variable name.

public class Pet {
    private String name = null;

    public void setName(final String newName) {
        name = newName;
    }
}

The code above should again compile and function as expected.

Option 2: Calling out Desired Scope

Another option is to explicitly call out that the variable belongs to the object instance (AKA the this keyword) or is a static/class-level variable (by prefixing the variable with the class name).

public class Pet {
    private String name = null;

    public void setName(final String name) {
        // By adding the this. prefix, we tell Java that we want to use the instance variable, rather than the local variable.
        this.name = name;
    }
}

Technically, the Java compiler will also understand if you tried to use the same this keyword with a static variable. However, style checkers will likely flag this as an issue, as the variable belongs to the class, rather than the instance, so using the class name as the prefix signals to the reader that the variable is shared.

public class JDBCConnectionFactory {
    private static Connection connection = null;

    public static Connection getSharedConnection () {
        // Using this example to show you how the static prefixing might look, although in this case, there is no variable shadowing.
        // Caution - This code also isn't thread safe, but trying to keep the example simple.
        if (JDBCConnectionFactory.connection == null) {
            // logic to create a new JDBC connection
        }
        return JDBCConnectionFactory.connection;
    }
}

By using the class name as a prefix, rather than this, the reader can quickly tell that the variable is shared across instances of that class. However, in this case, since there is no variable shadowing, the connection variable could also be used without the class name prefix.

Method References

Just like variable inside of the object can be referenced with the this keyword, so can methods, but doing so is optional.

// Within one method, the current object's methods can be called with or without the this prefix.
this.setName("My new name");
setName("My new name");

The two method calls above are equivalent. The question is more about desired style. Most often, I see the this keyword omitted in these scenarios.

Similar to variables, while static methods can also be referenced using the this keyword and the Java compiler would understand, if there’s a prefix on a static method call, it should likely be the class name, rather than this. That way, readers of the code will more easily understand that the method is not specific to the instance.

Constructor Calls

One constructor can call another constructor using the this keyword, as well. For example, if you want to provide a constructor that supplies default value(s) but otherwise reuses the logic of a constructor with more arguments, then the this keyword may be helpful.

public class Pet {
    private final int numberOfLegs;
    
    public Pet() {
        this(4);
    }

    public Pet(final int legCount) {
        numberOfLegs = legCount;
    }
}

The example above is pretty simple, so we don’t save any lines of code by reusing the separate constructor. However, if there were many instance variables that needed to be initialized, or if the logic inside of the second constructor were more complex than just storing the value, we may see benefit by calling one constructor from another.

Summary

In Java, the this keyword can be used to indicate that an instance variable is being referenced. The this keyword can also be used for static variables, but it is not recommended, as doing so may confuse readers. Instead, the class name can prefix a static variable to indicate that the variable is static/shared by all of the members of a class. Static variable references that use the this keyword will likely be flagged by style checkers, again as this may be confusing to readers and make it harder to spot bugs in the code. Bugs can also occur by omitting the this keyword if variable shadowing is present.

The this keyword can also be used in Java for method calls. Constructors can call other constructors using the this keyword. Aside from constructors calling other constructors, the keyword this is available for use, but whether or not it should be used is more of a question of style. Often, I see this omitted in this scenario to save space and reduce boilerplate. Static method calls could also be prefixed with this, but if any prefix is included, it should likely be the class name, rather than this, so it is clear to the reader that the method belongs to the entire class, rather than one instance.

A Little Bit of This! Java’s Reference to Self

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.