Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the rationale for using static final Strings for SQL statement strings?

Tags:

java

constants

It seems many places incorporate as best practice the use of class constants for SQL strings.

So instead of:

String sql = "select * from users";
PreparedStatement stmt = conn.prepareStatement(sql);

It's preferred to do:

private static final String SQL_SELECT_USERS = "select * from users";

void someMethod() {
  ...
  PreparedStatement stmt = conn.prepareStatement(SQL_SELECT_USERS);
  ...
}

What are the advantages to the latter? It seems to me it's less readable.

Thanks.

like image 357
Steven Avatar asked Nov 22 '13 02:11

Steven


People also ask

Why do we use static final?

The static keyword means the value is the same for every instance of the class. The final keyword means once the variable is assigned a value it can never be changed. The combination of static final in Java is how to create a constant value.

What is static final String?

final indicates that the value of the variable won't change - in other words, a constant whose value can't be modified after it is declared. Use public final static String when you want to create a String that: belongs to the class ( static : no instance necessary to use it), that.

What is a static String?

Static string is the largest selling ionizing cord in the world because it produces 20 times the ionization of any other ion cord or tinsel product! Static String® provides clean performance with no oxidation, copper contamination or scratching.

Can we use static and final together?

Final method can't be inherited. Static methods can only access the static members of the class and can only be called by other static methods. Final class can't be inherited by any class. The static class object can't be created and it only contains static members only.


2 Answers

If it is a short text and it is used only in one place then there is no need to make it a field. In your case it could be this

PreparedStatement stmt = conn.prepareStatement("select * from users");

You can find a lot of this kind of coding style in JDK source, like this one

    if (is == null) {
        throw new IllegalArgumentException("InputStream cannot be null");
    }
like image 146
Evgeniy Dorofeev Avatar answered Sep 18 '22 22:09

Evgeniy Dorofeev


A final variable cannot be changed, by mistake or otherwise. Declaring the statement string as final makes sure to avoid this bug:

String s = "select * from users";

// many lines of code
s = "temp";
// do something with s
// many lines of code
PreparedStatement stmt = conn.prepareStatement(sql);

No matter how many lines of code you add after declaring s, if s is final the compiler will tell you when some code attempts to clobber it with a new value.

If you always do the prepared statement immediately after the variable, then simple proximity will help you avoid this error. Also, your actual example used a better name (sql rather than just s). But still, you never know who will edit your code after you write it.

Any time you can use a feature of the language to get the compiler to help you, you should do it. In this case, the final declaration lets the compiler protect you from someone clobbering your pre-defined string. Admittedly in this specific example the benefit seems pretty small, but in general constant things should be declared final and I don't see any reason to break that rule for this case.

As for declaring it private, that is just typical data hiding. If this string isn't part of the "interface" to this class, it should be private; by default, make everything private, and only make the interface stuff public.

EDIT: One more point worth considering. If you have a literal string that contains SQL, and you make some mistake when writing the SQL, the compiler cannot help you. "selct * from users" is a perfectly valid string; the Java compiler doesn't know it's an SQL error, so you find out at runtime.

You can make constants that are SQL fragments, and put them together with string concatenation. The great part about this is that if you misspell something, now you likely have a compiler error.

private final String SELECT_STAR_FROM = "select * from ";
private final String USERS_TABLE = "users";

// many lines of code
PreparedStatement stmt0 = conn.prepareStatement(SELECT_STAR_FROM + USERS_TABLE);

// this line would fail at run time
PreparedStatement stmt1 = conn.prepareStatement("selct * from users");

// this line fails at compile time and the compiler points you at it
PreparedStatement stmt0 = conn.prepareStatement(SELCT_STAR_FROM + USERS_TABLE);

When you do JNI programming you need to specify function signatures with cryptic codes. I made a bunch of constants and my JNI programs concatenate the constants together to build up the function signatures. This is C code, not Java, but it illustrates the same idea as the above.

#define JSIG_CONSTRUCTOR "<init>"

If I made a typo and wrote "<intt>" for a constructor, the C compiler couldn't help me; it would be a runtime error (JNI would fail to find the constructor). But if I use JSIG_CONSTRUCTOR in my code, if I make a typo, the compiler will tell me.

like image 28
steveha Avatar answered Sep 19 '22 22:09

steveha