为SQL语句字符串使用静态最终字符串的基本原理是什么?

Ste*_*ven 5 java constants

似乎很多地方都将SQL字符串的类常量用作最佳实践.

所以代替:

String sql = "select * from users";
PreparedStatement stmt = conn.prepareStatement(sql);
Run Code Online (Sandbox Code Playgroud)

最好这样做:

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

void someMethod() {
  ...
  PreparedStatement stmt = conn.prepareStatement(SQL_SELECT_USERS);
  ...
}
Run Code Online (Sandbox Code Playgroud)

后者有什么好处?在我看来,它的可读性较差.

谢谢.

Evg*_*eev 5

如果它是一个短文本并且只在一个地方使用,那么就不需要将它作为一个字段.在你的情况下,它可能是这样

PreparedStatement stmt = conn.prepareStatement("select * from users");
Run Code Online (Sandbox Code Playgroud)

你可以在JDK源代码中找到很多这种编码风格,就像这一样

    if (is == null) {
        throw new IllegalArgumentException("InputStream cannot be null");
    }
Run Code Online (Sandbox Code Playgroud)


ste*_*eha 3

变量final不能因错误或其他原因而被更改。将语句字符串声明为可final确保避免此错误:

String s = "select * from users";

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

无论您在声明后添加多少行代码s, if sisfinal编译器都会在某些代码尝试用新值破坏它时告诉您。

如果您总是在变量之后立即执行准备好的语句,那么简单的邻近将帮助您避免此错误。另外,您的实际示例使用了更好的名称(sql而不仅仅是s)。但是,您仍然不知道在您编写代码后谁会编辑您的代码。

任何时候只要你可以使用该语言的某个功能来让编译器来帮助你,你就应该这样做。在这种情况下,final声明可以让编译器保护您免受他人破坏您的预定义字符串的影响。诚然,在这个特定的例子中,好处似乎很小,但一般来说,应该声明恒定的东西final,并且我认为没有任何理由打破这种情况的规则。

至于声明它private,那只是典型的数据隐藏。如果这个字符串不是这个类的“接口”的一部分,它应该是私有的;默认情况下,将所有内容设为私有,仅将接口内容设为公开。

编辑:还有一点值得考虑。如果您有一个包含 SQL 的文字字符串,并且在编写 SQL 时犯了一些错误,则编译器无法帮助您。 "selct * from users"是一个完全有效的字符串;Java 编译器不知道这是一个 SQL 错误,因此您可以在运行时发现。

您可以将常量设置为 SQL 片段,并通过字符串连接将它们放在一起。最重要的是,如果您拼写错误某些内容,现在可能会出现编译器错误。

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);
Run Code Online (Sandbox Code Playgroud)

当您进行 JNI 编程时,您需要使用神秘代码指定函数签名。我创建了一堆常量,我的 JNI 程序将这些常量连接在一起以构建函数签名。这是 C 代码,不是 Java,但它说明了与上面相同的想法。

#define JSIG_CONSTRUCTOR "<init>"
Run Code Online (Sandbox Code Playgroud)

如果我写错了"<intt>"一个构造函数,C 编译器就帮不了我;这将是一个运行时错误(JNI 将无法找到构造函数)。但是如果我JSIG_CONSTRUCTOR在代码中使用,如果我犯了一个拼写错误,编译器会告诉我。