所以我知道还有其他类似问题,例如this one和this 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?
}
}
答案 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}}作为"*"
中的字符串。