在Java中我们通常会这样做:
Class myObject = new Class();
因为new
关键字返回一个地址。
但为什么我们这样做?:
String myString = "Hello";
好像String
是原始的?
我向老师问了这个问题,他回答说这是因为引号中的内容相当于一个地址,但他不确定。你确定吗?
“Hello”是否存储在String类的实例变量中?
答案 0 :(得分:16)
......好像
String
是原始的?
作为Jon points out in a comment,“具有文字形式”!=“是原始类型。” :-)字符串在Java中具有文字形式,因为the spec defines one for them。 String
仍然是对象类型。
某些语言还有其他对象类型也有文字形式(例如,JavaScript具有正则表达式,数组和非数组对象的文字形式 [字符串的字面形式实际上定义了它所谓的字面形式字符串原语而不是字符串对象 - JavaScript具有字符串的原始和对象版本)。我认为字符串是Java中唯一的字符串(null
除外,它是“无对象”的文字),尽管当然有数组初始值设定项,它们是类似的但与文字不完全相同。
答案 1 :(得分:13)
您可以使用文字表达式这一事实并不意味着表达式会导致基本类型!这只是你强烈的误解。
你看:
Integer[] numbers = { 1, 2, 3 };
也是一个文字(好吧,“几乎”;因为你只能将它用于这种类型的数组init语句);但它不是原始类型!
要问你问题中的为什么部分:机会是 - 只是为了方便。当Java被创建时,它意味着比那些时代的C和C ++“更好”。并猜测:处理字符串是非常烦人的,并且在这些语言中容易出错。
从这个意义上讲:引入字符串文字可以被视为unique selling point,以区分Java与竞争对手!
答案 2 :(得分:8)
其他答案非常好。一些具体要点:
我向老师问了这个问题,他回答说这是因为引号中的内容相当于一个地址,但他不确定。你能证实吗?
是。他是对的。正如其他人所指出的那样,字符串文字,即包含在一对“s”中的有效Unicode字符序列被Java语言规范识别。当Java编译器(javac
程序)遇到这样的文字时(例如{Java}源文件中的"Hello"
,它将字面上并将其放在编译的class file内的特定部分。此部分称为运行时常量池。然后创建一个名为ldc
的特定指令,它放在类文件中,其中存储了用于初始化的编译代码。例如,{{的主体1}}以下Java源代码中的方法:
main
编译为:
public class StringAsPrimitive {
public static void main(String[] args) {
String s = "Hello";
}
}
(这里没有魔法。只需使用 0: ldc #2 // String Hello
2: astore_1
3: return
程序编译代码并使用javac
程序查看类文件。您甚至可以使用hex查看器查看.class文件的内容你会看到字符串javap
字面意思)。
当您要求Hello
程序运行此类文件时,JVM会对此代码进行解释。
记录java
JVM的ldc
指令here。这就是JVM在解释#2
时所做的事情,"Hello"
是对文本字符串static
存储在计算机内存(RAM)中的实际位置的引用:
否则,如果运行时常量池条目是对a的引用 class的实例String表示字符串文字(第5.1节),然后是a 对该实例的引用value被推送到操作数堆栈上。
所以,你的老师所说的是正确的,尽管我们并没有这么说。在Java中,有两种类型:基元和引用。因此,更合适的做法是String字面值是一个引用(而不是地址)。
“Hello”是否存储在String类的实例变量中?
没有。初始化为String文字的String变量可以是任何内容,StringAsPrimitive.class
或类变量,实例变量或局部变量(上面的代码)。它存储在类文件中:Enemy
以后它可用于特定内存位置的JVM。当JVM 加载类时会发生这种情况。
答案 3 :(得分:1)
所有文字都不是原始文字。
来自JLS 3.10
3.10。文字
文字是基元值的源代码表示 type(§4.2),String类型(§4.3.3)或null类型(§4.1)。
文字:
IntegerLiteral
FloatingPointLiteral
BooleanLiteral
字符文字
串文字
NullLiteral
所以String
文字不是基元而是对象。
JLS引用它,你也可以推导它,因为String
实例有方法而原语不能有方法。
该语言很可能引入了字符串文字(String myString = "Hello"
),以简化String的声明,这种类型与int
或boolean
等基本类型相同。
想象一下String
连接,例如:
new String("hello ") + new String (nameInput) + new String (" and welcome!");
这显然更加冗长,可读性更低,因此更容易出错:
"hello " + nameInput +" and welcome!";