Before the introduction of enums, it was common practice to use integer constant values to indicate different variations of domain constants.
However, this should no longer be necessary, since enums can replace integer constants and communicate an upper limit of the variation count. This is because when an enum class is create it communicates the limited range of variations to the compiler.
Never use the ordinals of an enum class to identify a given enum. Ordinals are based on the order of enums and will therefore change if the order is changed or options areadded/removed to the selection.
Instead assign an integer value directly to the enum value by giving the enum class an integer field and create a constructor with the appropriate integer value assigned to the field.
In the past it was common to use bit fields to work with multiple enum at the same time.
method(EnumClass.ONE | EnumClass.TWO);
However, since the introduction of EnumSets, there is no longer any reason to use this type of operation.
method(EnumSet.of(EnumClass.ONE, EnumClass.TWO));
Instead of using the ordinals of an enum class to index the enums, it is preferable to use the EnumMap.
Map<EnumClass, set> map = new EnumMap<>(EnumClass.class);
It is possible to implement interfaces on enum classes, which thereby requires that all enum types have to implement the interface’s methods. It is therefore recommended to only use this feature with simple interfaces.
This could be useful to emulate the behaviour of multiple small classes.
public enum CharacterClass implements Weapon { KNIGHT (1) { public int damage(int str, int agi){ return str * 30 + agi * 10; } }, NINJA (2) { public int damage(int str, int agi){ return str * 10 + agi * 40; } }; }
Several concepts in Java rely on naming classes and members correctly to work as expected.
For instance, test cases in JUnit 3 required the work “test” in the beginning of each test method, and method overriding superclass method needs to be spelled in the exact same way. (including upper- and lowercase)
However, in many of these naming pattern scenarios, it is now possible to use annotations.
With the @Test annotation introduced in JUnit 4, it has now become much simpler to indicate all the test cases.
Likewise, the @Override annotation will show errors in the code, if there is no superclass method to override.
Annotations are a useful way of avoiding reliance on naming patterns, so use them as frequently as possible.
As mentioned in item 39, it is recommended to always use the @Override annotation, since it will make the compiler show errors in case there is no superclass method to override.
The override annotation should therefore always be used as it ensures reliability in between inheriting classes.
Marker interfaces are used to indicate that a class follows a specific set of rules.
For example, a class using the @Serializable annotation indicates that the class is serializable.
Use marker interface whenever relevant, as they are providing fine way of communicating intents and concepts between developers.
My name is Daniel H. Jacobsen and I’m a dedicated and highly motivated software developer with a masters engineering degree within the field of ICT.
I have through many years of constantly learning and adapting to new challenges, gained a well-rounded understanding of what it takes to stay up to date with new technologies, tools and utilities.
The purpose of this blog is to share both my learnings and knowledge with other likeminded developers as well as illustrating how these topics can be taught in a different and alternative manner.
If you like the idea of that, I would encourage you to sign up for the newsletter.
Cheers! 🍺
INTEGU uses cookies to personalize your experience and provide traceability for affiliate links. By using the website, you agree to these terms and conditions. To learn more see the privacy policy page.