不是文字的字符串对象,不需要 new 关键字



所以我知道还有其他类似的问题,比如这个和这个。但他们的答案似乎是,因为它们是文字的,并且是一些不可变的文字常量池的一部分,所以它们将保持可用。这对我来说是有道理的,但是为什么非文字也可以正常工作呢?在处理字符串时,我什么时候必须使用"new"关键字。在下面的示例中,我使用字符串来做一些事情,但一切正常,我从不使用"new"关键字(更正:我从不将其与 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?
   }
}

几点:"'老'字在这里被垃圾收集了吗?"您的编译器可能意识到它从未被使用过,只是完全跳过它。

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添加的对象才会匹配任何值(因为它是用==测试的),即使用户使用"*"作为addMatch中的字符串。

字符串在Java中是专门处理的。Java JVM使用类似于缓存的实现,称为字符串池。

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

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

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

在上面的代码中,当 s1 被分配"Hello"时,JVM 将看到它没有存储在池中,并将其创建/添加到池中。对于 s2,您再次引用"Hello"。JVM 将在池中看到它,并将 s2 分配给存储在池中的同一字符串。s3 只是分配给 s1 内存地址处引用的值,或相同的字符串"Hello"。最后,s1 被重新分配给另一个字符串,该字符串在池中尚不存在,因此被添加。此外,s1 不再指向"Hello",但它不会被垃圾回收,原因有两个。1:t 存储在字符串池中,2:s2 也指向相同的引用字符串。

对于字符串,切勿使用 new 关键字来创建文本字符串。如果这样做,则不会利用字符串池重用,并可能导致内存中存在同一字符串的多个实例,这是一种浪费。

最新更新