简体   繁体   English

在我的自定义ListView项上,为什么(string.length()<= 0)始终为true,而(string ==“””)始终为false?

[英]On my custom ListView item, why is (string.length() <= 0) always true, while (string == “”) is always false?

I've created a custom ListView adapter/item. 我创建了一个自定义ListView适配器/项目。 The item contains a CheckedTextView and a TextView. 该项目包含一个CheckedTextView和一个TextView。

In the adapter's getView() method, the custom item is created and its setTask(Task) method is called right before it's returned. 在适配器的getView()方法中,将创建自定义项,并在返回之前立即调用其setTask(Task)方法。

The setTask(Task) method gets 2 Strings and a boolean from the Task object passed in as a parameter. setTask(Task)方法从作为参数传入的Task对象中获取2个字符串和一个布尔值。 (I do recognize that its address is actually what gets passed.) (我确实知道它的地址实际上就是通过的地址。)

One of the Strings is assigned to the custom item's TextView's text property IF that String contains text. 如果字符串包含文本,则将其中一个字符串分配给自定义项目的TextView的文本属性。 Otherwise, the TextView's visible property is set to "gone." 否则,TextView的visible属性将设置为“ gone”。

To make that determination, I check to see if the String's length is less than or equal to 0... it produces unexpected behavior - it ALWAYS evaluates true. 为了确定这一点,我检查一下String的长度是否小于或等于0 ...它会产生意外的行为-总是评估为true。

If I change it to check if the String is equal to "", it always returns false. 如果我更改它以检查String是否等于“”,则它始终返回false。

This leads me to believe that the String I'm checking is null. 这使我相信我正在检查的字符串为空。 Why would that be? 为什么会这样呢?

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());
}

And here's the getView() method in the adapter: 这是适配器中的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; 
}
myString == ""

checks the reference of the string object rather than the content. 检查字符串对象的引用而不是内容。 You should use: 您应该使用:

"".equals(myString)

which checks the content of the string, rather then the reference. 它检查字符串的内容,而不是引用。 You could use: 您可以使用:

myString.equals("")

but that has a chance of a NullPointerException if myString is null. 但是如果myString为null,则可能会出现NullPointerException。

In Java you can't use == to compare the contents of a String with another String. 在Java中,您不能使用==将一个字符串的内容与另一个字符串进行比较。 The == operator always compares the reference or memory address of the variables. ==运算符总是比较变量的引用或内存地址。 In other languages == can be made to compare the contents of objects. 在其他语言中,可以使==来比较对象的内容。 In Java it cannot. 在Java中不能。 Use .equals() or .equalsIgnoreCase(). 使用.equals()或.equalsIgnoreCase()。

You're comparing strings using == which is always a bad idea with Objects. 您正在使用==比较字符串,这对于Objects总是一个坏主意。 Your empty string "" points to a different String object than t.getDescription(), though the values may be the same. 您的空字符串“”指向与t.getDescription()不同的String对象,尽管值可能相同。 With Strings sometimes == will work because the String class maintains a pool of Strings and will it use for string literals and constants. 对于Strings,有时==将起作用,因为String类维护一个Strings池,并将其用于字符串文字和常量。 A demonstration of how String works is better than words, however. 但是,关于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());
  }
}

I hope this helps. 我希望这有帮助。

Additionally, you should check t.getDescription() before using .length() on it. 此外,在使用.length()之前,应检查t.getDescription()。

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

To avoid playing with String, insure that t->description always start as null instead of empty String. 为了避免使用String,请确保t-> description始终以null开头,而不是空的String。 This can be done in Class constructor. 这可以在Class构造函数中完成。

As it turns out, other than comparing String object directly, there is another serious bug which JUST occurred to me. 事实证明,除了直接比较String对象之外,还有一个严重的错误是我刚想到的。 (Please correct me if I'm wrong.) (如果我错了,请纠正我。)

Because views in a ListView are sometimes recycled, the "tli" reference sometimes references a view who's visibility property is already set to "gone." 由于有时会回收ListView中的视图,因此“ tli”引用有时会引用其可见性属性已设置为“ gone”的视图。 That property never gets changed back to "visible" even if the String ISN'T empty. 即使字符串ISN'n为空,该属性也永远不会变回“可见”。 I just had to explicitly set that property under both conditions. 我只需要在两种情况下都明确设置该属性即可。 Here's the fixed code: 这是固定代码:

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());
}

It now functions whether or not I check the content or the length of the String from task.getDescription(). 现在,无论我是否从task.getDescription()检查字符串的内容或字符串的长度,它都起作用。

The == operator checks if both sides refer to the same object. ==运算符检查双方是否都引用同一对象。 Two strings that have the same contents don't (usually) refer to the same object, see below. 具有相同内容的两个字符串通常不会引用同一对象,请参见下文。

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!
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM