【问题标题】:On my custom ListView item, why is (string.length() <= 0) always true, while (string == "") is always false?在我的自定义 ListView 项目上,为什么 (string.length() <= 0) 始终为真,而 (string == "") 始终为假?
【发布时间】:2011-06-23 20:38:14
【问题描述】:

我创建了一个自定义 ListView 适配器/项目。该项目包含一个 CheckedTextView 和一个 TextView。

在适配器的 getView() 方法中,创建了自定义项,并在返回之前调用了它的 setTask(Task) 方法。

setTask(Task) 方法从作为参数传入的 Task 对象中获取 2 个字符串和一个布尔值。 (我确实认识到它的地址实际上是被传递的。)

如果该字符串包含文本,则将其中一个字符串分配给自定义项的 TextView 的文本属性。否则,TextView 的可见属性设置为“已消失”。

为了做出决定,我检查了字符串的长度是否小于或等于 0...它会产生意外的行为 - 它总是评估为真。

如果我更改它以检查字符串是否等于“”,它总是返回 false。

这让我相信我正在检查的字符串为空。为什么会这样?

protected void onFinishInflate() {
    super.onFinishInflate();
    checkbox = (CheckedTextView)findViewById(android.R.id.text1);   
    description = (TextView)findViewById(R.id.description);
}

public void setTask(Task t) {
    task = t;
    checkbox.setText(t.getName());
    checkbox.setChecked(t.isComplete());
    if (t.getDescription().length() <= 0)
        description.setVisibility(GONE);
    else
        description.setText(t.getDescription());
}

这是适配器中的 getView() 方法:

public View getView(int position, View convertView, ViewGroup parent) {

    TaskListItem tli;
    if (convertView == null)
        tli = (TaskListItem)View.inflate(context, R.layout.task_list_item, null);
    else
        tli = (TaskListItem)convertView;

    tli.setTask(currentTasks.get(position));
    return tli; 
}

