@UtilityClass -- should be non-experimental! But JavaDoc?

126 views
Skip to first unread message

Morten Sabroe Mortensen

unread,
Jul 28, 2025, 7:36:52 AM7/28/25
to Project Lombok

I am extremely found of @UtilityClass. It does have value, class being marked as final, private constructor generated. There is no doubt that it has value. None whatsoever.

However, there are two issues:

1) Instead of actively marking elements, methods as static it is better to verify it and reject the existence of non-static elements. It is best to keep the keyword "static" for plain understanding.

2) JavaDoc, in general, I hope it is not specific to my setup alone, but the class is not marked "final", the constructor is public, and there is no trace of the annotation, which I guess is okay. Is it possible to have the JavaDoc tool run on the generated code?

Regards,
Morten Sabroe Mortensen

Jens Bannmann

unread,
Dec 14, 2025, 3:57:12 PM12/14/25
to Project Lombok
1) In my code bases, I established the convention of explicitly adding `static` to all members of @UtilityClass classes, but for a different reason: without that, the methods would not be usable with `import static`.
To help enforce conventions around @UtilityClass members being static or not, I wrote the a set of rules for my light-weight static code analysis tool mandor:

  • UtilityClassMemberInconsistentlyStatic
    members should be declared consistently static / not static (i.e. within every @UtilityClass, either all members have the `static` keyword, or none)

  • UtilityClassMemberMarkedStatic
    members should not be declared static as it is redundant

  • UtilityClassMemberWithoutStaticModifier
    members should be explicitly declared static to make them usable in static imports
Obviously, the rules are mutually exclusive. Projects should pick one and add it to their unit tests. Here's an example how to run the third rule:

public class ExampleMandorTest
{
    @Test
    public void testRule()
    {
        new SourceBundle().importSources("src/main/java")
            .importSources("src/test/java")
            .verifyStrictly(new UtilityClassMemberWithoutStaticModifier());
    }
}

For a project with 48K lines of code, this takes only about 3 seconds on my machine.

Timofey Gorshkov

unread,
Jun 11, 2026, 4:48:26 PM (yesterday) Jun 11
to Project Lombok
I think this could be a good transition path:

- while @UtilityClass remains experimental, add explicit-static enforcement as an opt-in mode;
- if @UtilityClass is ever promoted to stable, make explicit-static enforcement the default stable behavior.

That way existing experimental users are not broken immediately, but the stable API
does not inherit the current implicit-static behavior that causes the named static
import issue in javac.

Timofey Gorshkov

unread,
Jun 11, 2026, 4:48:39 PM (yesterday) Jun 11
to Project Lombok
I think this could be a good transition path:

- while @UtilityClass remains experimental, add explicit-static enforcement as an opt-in mode;
- if @UtilityClass is ever promoted to stable, make explicit-static enforcement the default stable behavior.

That way existing experimental users are not broken immediately, but the stable API does not inherit the current implicit-static behavior that causes the named static import issue in javac.
Reply all
Reply to author
Forward
0 new messages