为啥字符串不需要新关键字
Posted
技术标签:
【中文标题】为啥字符串不需要新关键字【英文标题】:Why new keyword not needed for String为什么字符串不需要新关键字 【发布时间】:2012-01-30 14:36:02 【问题描述】:我是java新手。
在 java 中,String
是 class
。但是
我们不必使用new
关键字来创建String
类的对象,而new
用于为其他类创建对象。
我听说过类似 Integer
,Double
这样的 Wrapper 类。
但是String
不是 Wrapper,不是吗?
其实我使用的时候发生了什么
String message = "Hai";
?? 它与
有何不同String message = new String("Hai");
这里是message
引用变量还是别的什么??
是否有其他类不需要new
来创建对象??
【问题讨论】:
【参考方案1】:使用以下行,您不是在堆中创建新的 String
对象,而是重用字符串文字(如果已经可用):
String message = "Hai";
"Hai"
是字符串文字池中的字符串文字。由于字符串是不可变的,因此它们是可重用的,因此它们被 JVM 汇集在字符串文字池中。这是推荐的方式,因为您正在重复使用它。
但是,您实际上是在创建一个新对象(在堆中):
String message = new String("Hai");
new String("Hai")
是一个新的String
对象。在这种情况下,即使文字 "Hai"
已经在字符串文字池中,也会创建一个新对象。不建议这样做,因为您可能会以多个具有相同值的 String
对象结尾。
另请参阅此帖子:Questions about Java's String pool
还有其他不需要 new 来创建对象的类吗??
实际上,不使用关键字new
,您无法在Java中创建任何对象。
例如
Integer i = 1;
并不意味着Integer
对象是在不使用new
的情况下创建的。我们不需要明确地使用new
关键字。但实际上,如果缓存中不存在值为 1 的 Integer
对象(Integer
对象被 JVM 缓存),则将使用 new
关键字来创建它。
【讨论】:
我认为,Integer
是原始类型int
的包装类。但是字符串不是原始的,不是吗?【参考方案2】:
Java 语言规范允许将字符串表示为文字。您可以将其视为 String 的快捷方式初始化,它具有与通过 new
进行的常规初始化不同的重要副作用字符串字面量都是 interned,这意味着它们是 Java 运行时存储的常量值,可以在多个类之间共享。例如:
class MainClass (
public String test = "hello";
class OtherClass
public String another = "hello";
public OtherClass()
MainClass main = new MainClass();
System.out.println(main.test == another);
会打印出“true”,因为两个 String 实例实际上都指向同一个对象。如果您通过 new 关键字初始化字符串,则不会出现这种情况。
【讨论】:
+1。简洁明了。如果 OP 想要真正深入研究,我们应该提到 Java 语言规范可在 java.sun.com/docs/books/jls 免费获得。【参考方案3】:字符串和整数的创建是不同的。
String s = "Test";
这里 '=' 运算符被重载为字符串。 “一些”+“事物”中的“+”运算符也是如此。 在哪里,
Integer i = 2;
在 Java 5.0 之前,这是编译时错误;你不能将原语分配给它的包装器。但从 Java 5.0 开始,这被称为自动装箱,其中原语在需要时自动提升到其包装器。
String h1 = "hi";
将不同于
String h2 = new String("hi");
原因是 JVM 为所有字符串文字维护了一个字符串表。所以表中会有一个“hi”的条目,说它的地址是1000。
但是当你显式创建一个字符串对象时,会创建一个新对象,假设它的地址是 2000。现在新对象将指向字符串表中的条目,即 1000。
所以当你说
h1 == h2
比较
1000 == 2000
原来是假的
【讨论】:
=
运算符 NOT 重载。 Java 为字符串提供了一些语法糖,因此当您编写“Hello, World”时,您会获得对代表给定字符流的String
对象的引用。您正在那里隐式创建一个对象(如果需要),但这与 =
运算符没有任何关系。【参考方案4】:
在java中 "==" 比较左侧和右侧的内存位置(而不是该内存位置的值),因此在
new String("hai")==new String("hai")
它返回假。
在 "Hai"=="Hai" 的情况下,java 不会为相同的字符串文字分配单独的内存,因此这里的 "==" 返回 true。您始终可以使用 equals 方法来比较值。
【讨论】:
以上是关于为啥字符串不需要新关键字的主要内容,如果未能解决你的问题,请参考以下文章
字符串是 Java 中的对象,那么我们为啥不使用 'new' 来创建它们呢?
为啥关键字参数必须作为带有符号键的哈希传递,而不是 Ruby 中的字符串键?