Came across this coding standard from Oracle:
Do not use a static array of strings.
What is the reason for this recommendation?
Came across this coding standard from Oracle:
Do not use a static array of strings.
What is the reason for this recommendation?
Arrays are mutable containers. Global mutable container without built-in synchronisation is multi-threaded horror waiting to happen. You can store reference to that array in some local context and then have it's content changed at any time without you knowing it. Or vice versa you may assume that this is convenient global state, but then every client must know the exact correct way to synchronise its access to that state. And somebody will forget and bug will be born.
I believe it's due to developers using String
as a replacement (most likely unintentionally) for enumeration, and the static String[]
was a way to group these types.
For all we know, this article could be targetting the Java 4- code base.
Not saying this was written during Java 4, but that most production code existing at the time may have been written in Java 4. The lack of autoboxing pitfalls (which are quite common) and no mentions of generics (raw types) lead me to believe this.
I don't believe it has to do with global state, since I'm sure singletons would have been mentioned (being the pinnicle of global state).
I doubt concurrency is the issue, since the article does not mention anything else about sharing data across threads, or even using multiple threads. You would assume they would have mentioned SOMETHING about the thread environment.
Misusing String
for type enumeration purposes was common back in the day, so I'm sure this statement (if related to what I think it is) was a lot easier to understand back then. I find it to be quite a stretch that this statement was just as cryptic back then, yet no one has cared to question it, resulting in the lack of google results when digging into this.
Developers to this day still misuse String
for type information. With the lack of enumeration, I could see how a developer may be tempted to do something along the lines of:
class Card {
static String HEARTS = "HEARTS";
static String DIAMONDS = "DIAMONDS";
static String CLUBS = "CLUBS";
static String SPADES = "SPADES";
static String[] CARD_TYPE = {
HEARTS, DIAMONDS, CLUBS, SPADES
};
private String type;
//...
}
Using the array for easy looping (as one would do with Enum.values()
).
Using String
as enums is frowned upon:
It's not type safe. If MAGE
can be passed to a method, ANY String
could be passed in it's place. This leads us to...
Mistakes are easier to make. It's possible for a typo to go unnoticed, which may seem small for the average developer, but could be catastrophic for businesses with large code bases and many consumers (such as Oracle). For example: a hidden typo results in a comparison returning false. This prevents a service from launching. The lack of this service results in a bug. If not found before users notice the bug, it could lead to exploits.
This could be fix by using Java's built-in type system:
abstract class CardType {
}
class Hearts extends CardType {
}
....
Or
enum CardType { HEARTS, DIAMONDS, ...; }
Not only is this less error-prone, but it allows you to use polymorphism, which prevents the need to check the value in order to trigger a specific behavior. The behavior can be contained in the type itself.
Although I can't promise this is the correct answer, it seems to be the only answer that does not depend on the use of modifiers that weren't mentioned in the statement.
Yes, the example above does not use proper constants (lacks the final
). But although constants should be preferred, they are not required to benefit from this design (being able to use String
for type information) nor does the design require it to work . Since people may not have always used constants for this, they could have left out the final
or "array of constants" for this purpose.
This way undermines the object oriented paradigm. Moreover it's a security hole, because the final
keyword assures only reference value and leaves the content to be changed easily.
Some of them are arbitrary. For example, having a single return statement is a matter of style (maybe related to some analysis tool that in the past couldn't handle multiple return paths?).
Some of them are outdated. Like the one about StringBuilding.
I'd assume that these are a mixture of old performance recommendations and style guides. I'd reckon the String static array one falls in the latter category, with maybe a hint towards what others have said about the possible link with the introduction of enums (maybe that's why Strings in particular).
Some of them are actually completely unfeasible when you try to apply them to modern frameworks: "Do not use a switch to make a call based on the object type.", for example, is at the core of Akka Java (onReceive) method and in general in any type of pattern matching in Java...
While I admit it's curious, I'd say it's probably something related to some specific tool they used in the past or to the enum possibility mentioned. But it's just my opinion, not a definitive answer.