[java] Fix #1102: improve consistency of utility class detection across rules#6691
Conversation
|
Compared to main: (comment created at 2026-05-25 12:55:58+00:00 for 8fdaa02) |
Changes in JavaRuleUtil.isUtilityClass() * Add support for nested classes * Abstract classes aren't utility classes * Classes with main() method aren't utility classes This was broken before and handled inconsistently
Changes in UseUtilityClass * Add support for initializers * Classes with main() method aren't utility classes * Remove special cases for JUnit3/4 suites - they are handled correctly by the current code.
The implementations are identical.
cb51ad0 to
4b6e158
Compare
|
The most significant user-facing change here is that classes that contain a |
|
Good idea. And I just noticed that this doesn't have a release_notes entry, yet. |
|
Hmm... but you're right. That is fishy... Does having a non-static nested class make the outer class stateful? It doesn't, right? |
|
On the other hand: If we add a private, /throwing/ constructor to |
|
Nested interfaces, records and enums are always static, so the two lines you linked should not affect the utility status of the parent. Nested classes that are not static should probably still make the parent non-utility class. |
TIL. Thanks, that's definitely a TODO.
I think I agree, if only for consistency's sake. Oh, and because of JUnit Jupiters
Do you want to write an issue for that, or should I? |
|
adangel
left a comment
There was a problem hiding this comment.
I see, ClassNamingConvention already uses JavaRuleUtil.isUtilityClass, so nothing to change there.
Don't forget to update the rule descriptions of both rules to add the new definition for utility classes there:
pmd/pmd-java/src/main/resources/category/java/design.xml
Lines 1498 to 1502 in 7db7a0a
pmd/pmd-java/src/main/resources/category/java/codestyle.xml
Lines 265 to 267 in 7db7a0a
Out of scope for this change, but maybe something to consider in the future: I don't think the name of the rule "UseUtilityClass" is a good name... It's more like: "Hey, this class looks like a utility class, but it still can be instantiated although it doesn't have state. This doesn't make sense. Consider to add a private constructor ..." The rule is named better maybe "InstantiableUtilityClass"?
…rnal/JavaRuleUtil.java Co-authored-by: Andreas Dangel <andreas.dangel@adangel.org>
zbynek
left a comment
There was a problem hiding this comment.
As discussed, interfaces, records and enums should not be considered for utility class check, otherwise looks good.
Co-authored-by: Andreas Dangel <andreas.dangel@adangel.org>
Update javadoc of JavaRuleUtil.isUtilityClass()
|
Updated rule descriptions. Nested interfaces, records and enums are static, those no longer prevent a class from being considered a utility class.
|
Co-authored-by: Andreas Dangel <andreas.dangel@adangel.org>
|
Thanks for the reviews! |
Describe the PR
This PR standardizes what
UseUtilityClassRuleandJavaRuleUtil.isUtilityClass()(used byClassNamingConventionsRule) mean by the term "utility class."The new common definition is:
Related issues
Ready?
./mvnw clean verifypasses (checked automatically by github actions)