【问题标题】:java string equal [closed]java字符串等于[关闭]
【发布时间】:2012-09-22 06:01:36
【问题描述】:

可以通过两种方式初始化字符串:

String s="ABCD";

String s=new String("ABCD");

这两个是相同的还是不同的?? 我再次注意到

String s="ABCD";
String z="ABCD";
boolean b=s.equals(z);

结果为真,但

String s=new String("ABCD");
String z=new String("ABCD");
boolean b=s.equals(z);

结果为假。 谁能解释一下为什么会这样??

【问题讨论】:

  • 我否认你的前提:两个 sn-ps 都会将值 true 放入变量中。也许你的意思是s == z

标签: java string


【解决方案1】:

你所有的例子都必须是true,甚至the second one

为什么? String 类有一个重写的 equals 方法,该方法检查两个字符串是否相同 - 逐个字符。 另一方面,运算符 == 检查两个字符串引用是否指向同一个对象。

例如:

String a = new String("asd"); //new object, will add to pool though
String b = new String("asd"); //new object
String c = "asd"; //will use the pool
boolean b1 = (a == b); //false, different objects (same contents though)
boolean b2 = (a.equals(b)); //true, same contents
boolean b3 = (a == c); //false, different objects
boolean b3 = (a.equals(c)); //true, same contents

还有一点需要注意的是 Java 池化字符串。如果您在代码中的某处使用字符串文字,JVM 将汇集该值,当您再次使用它时,在代码中的其他地方,JVM 将检测到它并将您的引用指向它。字符串是不可变的,所以这是非常安全的。

我要强调的最后一件事是构造String b = new String("asd");。在这种情况下,将创建一个新的 String 对象(由于运算符 new)。即使字符串池中已经存在“asd”,字符串b 也会指向一个单独的内存位置,并带有一个新对象。

如果池中不存在“asd”,那么b 不仅会指向非池化区域,还会将“asd”添加到池中,以防万一(以备将来参考)。

【讨论】:

    【解决方案2】:

    对不起,我想。

    String s=new String("ABCD");
    String z=new String("ABCD");
    boolean b=s.equals(z);
    

    应该是返回true,请再次检查..!!

    您的问题在不同方面是正确的(使用 == 运算符) 在 Java 中创建 String 对象有两种方法:

    • 使用 new 运算符。例如,

      String str = new String("Hello");

    • 使用字符串文字或常量表达式)。例如,

      String str="Hello"; (string literal) or
      String str="Hel" + "lo"; (string constant expression).

    字符串字面量
    与所有对象分配一样,字符串分配在时间和内存方面都被证明是昂贵的。 JVM 在实例化字符串文字时会执行一些技巧以提高性能并减少内存开销。为了减少在 JVM 中创建的 String 对象的数量,String 类保留了一个字符串池。每次您的代码创建字符串文字时,JVM 首先检查字符串文字池。如果该字符串已存在于池中,则返回对池实例的引用。如果池中不存在字符串,则实例化一个新的 String 对象,然后将其放入池中。 Java 可以进行这种优化,因为字符串是不可变的,并且可以共享而不必担心数据损坏。

    从你的问题来看

    String s="ABCD";
    String z="ABCD";
    boolean b=s==z; 
    

    我应该返回true,因为两个对象具有相同的引用。

    但万一

    String s=new String("ABCD");
    String z=new String("ABCD");
    boolean b = s==z;
    

    它将返回false,因为两个对象不同

    【讨论】:

      【解决方案3】:

      建议大家阅读和分析String.class的源码,尤其是equals和intern方法,另外还要研究一下java的内存结构。

      字符串#equals

      /**
       * Compares this string to the specified object.  The result is {@code
       * true} if and only if the argument is not {@code null} and is a {@code
       * String} object that represents the same sequence of characters as this
       * object.
       *
       * @param  anObject
       *         The object to compare this {@code String} against
       *
       * @return  {@code true} if the given object represents a {@code String}
       *          equivalent to this string, {@code false} otherwise
       *
       * @see  #compareTo(String)
       * @see  #equalsIgnoreCase(String)
       */
      public boolean equals(Object anObject) {
      if (this == anObject) {
          return true;
      }
      if (anObject instanceof String) {
          String anotherString = (String)anObject;
          int n = count;
          if (n == anotherString.count) {
          char v1[] = value;
          char v2[] = anotherString.value;
          int i = offset;
          int j = anotherString.offset;
          while (n-- != 0) {
              if (v1[i++] != v2[j++])
              return false;
          }
          return true;
          }
      }
      return false;
      }
      

      字符串#intern

      /**
       * Returns a canonical representation for the string object.
       * <p>
       * A pool of strings, initially empty, is maintained privately by the
       * class <code>String</code>.
       * <p>
       * When the intern method is invoked, if the pool already contains a
       * string equal to this <code>String</code> object as determined by
       * the {@link #equals(Object)} method, then the string from the pool is
       * returned. Otherwise, this <code>String</code> object is added to the
       * pool and a reference to this <code>String</code> object is returned.
       * <p>
       * It follows that for any two strings <code>s</code> and <code>t</code>,
       * <code>s.intern()&nbsp;==&nbsp;t.intern()</code> is <code>true</code>
       * if and only if <code>s.equals(t)</code> is <code>true</code>.
       * <p>
       * All literal strings and string-valued constant expressions are
       * interned. String literals are defined in &sect;3.10.5 of the
       * <a href="http://java.sun.com/docs/books/jls/html/">Java Language
       * Specification</a>
       *
       * @return  a string that has the same contents as this string, but is
       *          guaranteed to be from a pool of unique strings.
       */
      public native String intern();
      

      内存结构

      http://www.yourkit.com/docs/kb/sizes.jsp

      【讨论】:

        【解决方案4】:

        当我们调用以下语句时

        String s="ABCD";
        String z="ABCD";
        

        然后它将在字符串池中检查,如果池中已经存在,则将地址引用到变量。
        但是当我们调用new关键字然后明确表示要创建新内存。

        【讨论】:

          【解决方案5】:

          对此我不确定,但我在第二个例子中猜测

          String s=new String("ABCD");
          String z=new String("ABCD");
          

          它被声明为一个对象,所以当你尝试检查相等性时肯定会给你false(对象不能等于对象)

          【讨论】:

          • 他们确实在实例化一个new String,当String 以这种方式声明时,它分配的新内存不会进入全局String 池。所有Java Objects 都有equals 方法,默认情况下确实只进行引用检查(this == obj)。但是,String 和许多其他对象、Override 对这种行为进行了更深入的检查。海报弄错了;这些对象会说它们是相等的。
          【解决方案6】:
          String s="ABCD";
          String z="ABCD";
          

          在内存池中引用相同的字符串。 但是

          String s=new String("ABCD");
          String z=new String("ABCD");
          

          为字符串生成单独的内存空间。 所以输出是这样的。 这也回答了您的第一个问题。

          【讨论】:

          • 我不认为这对于发布的代码是正确的。 .equals() 检查相等性,而不是身份。池化在这里不起作用。
          • 内存池的想法是准确的。这对equals 错误有任何影响的事实并非如此。 "ABCD".equals(new String("ABCD")) 将是 true
          • 对不起,我的意思是 == 而不是 .equals()。
          猜你喜欢
          • 2012-11-01
          • 2016-12-27
          • 1970-01-01
          • 2014-07-29
          • 1970-01-01
          • 2022-11-16
          • 1970-01-01
          • 2020-12-29
          • 1970-01-01
          相关资源
          最近更新 更多