string是Java中的对象,那么为什么我们不使用“新”来创build它们呢?

我们通常使用new关键字创build对象,如:

 Object obj = new Object(); 

string是对象,但我们不使用new来创build它们:

 String str = "Hello World"; 

为什么是这样? 我可以用new的string吗?

除了已经说过的之外,Java中的string字面量 (即像"abcd"string,但不像new String("abcd") ]是实现的 – 这意味着每次引用“abcd”时,到一个单一的String实例,而不是一个新的每一次。 所以你会有:

 String a = "abcd"; String b = "abcd"; a == b; //True 

但如果你有

 String a = new String("abcd"); String b = new String("abcd"); 

那么有可能

 a == b; // False 

(如果有人需要提醒,总是使用.equals()来比较string; ==testing物理相等)。

实习string文字是好的,因为它们经常被使用多次。 例如,考虑(人为的)代码:

 for (int i = 0; i < 10; i++) { System.out.println("Next iteration"); } 

如果我们没有实习Strings,那么“Next iteration”需要实例化10次,而现在只会实例化一次。

string是Java中的“特殊”对象。 Javadevise人员明智地决定,string被频繁使用,以至于他们需要自己的语法以及caching策略。 当你声明一个string时说:

 String myString = "something"; 

myString是一个值为“something”的String对象的引用。 如果您稍后声明:

 String myOtherString = "something"; 

Java足够聪明地解决myString和myOtherString是相同的,并将它们作为相同的对象存储在一个全局的String表中。 它依赖于你不能修改string来做到这一点。 这降低了所需的内存量,可以加快比较速度。

如果,而是你写

 String myOtherString = new String("something"); 

Java将为您创build一个全新的对象,与myString对象不同。

 String a = "abc"; // 1 Object: "abc" added to pool String b = "abc"; // 0 Object: because it is already in the pool String c = new String("abc"); // 1 Object String d = new String("def"); // 1 Object + "def" is added to the Pool String e = d.intern(); // (e==d) is "false" because e refers to the String in pool String f = e.intern(); // (f==e) is "true" //Total Objects: 4 ("abc", c, d, "def"). 

希望这个清除一些疑虑。 🙂

这是一个捷径。 它本来不是这样,但Java改变了它。

这个常见问题解答会简要地介绍 Java规范指南也谈到它。 但我无法在网上find它。

string受到一些优化(为了更好的短语)。 请注意,string也有运算符重载(+运算符) – 不像其他对象。 所以这是非常特殊的情况。

在Java中,string是一种特殊情况,许多规则只适用于string。 双引号使编译器创build一个String对象。 由于String对象是不可变的,这允许编译器实习多个string,并build立一个更大的string池。 两个相同的string常量将始终具有相同的对象引用。 如果你不想这样做,那么你可以使用新的String(“”),并在运行时创build一个String对象。 intern()方法以前是很常见的,可以根据string查找表来检查dynamic创build的string。 一旦实现了string,对象引用将指向规范的String实例。

  String a = "foo"; String b = "foo"; System.out.println(a == b); // true String c = new String(a); System.out.println(a == c); // false c = c.intern(); System.out.println(a == c); // true 

当类加载器加载一个类时,所有的string常量被添加到string池中。

语法糖。 该

 String s = new String("ABC"); 

语法仍然可用。

您仍然可以使用new String("string") ,但是创build没有string文字的新string会更困难…您将不得不使用字符数组或字节:-)string文字具有一个附加属性:所有相同的string文字从任何类的点到相同的string实例(他们被interned)。

几乎不需要新buildstring,因为文本(引号中的字符)已经是加载主机类时创build的string对象。 在文字和文字上调用方法是完全合法的,主要区别在于文字提供的便利。 如果我们必须创build一个char数组,然后用char来填充它,然后再做一个新的String(char数组),那将会是一大痛苦和浪费。

随意创build一个新的string

 String s = new String("I'm a new String"); 

通常的符号s = "new String"; 或多或less是一个方便的捷径 – 除了那些非常罕见的情况,应该用于性能方面的原因,在这些情况下,您确实需要符合公式的string

 (string1.equals(string2)) && !(string1 == string2) 

编辑

在回应评论时:这不是为了提供build议,而仅仅是对提问者论文的直接回应,即我们没有在string中使用“新”关键字 ,这根本不是真的。 希望这个编辑(包括上面)澄清这一点。 顺便说一句,关于SO的上述问题有几个好的和更好的答案。

文字池包含不使用关键字new而创build的任何string。

有一个区别:没有新的引用的string被存储在string文字池中,新的string表示它们在堆内存中。

新的string就像任何其他对象一样在内存中的其他地方。

因为String是java中的一个不可变类。

现在为什么它是不可改变的? 由于string是不可变的,所以它可以在多个线程之间共享,我们不需要从外部同步string操作。 As String也用于类加载机制。 所以如果String是可变的,那么java.io.writer可能已经被改为abc.xyz.mywriter

 TString obj1 = new TString("Jan Peter"); TString obj2 = new TString("Jan Peter"); if (obj1.Name == obj2.Name) System.out.println("True"); else System.out.println("False"); 

输出:

真正

我创build了两个单独的对象,都有一个字段(参考)“名称”。 所以即使在这种情况下,“Jan Peter”也是共享的,如果我理解java交易的方式。