Javac Effectively Final Compiler Plugin

Javac plugin that requires method parameters to either be explicitly final or effectively final. This enforces the best practice of treating the parameters as final without the burden of having to type final everywhere.

License

License

GroupId

GroupId

com.massfords
ArtifactId

ArtifactId

effectively-final
Last Version

Last Version

1.0
Release Date

Release Date

Type

Type

jar
Description

Description

Javac Effectively Final Compiler Plugin
Javac plugin that requires method parameters to either be explicitly final or effectively final. This enforces the best practice of treating the parameters as final without the burden of having to type final everywhere.
Project URL

Project URL

https://github.com/massfords/jaxb-visitor
Source Code Management

Source Code Management

https://github.com/massfords/effectively-final

Download effectively-final

How to add to project

<!-- https://jarcasting.com/artifacts/com.massfords/effectively-final/ -->
<dependency>
    <groupId>com.massfords</groupId>
    <artifactId>effectively-final</artifactId>
    <version>1.0</version>
</dependency>
// https://jarcasting.com/artifacts/com.massfords/effectively-final/
implementation 'com.massfords:effectively-final:1.0'
// https://jarcasting.com/artifacts/com.massfords/effectively-final/
implementation ("com.massfords:effectively-final:1.0")
'com.massfords:effectively-final:jar:1.0'
<dependency org="com.massfords" name="effectively-final" rev="1.0">
  <artifact name="effectively-final" type="jar" />
</dependency>
@Grapes(
@Grab(group='com.massfords', module='effectively-final', version='1.0')
)
libraryDependencies += "com.massfords" % "effectively-final" % "1.0"
[com.massfords/effectively-final "1.0"]

Dependencies

test (1)

Group / Artifact Type Version
junit : junit jar 4.12

system (1)

Group / Artifact Type Version
com.sun » tools jar 1.8.0

Project Modules

There are no modules declared in this project.

Overview

It's best practice to not assign to a method parameter in the body of your method. You can find lots of opinions about this but here's a good summary on Stack Overflow.

However, it's a bit tedious to have to write the modifier "final" before each parameter declaration and with the addition of Java 8's "effecitvely final" concept it seems reasonable to relax the requirement of having the final modifier on the parameter and instead move it to a compiler plugin. This is less typing and less clutter in your code.

Explicitly final:

public class ExplicitlyFinalExample {

    public void sendData(final String alpha, final String beta, final int gamma, final List<String> omega) {
        System.out.printf("sending %s, %s, %s, %s\n", alpha, beta, gamma, omega);
    }
}

Effectively final:

public class EffectivelyFinalExample {
    public void sendData(String alpha, String beta, int gamma, List<String> omega) {
        System.out.printf("sending %s, %s, %s, %s\n", alpha, beta, gamma, omega);
    }
}

In both snippets above, the method params are final. They are either final because they are explicitly declared as being final or they are effectively final because they are never assigned to.

However, it's easy for the programmer to break this contract in the effectivley final example by assigning to one of the method params in the body of the method. As long as this method parameter isn't used in an Anonymous Class or within a lambda expression, it's still valid. This is exactly what this plugin is designed to catch during compilation.

Breaking the effectively final contract:

public class BreakingEffectivelyFinalExample {
    public void sendData(String alpha, String beta, int gamma, List<String> omega) {
    
        if (gamma < 100) {
            gamma = 100; // <|--- plugin will generate a compilation error on this line
        }
    
        System.out.printf("sending %s, %s, %s, %s\n", alpha, beta, gamma, omega);
    }
}

Compilation Error

BreakingEffectivelyFinalExample.java:[5,13] error: EFFECTIVELY_FINAL: Assignment to param in `gamma = 100`

Maven Config

You need to tell the maven compiler plugin to use this plugin during compilation.

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.6.1</version>
    <configuration>
        <compilerArgs>
            <arg>-Xplugin:EffectivelyFinal</arg>
        </compilerArgs>
        <forceJavacCompilerUse>true</forceJavacCompilerUse>                
        </configuration>
    <dependencies>
        <dependency>
            <groupId>com.massfords</groupId>
            <artifactId>effectively-final</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>
</plugin>

Versions

Version
1.0