-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[java] ClassWithOnlyPrivateConstructorsShouldBeFinal - fix FP with inner private classes #3668
[java] ClassWithOnlyPrivateConstructorsShouldBeFinal - fix FP with inner private classes #3668
Conversation
Generated by 🚫 Danger |
non-abstract abstract classes These are abstract classes without abstract methods. They can be made final without problems.
Ok, much better now: Only real false-positive cases are now removed. |
pmd7-ClassWithOnlyPrivateConstructorsShouldBeFinal-abstract
...sourceforge/pmd/lang/java/rule/design/ClassWithOnlyPrivateConstructorsShouldBeFinalRule.java
Outdated
Show resolved
Hide resolved
I'm unsure excluding abstract classes is the right approach here… If we had a top level class: public abstract FooUtils {
private FooUtils() {
throw new AssertionError("Do not instantiate utility classes");
}
…
} I'd still consider this something to be flagged. Here I think this false positive can be addressed in a different way, not by waving abstract classes, but by waving nested classes. This is down to the fact that these "private constructors" can actually be invoked within the top level class by way of the auto generated default-visiblity constructor the compiler generate (and hence, do not contain "only private constructors" as the rule flags). EDIT: Java 11+ doesn't generate the synthetic method, but can still invoke the private members due to nest-based access control |
Nested classes should only be flagged, if they are not instantiated.
Hm... I'm working on it, but I'm regularly loose what this rule should do... so, I'm trying to describe, what should be correct as far as I understand (please correct me...): The rule ClassWithOnlyPrivateConstructorsShouldBeFinal should flag classes, that can't be extended, because it has only private constructors. So far so good. This has nothing to do with a constructor, that prevents instantiation by throwing a exception. This creates the following test cases: Now considering inner classes. There is also #2536 . Let's only consider first inner classes that are visible somewhere else (not private inner classes). The same test cases apply here. For inner classes that are public, package-private or protected - if they only contain private constructors -> class should be made final. But unless they are subclassed in the same compilation unit (then making it final would result in compilation error, so the rule shouldn't suggest that). Now the very special case private inner classes. These can be used inside the same compilation unit without restriction. So, making a constructor private here does not prevent subclassing. We probably indeed should do nothing there. We could suggest to make the class final - but for other reasons (there are no subclasses) - and therefore it would be a different rule. I think, I was additionally thrown off now by the sentence in the rule description "... unless the private constructor is invoked by a inner class". These are different things... It should probably be "... unless it is a private inner class". Whether the constructors are invoked or not doesn't matter. I'll try to update the test cases accordingly.... |
classes.
I found this while trying to run PMD 7 on PMD 7 sources (dogfood).
Rule: ClassWithOnlyPrivateConstructorsShouldBeFinal
E.g.:
pmd/pmd-core/src/main/java/net/sourceforge/pmd/cpd/GUI.java
Line 775 in f36b99f