字符串a ==字符串b

时间:2016-06-08 06:40:19

标签: java string heap-memory

我正在尝试理解字符串池的工作原理以及字符串与另一个字符串相等的规则。

例如此代码段:

public static void main(String[] hi){
    String s1 = "lol";
    String s2 = "lol";
    String s3 = new String("lol");
    System.out.println( s1 == s2 );// true
    System.out.println( s2 == s3); // false
    s3.intern(); //line 1
    System.out.println( s1 == s3); // false
    testString(s1);

}

private static void testString(String s1){
    String s4 = "lol";
    System.out.println( s1 == s4); // true
}
  1. 在第1行:字符串被添加到字符串池中。由于它不等于s1,我假设字符串池中有重复。正确吗?

  2. 在游泳池中复制的规则是什么?换句话说,即使两个字符串具有相同的字符序列,someString == someString何时返回false?

  3. PS:无论如何,我在任何地方都使用string1.equals(string2)。我只是想深入了解潜在的机制。

5 个答案:

答案 0 :(得分:5)

s3.intern(); s3 = s3.intern();应为$data = [ 'CurrencyFrom' => 'USD', 'CurrencyTo' => 'EUR', 'RateDate' => '2014-06-05', 'Amount' => '1000' ]; // Using the added service SoapWrapper::service('currency', function ($service) use ($data) { var_dump($service->getFunctions()); var_dump($service->call('GetConversionAmount', [$data])->GetConversionAmountResult); }); 以获得正确的行为。

答案 1 :(得分:3)

  
      
  1. 在//第1行:字符串被添加到字符串池中。由于它不等于s1,我假设字符串池中有重复。正确吗?
  2.   

不,不正确。已经有一个字符串" lol"在字符串池中,所以它不会创建重复。但是,您没有对intern()调用的返回值执行任何操作,因此s3仍然引用池中不存在的String对象。

尝试s3 = s3.intern();而非s3.intern();

  
      
  1. 在池中复制的规则是什么?换句话说,即使两个字符串具有相同的char序列,someString == someString何时返回false?
  2.   

字符串池的重点是避免内存中重复的字符串,因此字符串池中不会有任何重复。

答案 2 :(得分:2)

将来自池(案例s1和s2)的字符串文字与在运行时创建的字符串文字或字符串与使用new创建的另一个字符串进行比较时,存在差异。

当完全相同的文字已存在时,保证字符串文字取自字符串池。字符串对象仍在内部使用池中的字符串,但作为对象具有不同的引用。

String#intern();返回对池中字符串的引用,这是内部使用的。

显示此行为的代码段:

String literalOne = "abc";
String literalTwo = "abc";
String stringOne = new String("abc");
String stringTwo = new String("abc");

System.out.println("literalOne == literalTwo ? " + (literalOne == literalTwo));
System.out.println("stringOne == stringTwo ? " + (stringOne == stringTwo));
System.out.println("Internally stringOne == stringTwo ? " + (stringOne.intern() == stringTwo.intern()));
System.out.println("Internally stringOne == literalOne ? " + (stringOne.intern() == literalOne));

输出:

literalOne == literalTwo ? true
stringOne == stringTwo ? false
Internally stringOne == stringTwo ? true
Internally stringOne == literalOne ? true

答案 3 :(得分:2)

basically we can create Sting by two ways基本上我们可以通过两种方式创建Sting

String str="some data" (not bound to any object like primitive data type)
String strTwo=new String("some String"); (here strTwo object contains value)

顾名思义,String Pool是存储在Java Heap内存中的字符串池。我们知道String是java中的特殊类,我们可以使用new运算符创建String对象,也可以用双引号提供值。

String Pool是可能的,因为String在Java中是不可变的,它是String interning概念的实现。字符串池也是Flyweight设计模式的一个例子。

字符串池有助于为Java Runtime节省大量空间,尽管创建String需要更多时间。

当我们使用双引号创建一个String时,它首先在String池中查找具有相同值的String,如果发现它只返回引用,否则它会在池中创建一个新String,然后返回引用。

但是使用new运算符,我们强制String类创建一个新的String对象,然后我们可以使用intern()方法将它放入池中或从具有相同值的池中引用其他String对象。

作为

public void method(){
String s1 = "Cat";
        String s2 = "Cat";
        String s3 = new String("Cat");

        System.out.println("s1 == s2 :"+(s1==s2));
        System.out.println("s1 == s3 :"+(s1==s3));
}

和输出

[![s1 == s2 :true
s1 == s3 :false

答案 4 :(得分:1)

==比较引用,所以当你尝试s1 == s3时,你正在检查这两个引用是否指向同一个不是真的对象,因为你已经创建了s3作为一个新对象(new String(&#34) ; lol"))。所以现在字符串池有两个不同的对象恰好具有相同的字符串值(" lol")并且在你的代码中你有s1,s2,s4指向一个和s3指向另一个。

为了比较已引用的每个对象的值,必须使用equals()方法。