字符串是 Java 中的对象,那么为什么我们不使用“ new”来创建它们呢?

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

Object obj = new Object();

字符串是对象,但我们不使用 new来创建它们:

String str = "Hello World";

这是为什么? 我可以用 new做一个字符串吗?

76454 次浏览

这是一个快捷方式,原本不是这样的,但 Java 改变了它。

This 常见问题 talks about it briefly. The Java Specification guide talks about it also. But I can't find it online.

创建一个新的 String

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

通常的表示法 s = "new String";或多或少是一种方便的快捷方式——除了那些非常罕见的情况,really需要符合等式条件的字符串,否则应该根据性能原因使用 s = "new String";

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

剪辑

作为对评论的回应: 这是 没有的意图是一个建议,但只是对提问者的论点,即字符串的 我们不使用’新’关键字的直接回应,这根本不是真的。希望这个编辑(包括上面的)能够澄清一点。顺便说一下——对于上面关于 SO 的问题,有几个更好的答案。

字符串需要进行一些优化(因为没有更好的表达方式)。请注意,字符串也有运算符重载(用于 + 操作符)-不同于其他对象。所以这是一个非常特殊的情况。

语法糖

String s = new String("ABC");

syntax is still available.

除了已经说过的,字符串 字面意思[即类似于 "abcd"但不像 new String("abcd")的字符串]在 Java 中被实习——这意味着每次引用“ abcd”时,都会得到一个对单个 String实例的引用,而不是每次都有一个新的实例。所以你会得到:

String a = "abcd";
String b = "abcd";


a == b; //True

but if you had

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

那就有可能

a == b; // False

(如果有人需要提醒,总是使用 .equals()来比较字符串; 使用 ==测试物理相等性)。

实际字符串文字是很好的,因为它们经常被使用不止一次:

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

如果我们没有实习字符串,“下一个迭代”将需要被实例化10次,而现在它将只被实例化一次。

你仍然可以使用 new String("string"),但是如果没有字符串文字,创建新的字符串会更加困难... 你将不得不使用字符数组或字节: ——字符串文字有一个额外的属性: 从任何类点到同一个字符串实例的所有相同的字符串文字(它们被实现)。

字符串是 Java 中的“特殊”对象。Java 设计人员明智地决定,字符串的使用是如此频繁,以至于他们需要自己的语法和缓存策略。当你声明一个字符串时:

String myString = "something";

MyString 是对 String 对象的引用,其值为“ something”:

String myOtherString = "something";

Java 足够聪明,能够计算出 myString 和 myOtherString 是相同的,并将它们作为相同的对象存储在一个全局 String 表中。它依赖于这样一个事实,即您不能修改 String 来执行此操作。这样可以降低所需的内存量,并且可以更快地进行比较。

如果,相反,你写

String myOtherString = new String("something");

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

在 Java 中,String 是一种特殊情况,有许多只适用于 String 的规则。双引号使编译器创建一个 String 对象。因为 String 对象是不可变的,所以这允许编译器内部存储多个字符串,并构建一个更大的字符串池。两个相同的 String 常量总是有相同的对象引用。如果您不希望出现这种情况,那么可以使用 new 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

When the classloader loads a class, all String constants are added to the String pool.

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

The literal pool contains any Strings that were created without using the keyword new.

这里有一个区别: 没有新引用的 String 存储在 String 文本池中,而带有 new 的 String 表示它们在堆内存中。

与其他对象一样,带有 new 的字符串在内存中的其他位置。

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").

希望这能消除一些疑虑。 :)

Because String is an immutable class in java.

那么为什么它是不可变的呢? 因为 String 是不可变的,所以它可以在多个线程之间共享,我们不需要在外部同步 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");

产出:

没错

我创建了两个单独的对象,它们都有一个字段(ref)‘ Name’。所以即使在这种情况下“ Jan Peter”也是共享的,如果我理解 java 的处理方式的话。.

We usually use String literals to avoid creating unnecessary objects. If we use new operator to create String object , then it will create new object everytime .

Example:

String s1=“Hello“;
String s2=“Hello“;
String s3= new String(“Hello“);
String s4= new String(“Hello“);

对于内存中的上述代码:

enter image description here

StringPool 是用 java 中的 Hashmap 实现的。如果我们总是创建一个新的关键字,它不在字符串池中搜索,并创建一个新的内存,这可能需要以后,如果我们有一个内存密集型操作运行,如果我们创建所有的字符串与新的关键字,将影响我们的应用程序的性能。因此,建议不要使用新关键字来创建字符串,因为只有这样它才会进入字符串池,而后者又是一个 Hashmap (节省内存,想象一下如果我们有很多用新关键字创建的字符串) ,它将被存储在这里,如果字符串已经存在,它的引用(通常会驻留在堆栈内存中)将被返回到新创建的字符串。 这样做是为了提高性能。