如何使用“”初始化字符串?


154

如果String和其他字符串一样是一个类,如何使用双引号将其初始化?


25
字符串是VIP类。" "已经是一个字符串!
johnchen902

2
没有特别的意思。我的意思是非常重要。即java.lang.String对Java语言进行特殊处理。
johnchen902

16
谁说这个字符串是“一个像其他类一样的类”?与其他课程不同,这是一个非常特殊的课程。由于您的假设是错误的,因此该问题并非真正可以回答。
埃里克·利珀特

5
仅仅因为假设是错误的,并不意味着问题就不能回答。正确的答案已经有197票。
Koray Tugay 2014年

Answers:


293

Java字符串很特殊

Java的设计者决定保留面向对象语言中的原始类型,而不是将所有内容都变成对象,以提高语言的性能。原语存储在调用堆栈中,这需要较少的存储空间并且更便宜。另一方面,对象存储在程序堆中,这需要复杂的内存管理和更多的存储空间。

出于性能原因,Java的String设计为介于基本体和类之间。

例如

String s1 = "Hello";              // String literal
String s2 = "Hello";              // String literal
String s3 = s1;                   // same reference
String s4 = new String("Hello");  // String object
String s5 = new String("Hello");  // String object

在此处输入图片说明

注意: 字符串文字存储在公共池中。这有助于共享具有相同内容的字符串的存储,以节省存储空间。String通过new运算符分配的对象存储在中heap,并且没有共享相同内容的存储。


72
请注意,“公共池” 通常是堆的一部分。
Joachim Sauer

3
@JoachimSauer是的..没有什么好处:)在便笺中添加了此内容。感谢您记住。
Suresh Atta

2
这样写String s1 =“ Hello”更快吗?比字符串s2 = new String(“ Hello”);?
user2097804 2013年

28
我会在您的示例中添加s1 == s2 == s3但s4!= s5
Alfredo Osorio

8
@AndrewJanke在最近的热点jvm(7)上,字符串池不在perm gen中,并且从Java 8开始,不再有perm gen ...
assylias 2013年

50

Java将String视为特殊类,您可以通过两种方式进行初始化

  1. 直接分配文字

    String a = "adsasdf";
  2. 与其他使用new关键字的对象

    String a = new String("adsasdf");

当您想与==符号比较时,需要特别注意:

String a = "asdf";
String b = "asdf";
System.out.println(a == b);  // True
System.out.println(a.equals(b)); // True

String a = new String("asdf");
String b = new String("asdf");
System.out.println(a == b);  // False
System.out.println(a.equals(b)); // True

这是因为在第一种情况下,对象a和b被保存在称为的对象中,literal pool并且它们都引用相同的对象,因此它们在两种方式上都是相等的。

但是在第二种情况下,a和b引用了不同的对象,就像我们初始化任何其他对象时一样。因此与==运算符比较时它们是不相等的,而值相等。


18

字符串在JLS中得到特殊对待:它是存在文字的两种非基本类型之一(另一个是Class*

JLS

字符串文字是对类String [...]的实例的引用。

*好吧,还有“空类型”及其“空文字” null,但是大多数人并不认为“空类型”是适当的类型。


1
我也不知道Java中“空类型”是正确的类型。其非常有用的信息,您应该增加字体大小。
Grijesh Chauhan

1
@GrijeshChauhan:好吧,“空类型”只是一个漂亮的措辞,可以将任何内容null分配给任何引用类型变量。否则,这不是一个有趣的类型。
Joachim Sauer

15

这是Java语言的功能。源代码中的字符串文字被给予特殊待遇。

语言规范,在这里,简单地说,一个字符串文字是String类型


5

双引号内的文本创建一个文字String对象。

String myString = "Some text";

上面的代码String使用双引号创建一个对象。


4

字符串经常在编程语言中使用。由于java是面向对象的,因此字符串是一个对象。为了避免麻烦的新String(“ someString”); 每当您需要一个字符串对象时,Java语句就可以使用字符串文字来创建一个字符串对象。

但是您应该记住字符串相等性。这里是一个简短的JUnit测试,以演示我的意思。

    @Test
    public void stringTest() {
       // a string literal and a string object created 
       // with the same literal are equal
       assertEquals("string", new String("string"));

       // two string literals are the same string object
       assertSame("string", "string"); 

       // a string literal is not the same object instance 
       // as a string object created with the same string literal
       assertFalse("string" == new String("string"));

       // java's String.intern() method gives you the same
       // string object reference for all strings that are equal.
       assertSame("string", new String("string").intern());
    }

如果您只能使用初始化字符串new String(String src),那么您甚至无法为构造函数提供字符串文字。您将必须初始化一个char [],然后使用String(char [] src)构造器来构造该字符串,或者您必须从文件中读取该字符串。
AJMansfield

那是不对的。字符串文字只是源文件中由双引号引起来的字符序列。Java使用此文字自动创建字符串的实例。因此,文字和String对象是相等的,但它们是不相同的。Java也可以通过这种方式实现,即必须使用新的String(“”); 实例化一个String对象,但这只会使我们的生活更加艰难。因此,当您编写新的String(“ a string”)时,java为文字“ a string”创建一个String对象,并将此字符串对象传递给new String的构造方法。
勒内链接

2

提一下。字符串文字是对String类实例的引用,您可以编写如下代码:

 “ abc” .getBytes();

 “ a:b:c” .split(“:”);

 “爱” .codePointAt(0);

2

-字符串是一类的Java。您是对的,因此我们始终可以使用new关键字进行初始化。

-但是当我们做类似的事情时:

String s = "";

上面的语句被编译器标记为特殊的String对象,然后JVM在加载期间(加载在初始化之前完成)看到了所谓的字符串文字,它存储在字符串文字池中

-因此可以使用new()""方法创建字符串,但是后者提供了一个字符串文字,即使没有对该字符串对象的引用,该方法也将保留在堆中,因为它具有来自字符串文字池的引用。


2

Java为我们执行了两步过程。

String str = "hello";

相当于

char data[] = {'h', 'e', 'l' , 'l', 'o'};
String str = new String(data);

就像[.NET] [1]一样。

String(Char[]) constructor

确实

String(char[] value)

添加参考:


2
您所描述的过程是不是Java的实际作用:正如其他人已经指出的那样,"hello"是一个字符串文字,将被编译器放入常量池中,看JLS§3.10.5JVMS§5.1
siegi 2013年

1

Java.lang.String不只是一堂课。它是核心语言的组成部分。编译器为此提供了语法糖。例如,""就像是的缩写new String("")。编写时"",编译器会将相同的字符串优化到同一实例以节省空间。"a" + 5 == "a5" ==> true

编译器具有很多功能的语法糖,包括不必在对象版本及其本机类型之间进行装箱/拆箱,没有父级表示对象,默认构造函数,...


5
""不是的缩写new String("")。如果使用"",则要做的第一件事是在JVM的字符串池中查找匹配项,如果为true,它将返回该字符串。通过使用new String(""),即使字符串本身已经存在于字符串池中,您也将始终创建一个新的字符串(因为它不会存储在字符串池中)。
g00glen00b

我更新了答案。人们是否会利用它们的优势,例如使用与Lisp符号类型等效的字符串常量?
Sylwester
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.