I have a scenario in which I am using a Query object and a StringBuffer
, in which I will build an SQL query to be executed.
Here it is:
countQueryBuf.append("Select count(e) From " + clz.getSimpleName()
+ " e");
Here my senior told me that it is bad practice to use string literals like "Select count(e) from "
. We can make that:
string public final static selectCount="Select count(e) From "`
in a interface, and then use that in the string buffer. But after seeing this Interfaces with static fields in java for sharing 'constants' question, which says it is bad practice, I am confused. Can anyone let me know what is the best way to do it and prove my scenario?
First of all, it should be emphasized that the prerequisite of you question is flawed. String literals in Java do not produce multiple String
instances, so defining constants pointing to these String
instances does not change the number of instances. But, most likely, your senior didn’t intend to discuss the number of instances with that advice.
String literals can be considered constant values like 123
or 44.1f
. When such values appear somewhere in your code, they are often called “magic literals”, because they appear spuriously, without a recognizable source. In these cases, using a named constant, whose name explains it’s origin, should be preferred. E.g.
static final float COMPACT_DISC_FREQ_KHZ = 44.1f;
tells you something.
In contrast, constants like
static final int ONE = 1;
don’t tell you anything and are no improvement, only an attempt to fake a better coding style. I consider a constant like
static final String selectCount="Select count(e) From ";
to be of the same nonsensical category, as its name doesn’t tell me anything I can’t already see from the constant value.
Whether you place a named constant into an interface
or an ordinary class
doesn’t make much difference. But in the past, constants were placed into interfaces with the intention of implementing the interface to basically import these constants, to be able to refer them by simple name. It’s not the placement of the constants into the interface, that makes it a bad coding style, but the actually meaningless type inheritance relationship that exists only to save typing in the source code. Since Java 5, you can use import static
to place constants into whatever type you wish and refer to them by simple name without creating a questionable inheritance relationship. So in most cases, you don’t want to use an interface
for that.
As already pointed out by others, there are other issues with your code. StringBuffer
has been superseded by StringBuilder
for most use cases, further, it doesn’t make much sense to mix String
concatenation with either StringBuffer
or StringBuilder
usage.
Use
countQueryBuf.append("Select count(e) From ").append(clz.getSimpleName()).append(" e");
consistently, if the existing countQueryBuf
is needed, i.e. if there are other fragments to append. If the query consists of these three fragments only, code like
String query = "Select count(e) From "+clz.getSimpleName()+" e";
is preferable. Before Java 5, it used a StringBuffer
under the hood, starting with Java 5, it will get compiled to use a StringBuilder
and starting with Java 9, it will get compiled to use the builtin String concat factory instead. In other words, this simple expression will automatically get the benefit of future improvements when being (re)compiled, whereas dealing with StringBuffer
or StringBuilder
manually requires maintaining and sometimes rewriting the code to catch up with such development.
If the fragments of a query represent values, you should always use a PreparedStatement
instead of assembling a new query string each time…
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With