PMD 4.2.5.
PMD reports a constructor as unnecessary when it is a public, no-arg constructor with empty body or only calling super() and states: "Avoid unnecessary constructors - the compiler will generate these for you". However, the compiler generates the constructor with the same access modifier as the class - see http://java.sun.com/docs/books/jls/third_edition/html/classes.html#8.8.9 (for enums it generates a private constructor). So, for example, having a public, no-arg constructor with empty body in a non-public class is not a redundant declaration, but possibly an element of design. And even if not, the suggestion that the compiler will generate the "unnecessary" constructor is misleading, because the compiler will generate a constructor with different access modifier.
Samples:
=== SAMPLE 1 ===
public class Test {
public Test() {
// useless
}
private static class TA {
private TA() {
// useless
}
}
private static class TB {
public TB() {
// not useless - non-private constructor prevents synthetic access from the outer class
}
}
protected static class TC {
protected TC() {
// useless
}
}
}
class A {
public A() {
// not useless
}
}
class B {
B() {
// useless
}
}
=== SAMPLE 2 (from JLS, see link above) ===
package p1;
public class Outer {
protected class Inner{}
}
package p2;
class SonOfOuter extends p1.Outer {
void foo() {
new Inner(); // compile-time access error. If the Inner's class's constructor was public, the code would compile.
}
}
=========
Solution: PMD should report "Unnecessary constructor" when the constructor considered has the same access modifier as the class instead of when it is merely public.
Thank you for the feedback. I wouldn't be surprised if this Rule predates enums in Java.
I will try to spend some time going over your analysis, and seeing how the Rule should be modified to be most accurate.
Yes, in JLS ed. 1 they already say that "If the class is declared public, then the default constructor is implicitly given the access modifier public; otherwise, the default constructor has the default access implied by no access modifier" (there were no inner classes then). Anyway, enums here are just an exception from the general rule - the default constructor is always private for them as opposed to having the same access modifier as the class for "regular" classes. Thanks for looking into the problem!