Making Java Code Null-Safe With JPlus

Null-pointer exceptions are a common error in Java, causing inconvenience for many developers. Preventing null pointer exceptions in advance is important, but for developers who want to focus solely on logic, handling them can be tedious. Moreover, it’s not always easy to account for every scenario. Typically, static analysis tools are used to detect potential null pointer issues, but developers still have to find and fix the code themselves. JPlus reduces that burden. Let’s write null-safe Java code with JPlus.

1. Access the JPlus GitHub repository and download the IntelliJ plugin

https://github.com/nieuwmijnleven/JPlus

2. nstall the JPlus IntelliJ plugin

  • Open IntelliJ
  • Go to File > Settings > Plugin > ⚙️ > Install Plugin from Disk
  • Select the downloaded intellij-plugin-0.1-mvp-alpha.zip
  • Restart IntelliJ

3. Open the example project in IntelliJ

  • Go to File > New > Project from Version Control
  • Enter https://github.com/nieuwmijnleven/JPlusExample
  • Click the Clone button

4. Create a JPlus file for User.java in the Project View

  • Right-click User.java in the Project View
  • Select Convert Java File to JPlus File from the menu

5. Making Java code null-safe with JPlus

User.jplus

package jplus.example;

class User {
    // Name is required
    String name;        
    // Address can be null
    Address address;   

    User(String name, Address address) {
        this.name = name;
        this.address = address;
    }

    //remain codes
}

Opening the generated User.jplus file, you can see error messages in the Problems tab.

By default, JPlus assumes all reference types are non-nullable, which causes these errors. The problematic parts are where the constructors of the User and Address classes are called.

User(String name, Address address) {
    this.name = name;
    this.address = address;
}

Address(String city) {
    this.city = city;
}

User user1 = new User("Jeroen", new Address("New Amsterdam"));
User user2 = new User("Jane Smith", null);
User user3 = new User(null, new Address(null));
  • The constructor parameters for User and Address are all non-nullable. Passing null violates the null-safety rules.
  • Therefore, errors occur for user2 and user3.

Making Java code null-safe with JPlus

(1) Assume the name field is required

  • Add final to the name field
  • Use apply constructor(required) to auto-generate the required constructor
  • Press Ctrl + S to save, so changes reflect in User.java.

User.jplus

package jplus.example;

apply constructor(required);

class User {
    // Name is required
    final String name;        
    // Address can be null
    Address address;   

    User(String name, Address address) {
        this.name = name;
        this.address = address;
    }

    //remain codes
}
  • At the end, the generated User.java includes a constructor for the final name field.

(2) Assume the address field is nullable

  • Add ? to the Address type
  • Also mark the constructor parameter as nullable
package jplus.example;

apply constructor(required);

class User {
    // Name is required
    final String name;
    // Address can be null
    Address? address;

    User(String name, Address? address) {
        this.name = name;
        this.address = address;
    }

The Problems tab shows:

  • address is a nullable variable. But it directly accesses city. Consider using null-safe operator(?.)

  • Use the null-safe operator ?.:
    // Safely get the city name of the address
    String getCity() {
        return address?.city;
    }

Then only the constructor-related error for name remains.

Replace null with “No Name” because name field is required.

User user3 = new User("No Name", new Address(null));

Now only one error remains:

  • The 1st argument of the Address constructor is a non-nullable variable, but a null value is assigned to it.

(3) Assume city in Address is nullable

  • Add ? to String type and constructor parameter
static class Address {
    // City can be null
    String? city;

    Address(String? city) {
        this.city = city;
    }
}

All nullability errors disappear. Save the file (Ctrl + S) to generate new User.java.

User.java made null-safe by JPlus

package jplus.example;

//apply constructor(required);

class User {
    // Name is required
    final String name;
    // Address can be null
    Address address;    

    public User(String name) {
        this.name = name;
    }

    User(String name, Address address) {
        this.name = name;
        this.address = address;
    }

    // Safely get the city name of the address
    String getCity() {
        return (((address)!=null)?(address.city):null);
    }

    // Get the display name of the user
    String getDisplayName() {
        return name;
    }

    // Address class
    static class Address {
        // City can be null
        String city;

        Address(String city) {
            this.city = city;
        }
    }

    public static void main(String[] args) {
        // Null-safe object creation
        User user1 = new User("Jeroen", new Address("New Amsterdam"));
        User user2 = new User("Jane Smith", null);
        User user3 = new User("No Name", new Address(null));

        // Null-safe access
        System.out.println(user1.getDisplayName() + "'s city: " + user1.getCity()); // Jeroen's city: New Amsterdam
        System.out.println(user2.getDisplayName() + "'s city: " + user2.getCity()); // Jane Smith's city: No Address
        System.out.println(user3.getDisplayName() + "'s city: " + user3.getCity()); // No Name's city: No Address
    }
}

Run the program:

  • Go to User.java
  • Select Run > ‘Run User.java’

No NullPointerException occurs, but some outputs are null. Use the Elvis operator ?: to provide default values.

Edit getCity() in User.jplus:

class User {
    //...
    // Safely get the city name of the address
    String getCity() {
        return address?.city ?: "No City";
    }
   //...
}

Also, be sure to press Ctrl + S to save. This ensures that the new Java code is saved in User.java.

User.java made null-safe by JPlus

package jplus.example;

//apply constructor(required);

class User {
    // Name is required
    final String name;
    // Address can be null
    Address address;    

    public User(String name) {
        this.name = name;
    }

    User(String name, Address address) {
        this.name = name;
        this.address = address;
    }

    // Safely get the city name of the address
    String getCity() {
        return ((((((address)!=null)?(address.city):null))!=null)?((((address)!=null)?(address.city):null)):("No City"));
    }

    // Get the display name of the user
    String getDisplayName() {
        return name;
    }

    // Address class
    static class Address {
        // City can be null
        String city;

        Address(String city) {
            this.city = city;
        }
    }

    public static void main(String[] args) {
        // Null-safe object creation
        User user1 = new User("Jeroen", new Address("New Amsterdam"));
        User user2 = new User("Jane Smith", null);
        User user3 = new User("No Name", new Address(null));

        // Null-safe access
        System.out.println(user1.getDisplayName() + "'s city: " + user1.getCity()); // Jeroen's city: New Amsterdam
        System.out.println(user2.getDisplayName() + "'s city: " + user2.getCity()); // Jane Smith's city: No Address
        System.out.println(user3.getDisplayName() + "'s city: " + user3.getCity()); // No Name's city: No Address
    }

}

Run the program:

  • Go to User.java
  • Select Run > ‘Run User.java’

All null values are replaced with “No City”

Summary

With JPlus, you can easily enforce null-safety in Java code. JPlus fully supports Java syntax, making it accessible for Java developers. The final code is converted to Java, allowing developers to review it. JPlus is still in its early stages and needs support from the Java community. Even small, regular contributions will help complete this project. Your support can make a real impact.

Become a Sponsor via Github

Become a Sponsor via PayPal.me

Similar Posts