所以我知道还有其他类似的问题,比如这个和这个。但他们的答案似乎是,因为它们是文字的,并且是一些不可变的文字常量池的一部分,所以它们将保持可用。这对我来说是有道理的,但是为什么非文字也可以正常工作呢?在处理字符串时,我什么时候必须使用"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
关键字来创建文本字符串。如果这样做,则不会利用字符串池重用,并可能导致内存中存在同一字符串的多个实例,这是一种浪费。