Java 当这个变量已经初始化为空字符串时,为什么要将它设置为空字符串?

Java 当这个变量已经初始化为空字符串时,为什么要将它设置为空字符串?,java,android,android-contentprovider,android-contentresolver,Java,Android,Android Contentprovider,Android Contentresolver,我从第五段代码中获取了以下代码片段 混淆之处在于第一条语句String[]mSelectionArgs={”“},mSelectionArgs[0]设置为“” 然后,如果mSearchString为空(TextUtils.isEmpty(mSearchString)),则再次分配mSelectionArgs[0] 所以问题是,当它已经初始化为空字符串时,为什么他们要将其设置为空字符串? /* * This defines a one-element String array to contai

我从第五段代码中获取了以下代码片段

混淆之处在于第一条语句
String[]mSelectionArgs={”“}
mSelectionArgs[0]
设置为
“”

然后,如果
mSearchString
为空(
TextUtils.isEmpty(mSearchString)
),则再次分配
mSelectionArgs[0]

所以问题是,当它已经初始化为空字符串时,为什么他们要将其设置为空字符串?

/*
 * This defines a one-element String array to contain the selection argument.
 */
String[] mSelectionArgs = {""};

// Gets a word from the UI
mSearchString = mSearchWord.getText().toString();

// Remember to insert code here to check for invalid or malicious input.

// If the word is the empty string, gets everything
if (TextUtils.isEmpty(mSearchString)) {
    // Setting the selection clause to null will return all words
    mSelectionClause = null;
    mSelectionArgs[0] = "";

} else {
    // Constructs a selection clause that matches the word that the user entered.
    mSelectionClause = UserDictionary.Words.WORD + " = ?";

    // Moves the user's input string to the selection arguments.
    mSelectionArgs[0] = mSearchString;

}
...

我喜欢它,因为它是对称的

if something
    var = x
else
    var = y

在每种情况下,
var
是什么很清楚,无需返回并访问其初始值。

除了额外的清晰性和代码可读性,如另一个答案中所述,这种编码风格使得代码更容易维护,更不容易出错

这样,如果更改了
mSelectionArgs
的初始值,或者在执行
if else
块之前添加了覆盖此值的新代码,则此块的代码仍将正确执行。如果没有这个“基本的”分配,如上所述的更改可能会导致很难跟踪的bug

作为旁注:

这个特定的代码片段不是很好(是的,我知道它来自Android开发者网站…)-如果您将
null
作为
selection
参数传递给
query()
,那么最好也将
null
作为
selectionArgs
参数传递。我会将此示例修改为类似的内容(将
selection
selectionArgs
设置为null):

编辑:为什么上面的代码片段比原来的好?

/*
 * This defines a one-element String array to contain the selection argument.
 */
String[] mSelectionArgs = {""};

// Gets a word from the UI
mSearchString = mSearchWord.getText().toString();

// Remember to insert code here to check for invalid or malicious input.

// If the word is the empty string, gets everything
if (TextUtils.isEmpty(mSearchString)) {
    // Setting the selection clause to null will return all words
    mSelectionClause = null;
    mSelectionArgs[0] = "";

} else {
    // Constructs a selection clause that matches the word that the user entered.
    mSelectionClause = UserDictionary.Words.WORD + " = ?";

    // Moves the user's input string to the selection arguments.
    mSelectionArgs[0] = mSearchString;

}
...
将null作为
selection
传递和非null作为
selectionArgs
传递不是错误。此数组将传递给您正在寻址的特定
内容提供程序
,并且不应使用,因为
选择
不包含任何
占位符。任何违反此假设的
ContentProvider
都是错误的。虽然不是一个错误,但看起来很奇怪——为什么要传递一个应该忽略的对象?这还有性能成本(如果
ContentProvider
在不同的进程中运行,则性能成本会更高),这与所传递对象的大小成正比

编辑2:为什么上面的代码片段比原来的好得多? 原来我上面说的可能是误导。我以艰难的方式找到了答案:

 Caused by: java.lang.IllegalArgumentException: Cannot bind argument at index 3 because the index is out of range.  The statement has 1 parameters.
        at android.database.sqlite.SQLiteProgram.bind(SQLiteProgram.java:212)
        at android.database.sqlite.SQLiteProgram.bindString(SQLiteProgram.java:166)
        at android.database.sqlite.SQLiteProgram.bindAllArgsAsStrings(SQLiteProgram.java:200)
        at android.database.sqlite.SQLiteDirectCursorDriver.query(SQLiteDirectCursorDriver.java:47)
        at android.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:1314)
        at android.database.sqlite.SQLiteDatabase.queryWithFactory(SQLiteDatabase.java:1161)
        at android.database.sqlite.SQLiteDatabase.query(SQLiteDatabase.java:1032)
        at android.database.sqlite.SQLiteDatabase.query(SQLiteDatabase.java:1200)
引发上述异常是因为我试图传递
selectionArgs
,其中包含的元素数超过
选择中的
占位符数

SQLiteProgram.java
中的这两个方法是导致此异常的“罪魁祸首”:

public void bindAllArgsAsStrings(String[] bindArgs) {
    if (bindArgs != null) {
        for (int i = bindArgs.length; i != 0; i--) {
            bindString(i, bindArgs[i - 1]);
        }
    }
}

private void bind(int index, Object value) {
    if (index < 1 || index > mNumParameters) {
        throw new IllegalArgumentException("Cannot bind argument at index "
                + index + " because the index is out of range.  "
                + "The statement has " + mNumParameters + " parameters.");
    }
    mBindArgs[index - 1] = value;
}
public void bindallargsassstrings(String[]bindArgs){
if(bindArgs!=null){
对于(int i=bindArgs.length;i!=0;i--){
bindString(i,bindArgs[i-1]);
}
}
}
私有void绑定(int索引,对象值){
如果(索引<1 | |索引>多个参数){
抛出新的IllegalArgumentException(“无法在索引处绑定参数”
+索引+“因为索引超出范围。”
+“该语句有”+mNumParameters+“parameters.”);
}
mBindArgs[索引-1]=值;
}
现在,当我发现这种行为时,我认为Android开发者网站上的代码示例不仅效率低下,而且完全是一堆废话


底线:如果您将
null
作为
selection
传递,那么也将
null
作为
selectionArgs
传递。如果
selection
不为空且包含
占位符-请确保
selectionArgs
数组的长度等于
selection
中的
占位符的数量,我想这只是为了更清楚。例如,他们正在强调一点,在本例中,如果搜索值为空,mSelectionArgs[0]仍然为“”。但是,谁知道呢。这可能只是一种风格。“如果将null作为选择参数传递给query(),那么最好也将null作为selectionArgs参数传递。”-但为什么?如果
selectionArgs
是空字符串(如原始代码段中的字符串),会发生什么情况?(对不起,我是新手)@Solace,我在答案中添加了解释。在您的代码中,您可以将
mSelectionArgs
保留为未初始化状态。@bayou.io,是的,但我总是尝试在代码中明确说明。即使Lint抱怨不必要的赋值:)@Solace,我也发现了您引用的代码片段不好的其他原因。答案中的“编辑2”部分对此进行了描述。以防万一你感兴趣。。。