字符串对象不是文字不需要新关键字?

时间:2016-03-13 01:46:29

标签: java string new-operator

所以我知道还有其他类似问题,例如this onethis other one。但他们的回答似乎是因为它们是文字的,是一些不可变的文字常量池的一部分,所以它们仍然可用。这种方式对我来说很有意义,但是为什么非文字也能正常工作呢?我何时必须使用" new"处理字符串时的关键字。在下面的例子中,我使用字符串来做一些事情,但一切正常,我从不使用" new" keyword(更正:我从不将它与String类型对象一起使用)。

import java.util.*;

class teststrings{

   public static void main(String[] args){
      Scanner in = new Scanner(System.in);
      String nonew;
      String nonew2;
      String literally= "old";
      literally= "new"; //does the word "old" get garbage collected here?
      nonew = in.nextLine(); //this does not use the new keyword, but it works, why?
      System.out.println("nonew:"+nonew);
      System.out.println("literally:"+literally);
      nonew2 = in.nextLine();
      System.out.println("nonew:"+nonew); //the data is still preserved here
      System.out.println("nonew2:"+nonew2);
      //I didn't use the new keyword at all, but everything worked
      //So, when do I need to use it?
   }

}

2 个答案:

答案 0 :(得分:2)

字符串特别用Java处理。 Java JVM使用称为字符串池的缓存实现。

与其他对象不同,当您创建这样的文字字符串时:String mystring = "Hello"; Java将首先检查String" Hello"已存在于String池中。如果没有,它将添加它以进行缓存并再次引用时重用。

因此,当你将变量分配给" Hello"第一次,它被添加到池中:

String s1 = "Hello";
String s2 = "Hello";
String s3 = s1;
s1 = "SomethingElse"

在上面的代码中,当s1被分配时#34;你好" JVM将看到它未存储在池中并创建/添加到池中。 对于s2,您再次引用" Hello"。 JVM将在池中看到它并将s2分配给存储在池中的相同String。 s3简单地分配给在s1的存储器地址处引用的值,或者相​​同的字符串" Hello"。最后,然后将s1重新分配给另一个String,该String在池中尚未存在,因此被添加。此外,s1不再指向" Hello",但由于两个原因,它不会被垃圾收集。 1:t存储在String池中,2:s2也指向相同的引用字符串。

使用字符串,您不应该使用new关键字来创建文字字符串。如果这样做,您没有利用String池重用,并且可能导致内存中存在同一String的多个实例,这是一种浪费。

答案 1 :(得分:2)

有几点: "单词" old"在这里收集垃圾?" 有可能你的编译器意识到它从未使用过,只是完全跳过它。

Scanner::nextLine返回String,方法返回的值用于分配。

至于new使用String ......好吧,很少会是最好的。我曾经见过的唯一一次是内部常数。例如

public class MatchChecker {
    private static final String ANY_VALUE = new String("*");

    private final Map<Object, String> map = new HashMap<Object, String>();

    public void addMatch(Object object, String string) {
        map.put(object, string);
    }

    public void addAnyValueMatch(Object object) {
        map.put(object, ANY_VALUE);
    }

    public boolean matches(Object object, String string) {
        if (!map.contains(object)) {
            return false;
        }
        if (map.get(object) == ANY_VALUE || map.get(object).equals(string)) {
            return true;
        }
        return false;
    }
}

这意味着通过addAnyValueMatch添加的对象将匹配任何值(因为它已经过==测试),即使用户使用了{{ 1}}作为"*"中的字符串。