Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to avoid creating multiple string objects in java?

Tags:

java

string

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?

like image 752
Gopi Lal Avatar asked Dec 10 '22 13:12

Gopi Lal


1 Answers

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…

like image 83
Holger Avatar answered Dec 25 '22 19:12

Holger