Description
Affects PMD Version: 6.5.0-SNAPSHOT
Rule: ConstantsInInterface
Description:
Avoid constants in interfaces. Interfaces should define types, constants are implementation details better placed in classes or enums. See Effective Java, item 19.
suggests to place constants in enums. I assume that doesn't imply to remove the static modifier and was wondering how that's possible since placing anything before the enum listing causes an identifier expected compilation error and placing them after the listing causes an illegal forward reference (compilation) error. Placing them in a private interface as suggested (as only solution) in https://stackoverflow.com/questions/23608885/how-to-define-static-constants-in-a-java-enum causes the ConstantsInInterface
to fail again. It'd be nice to see the solution from Effective Java in the docs (it shouldn't be an issue to rephrase it and add a citation to the original).
Code Sample demonstrating the issue:
I can provide one if it's really necessary.
Running PMD through: Maven
Activity
jsotuyod commentedon Jun 24, 2018
Effective Java's item 19 (22 in the 3rd edition, using the name of item that remains unchanged may be better than using the number) states:
If they are not, a constant utility class (private constructor) is preferred.
It's not that both are equivalent, but rather that you should use enums if constants describe enumerations, or a constant utility class otherwise.
krichter722 commentedon Jun 26, 2018
I'm sorry, I don't get it. My point is, assuming we have
where do we put
REWARD
? InBonusConstants
it causesConstantsInInterface
failure (depending on the configuration). We can't put it inPermission
because it causes the compilation errors mentioned in the question.Apparently, the point of the quoted book passage is to put
REWARD
into a utility class rather than an interface. It should be explained why this is better coding (I don't see it in the idea and the failure message). The reference to enums seems obscure because of the impossibility in certain cases to place the constant into the enum (see above). It'd be great if the new message or details would explain both (in the sense of "Don't make me think").jsotuyod commentedon Jun 26, 2018
In that particular case, a utility class is your best option. Moreover, if only the enum is using it, I'd use a inner static utility class to avoid exporting it altogether:
As for the rule in general, consider the scenario:
In this case, the constant values (0, 1, 2, 3) have no real meaning. This is a poor-man's enumeration, hence, as the book states:
Meaning, we should favor writing:
For other scenarios (as your own), the utility class is the best alternative. The book provides a number of reasons for this. The first several deal specially with the scenario where such constants are referenced "locally" by having a concrete class implement it, ie:
That means, I shouldn't care if a class uses a given constant, so declaring it by implementing an interface is breaking encapsulation.
The book continues:
There is nothing in the code preventing you from doing this. Just as nothing prevents developers from doing:
All of these constitute legal code that will compile and run under Java. So, in general, as a developer, you want to shape your APIs to avoid all such nonsense usages. The utility class fixes all of these, as so do the enum where it applies.
krichter722 commentedon Jun 26, 2018
Excellent explanation, thanks a lot! I'd be very happy to see that going into the failure message description (directly to through a link, maybe to the wiki where you could put this).
dague1 commentedon Mar 1, 2023
@all-contributors please add @dague1 for doc
allcontributors commentedon Mar 1, 2023
@dague1
I've put up a pull request to add @dague1! 🎉
adangel commentedon Mar 2, 2023
Hi @dague1 , thanks for contributing. Would you mind to create your PR directly on this repo (pmd/pmd), rather than on a fork (Aliasbai/pmd)? -> AliAsbai#9
dague1 commentedon Mar 2, 2023
Hi, @adangel
Sure, I will try to do that!
2 remaining items