为什么这个变量已经初始化为空字符串,却设置为空字符串?
Why is this variable set to empty string when it is already initialized to an empty string?
我从这个 developer guide on Content Providers.
的第 5 个片段中提取了以下代码片段
令人困惑的是,在第一个语句中 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
块执行之前添加了覆盖这个值的新代码,这个块的代码仍然会正确执行.如果没有此 "rudimentary" 分配,上述更改可能会导致很难跟踪的错误。
旁注:
这个特定的代码片段不是很好(是的,我知道它来自 Android 开发者网站...) - 如果您将 null
作为 selection
参数传递给 query()
,那么最好也将 null
作为 selectionArgs
参数传递。我会将此示例修改为类似这样的内容(将 selection
和 selectionArgs
都设置为 null):
// Gets a word from the UI
mSearchString = mSearchWord.getText().toString();
// Remember to insert code here to check for invalid or malicious input.
String[] mSelectionArgs = null;
// 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 = null;
} 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 = new String[] {mSearchString};
}
编辑:为什么上面的代码片段比原来的更好?
将 null 作为 selection
传递,将非 null 作为 selectionArgs
传递不是错误。该数组将传递给您正在寻址的特定 ContentProvider
,并且根本不应使用,因为 selection
不包含任何 ?
占位符。任何违反此假设的 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
其中包含的元素多于 selection
.
中 ?
占位符的数量
SQLiteProgram.java
中的这两个方法是 "blame" 此异常:
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;
}
现在,当我发现这种行为时,我认为来自 Android 开发者网站的代码示例不仅效率低下,而且完全是垃圾!
底线:如果您将 null
作为 selection
传递,那么也将 null
作为 selectionArgs
传递。如果 selection
不为空且包含 ?
占位符 - 确保 selectionArgs
数组的长度等于 selection
.[=42 中 ?
占位符的数量=]
我从这个 developer guide on Content Providers.
的第 5 个片段中提取了以下代码片段令人困惑的是,在第一个语句中 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
块执行之前添加了覆盖这个值的新代码,这个块的代码仍然会正确执行.如果没有此 "rudimentary" 分配,上述更改可能会导致很难跟踪的错误。
旁注:
这个特定的代码片段不是很好(是的,我知道它来自 Android 开发者网站...) - 如果您将 null
作为 selection
参数传递给 query()
,那么最好也将 null
作为 selectionArgs
参数传递。我会将此示例修改为类似这样的内容(将 selection
和 selectionArgs
都设置为 null):
// Gets a word from the UI
mSearchString = mSearchWord.getText().toString();
// Remember to insert code here to check for invalid or malicious input.
String[] mSelectionArgs = null;
// 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 = null;
} 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 = new String[] {mSearchString};
}
编辑:为什么上面的代码片段比原来的更好?
将 null 作为 selection
传递,将非 null 作为 selectionArgs
传递不是错误。该数组将传递给您正在寻址的特定 ContentProvider
,并且根本不应使用,因为 selection
不包含任何 ?
占位符。任何违反此假设的 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
其中包含的元素多于 selection
.
?
占位符的数量
SQLiteProgram.java
中的这两个方法是 "blame" 此异常:
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;
}
现在,当我发现这种行为时,我认为来自 Android 开发者网站的代码示例不仅效率低下,而且完全是垃圾!
底线:如果您将 null
作为 selection
传递,那么也将 null
作为 selectionArgs
传递。如果 selection
不为空且包含 ?
占位符 - 确保 selectionArgs
数组的长度等于 selection
.[=42 中 ?
占位符的数量=]