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交易的方式。