【问题讨论】:

  • 你的问题是典型的课堂案例。
  • @Blessed Geek 原谅我 - 我是 Stack Overflow 的新手。这是否意味着它还不够先进,无法问?我在这附近做了什么不受欢迎的事情吗?我现在没有上 Java 课程,也从来没有上过,但我是初学者。
  • 不,不,一点也不。说它是一个典型的课堂案例,意味着你对这个案例的透彻理解是非常重要的。因为对本案例的理解为您理解 Java 编程语言(以及 C#)奠定了基础。

标签: java android


【解决方案1】:
myString == ""

检查字符串对象的引用而不是内容。你应该使用:

"".equals(myString)

它检查字符串的内容,而不是引用。你可以使用:

myString.equals("")

但如果 myString 为 null,则可能会出现 NullPointerException。

【讨论】:

    【解决方案2】:

    在 Java 中,您不能使用 == 将一个字符串的内容与另一个字符串进行比较。 == 运算符总是比较变量的引用或内存地址。在其他语言中 == 可以用来比较对象的内容。在Java中它不能。使用 .equals() 或 .equalsIgnoreCase()。

    【讨论】:

    • 您不能使用 == 来比较字符串的内容,但有时它给出的结果与 .equals() 相同。这经常会绊倒新的 Java 程序员。如果你写String a = "hi"; String b="hi";,那么a==b 给出的结果与a.equals(b) 相同。使用文字设置的测试代码与 == 配合使用效果很好...然后在生产中失败如果将 b 更改为 b = new String({'h','i'}); 然后 == 将为 false,尽管 a.equals(b) 仍然为 true;
    【解决方案3】:

    您正在使用 == 比较字符串,这对于对象来说总是一个坏主意。您的空字符串 "" 指向与 t.getDescription() 不同的 String 对象,尽管值可能相同。有时使用字符串 == 会起作用,因为 String 类维护了一个字符串池,并且它将用于字符串文字和常量。然而,字符串如何工作的演示比文字更好。

    public class StringTest
    {
      public static void main(String[] args)
      {
        String s0="";  // literal
        System.out.println("Length of s0 = " + s0.length());
        System.out.println("Does s0 point to same object as empty string? " 
          + (s0==""));  // since both are literals the same object is used for both
        System.out.println("Does s0 equal an empty string? "
          + s0.equals("")); // comparing values
        System.out.println("Is s0 empty? " + s0.isEmpty());
        System.out.println("");
    
        StringBuilder sb = new StringBuilder("");
        String s1 = sb.toString(); // don't use a literal for s1
        System.out.println("Length of s1 = " + s1.length());
        System.out.println("Does s1 point to same object as empty string? " 
          + (s1==""));  // s1 is a different object
        System.out.println("Does s1 equal an empty string? " + s1.equals("")); 
        System.out.println("Is s1 empty? " + s1.isEmpty());
        System.out.println("");
    
        // Do this like s1 but with a twist
        sb = new StringBuilder("");
        String s2 = sb.toString(); // again not a literal
        System.out.println("Does s2 point to same object as empty string? " 
          + (s2=="")); 
        System.out.println("Length of s2 = " + s0.length());
        s2 = s2.intern(); // returns the object from the pool that equals() s2
        System.out.println("Now does s2 point to same object as empty string? " 
          + (s2==""));  // s2 now has the reference to the empty string in the pool
        System.out.println("Does s2 equal an empty string? " + s2.equals(""));
        System.out.println("Is s2 empty? " + s2.isEmpty());
      }
    }
    

    我希望这会有所帮助。

    【讨论】:

    • 真的很有帮助。回答了我的问题,还给了我一些关于 String 类的非常受欢迎的见解。
    【解决方案4】:

    此外,您应该在使用 .length() 之前检查 t.getDescription()。

    if(t.getDescription()!=null){
    (t.getDescription().length()>0)?description.setText(t.getDescription()):description.setVisibility(GONE);}
    else { description.setVisibility(GONE);}
    

    为避免使用字符串,请确保 t->description 始终以 null 而不是空字符串开头。这可以在类构造函数中完成。

    【讨论】:

      【解决方案5】:

      事实证明,除了直接比较 String 对象外,我还发现了另一个严重的错误。 (如果我错了,请纠正我。)

      由于 ListView 中的视图有时会被回收,因此“tli”引用有时会引用可见性属性已设置为“已消失”的视图。即使字符串不为空,该属性也永远不会变回“可见”。我只需要在这两种情况下明确设置该属性。这是固定的代码:

      public void setTask(Task t) {
          task = t;
      
          checkbox.setText(task.getName());
          checkbox.setChecked(task.isComplete());
          if (task.getDescription().equals("")) 
              description.setVisibility(GONE);
          else
              description.setVisibility(VISIBLE);
              description.setText(task.getDescription());
      }
      

      无论我是否从 task.getDescription() 检查字符串的内容或长度,它现在都会起作用。

      【讨论】:

      • 你应该问一个新问题。没有人会在这里看到这个 Android 问题。我对 Android 开发知之甚少,但知道您的 Java 问题的答案。
      • @sjbotha 我实际上将这个问题标记为 Android 和 Java。这是你的意思吗?应该在Android中问吗?
      • 是的,但是,当您提出新问题时,您的问题会显示在主页和其他区域。此问题的文字只会被对您的原始问题感兴趣的人阅读。
      • @sjbotha 我明白你的意思。那么我应该问一个与其他 Android 特定错误相关的新问题,然后自己立即回答吗?这是否被认为是适当的礼仪,或者看起来我是在为声誉而钓鱼?感谢你的帮助。非常感谢。
      • 是的,这是正确的,或者您可以只询问您的解决方案是否是您问题中的正确解决方案并获得反馈。
      【解决方案6】:

      == 运算符检查双方是否引用同一个对象。具有相同内容的两个字符串不(通常)引用同一个对象,见下文。

      String s = "";
      String t = "";
      if (s == t){
        //false! s and t refer to different objects
      }
      if (s.equals(t) && t.equals(s)){ //these two are equivalent
        //true!
      }
      s = t;
      if (s == t){
        //now they refer to the same object, so true!
      }
      

      【讨论】:

      • 我不会称之为“对象平等”。这就是 .equals() 是什么。 == 运算符比较变量引用。
      • 你真的试过上面的代码吗? s == t 实际上会在您将它们分配为同一个变量之前返回 true。
      • @Kal 是正确的。因为您将它们都设置为字符串文字,所以它们指向字符串内部池中的同一个对象。请参阅我的答案,了解我如何构造一个非文字空字符串。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-02-14
      • 1970-01-01
      • 2018-01-06
      • 2012-08-20
      • 2016-04-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多