【问题标题】:getText() from EditText: is it possible to get a 'null'?来自 EditText 的 getText():是否有可能获得“null”?
【发布时间】:2015-07-28 19:21:42
【问题描述】:

我正在编写一个我正在编写的 Android 应用程序,并试图使我的代码完全符合 Android Studio 的 lint 建议。

我有以下代码发出警告(省略了一些代码):

final EditText input = (EditText)view.findViewById(R.id.edit_text);
Button button        = (Button)view.findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        String value = input.getText().toString();
        if (value == null || value.length() == 0) {

Android Studio 给我一个警告:

条件 'value == null' 始终为 false。

当我允许 Android Studio 为我“修复”问题时,它建议:

将 'value == null' 简化为 false

然后代码变成:

if (value.length() == 0) {

我查看了 Android 源代码 (http://www.grepcode.com),我很困惑。 EditText 的文档说“EditText 是对 TextView 的薄薄的一层,它将自身配置为可编辑。”那么getText()方法定义如下:

@Override
public Editable getText() {
    return (Editable) super.getText();
}

当我去getText() 寻找TextView(“超级”)时,我看到了这个:

public CharSequence getText() {
    return mText;
}

TextViewsetText() 方法似乎不允许 null 值,因为这是该方法的开始:

private void setText(CharSequence text, BufferType type, boolean notifyBefore, int oldlen) {
    if (text == null) {
        text = "";
    }

默认构造函数也是这样开始的:

public TextView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    mText = "";

因此,getText() 似乎无法返回 null 值,但 this answer 上的 cmets 表明它是。 this question 的答案似乎也表明这是可能的。

我想练习防御性编码,这就是我从一开始就按照我的方式构建代码的原因,但我不想做null 检查不可能是null 的东西.那么,在这种情况下,最佳做法是什么?

【问题讨论】:

  • 你会检查像 value.equals("") 并引用这个stackoverflow.com/a/3321548/4478125
  • 我认为 lint 检查告诉您的信息与您从中读取的内容略有不同。对于这个 if 语句,EditText.getText() 是否可以返回 null 实际上并不重要。因为如果它返回 null,那么在到达 if 语句之前,.toString() 将导致 NullPointerException。因此,如果 if 语句完全可以访问,则 value 不能为 null。因此,不需要value == null 检查。
  • @Barend 那么这更有意义。我认为 lint 检查不够聪明,无法分析我所做的所有层。那么,问题就变成了我的String value = input.getText().toString(); 行是否容易受到 NPE 的攻击。
  • 如果你将input.getText().toString()简化为null.toString(),你可以很容易地看到它会是NPE。我不确定getText() 是否可以返回null,即使标准EditText 不能,那么EditText 的某些未知子类也可以,因此防御方法是将代码重写为完全null-安全的方式。
  • 根据您通过挖掘源代码提供的详细信息,getText 不会返回 null。您在问题中发布的两个 SO 链接并没有真正说明 getText() 返回 null。

标签: android android-edittext


【解决方案1】:

我认为 lint 检查告诉您的情况略有不同:

String value = input.getText().toString();
if (value == null || value.length() == 0) {

条件 'value == null' 始终为 false。

在这个 if 语句中,EditText.getText() 是否可以返回 null 实际上并不重要。因为如果它返回 null,那么在到达 if 语句之前,.toString() 将导致 NullPointerException。因此,如果 if 语句完全可达,则 value 不能为 null。

你可以翻遍Android源码,也许你会发现EditText不可能返回null。如果是这种情况,那么如果您知道标准的 EditText 在您的应用程序中,则可以忽略 lint 警告。

但是,在更一般的情况下,没有什么能阻止我将其粘贴在视图层次结构中:

public class EvilEditText extends EditText {
    // Constructors

    @Override
    public Editable getText() {
        return null;
    }
}

所以最安全的选择是将代码重写为完全为空安全:

Editable e = input.getText();
String value = (e == null ? null : e.toString());
if (TextUtils.isEmpty(value)) {  //hat tip to Deepak Goyal's answer. Could also use isEmpty(e)

【讨论】:

  • 很好的答案。谢谢! value.isEmpty()TextUtils.isEmpty(value) 有什么区别?
  • 我认为EditableString 都没有isEmpty() 方法,所以第一个不会编译?
  • 根据 developer.android.com,确实如此。描述如下:“如果此字符串的长度为 0,则返回 true。”不确定这与TextUtils 有何不同。仅供参考。 ;-)
  • 嗯。我在 1.2 左右开始做 Java。我从未意识到 Java 字符串在 1.6 版本中有一个 isEmpty() 方法。今天我学到了…… :)
  • 嘘!很高兴在你帮助我之后我能帮助你!
【解决方案2】:

你可以使用 TextUtils.isEmpty(value);

final EditText input = (EditText)view.findViewById(R.id.edit_text);
Button button        = (Button)view.findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        String value = input.getText().toString();
        if (TextUtils.isEmpty(value)) {
          // value is empty
        }else{
          // have value
        }

【讨论】:

  • 不过,这并不能真正回答我的问题。看起来你对代码input.getText().toString 的 NPE 并不关心,对吧?那么,getText() 总是返回一个非空值,或者 toString() 可以采用空值,我不认为这是真的。你明白我在问什么吗?
  • 如果 input.getText() 曾经返回 null,这仍然是 NPE。
  • 不,它不会返回空值,它可以返回一个空字符串。
【解决方案3】:

您可能会收到此警告,因为您的 value 不包含从 EditText#getText()(返回 CharSequence)返回的内容,而是从 CharSequence#toString()(返回 String)返回的内容.

toString() 对非空 CharSequence 的调用应该不可能返回空值,这就是为什么 lint 警告您空值检查是不必要的。你应该对EditText#getText() 的返回做空检查。

换句话说,如果您的input.getText() 为空,那么它已经失败而无需调用toString(),因此您的空检查将永远无法到达。

【讨论】:

    【解决方案4】:

    表达式中的值

    String value = input.getText().toString();
    

    不会是null。 因为如果输入是null,它将为方法调用input.getText() 生成一个NPE。因此下一条语句将不会执行。如果你处理这个NPE 类似

                String value = null;
                if (input!=null) {
                    value = input.getText().toString();
                }
                if (value == null || value.length() == 0){
    
                }
    

    那么你就不会得到那个指示了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-11-04
      • 1970-01-01
      • 2019-02-12
      • 2020-01-13
      • 2013-05-24
      • 2014-01-24
      • 2017-01-18
      • 1970-01-01
      相关资源
      最近更新 更多