...String str=new String("a") 这个语句创建了几个对象。
发布网友
发布时间:2024-10-23 13:58
我来回答
共4个回答
热心网友
时间:2024-11-13 22:50
答案:两个,一个是字符串字面量"xyz"所对应的、驻留(intern)在一个全局共享的字符串常量池中的实例,另一个是通过new String(String)创建并初始化的、内容与"xyz"相同的实例
这是根据Java语言规范相关规定可以给出的合理答案。考虑到Java语言规范中明确指出了:
The Java Language Specification, Third Edition 写道
The Java programming language is normally compiled to the bytecoded instruction set and binary format defined in The Java Virtual Machine Specification, Second Edition (Addison-Wesley, 1999).
也就是规定了Java语言一般是编译为Java虚拟机规范所定义的Class文件,但并没有规定“一定”(must),留有不使用JVM来实现Java语言的余地。
考虑上Java虚拟机规范,确实在这段代码里涉及的常量种类为CONSTANT_String_info的字符串常量也只有"xyz"一个。CONSTANT_String_info是用来表示Java语言中String类型的常量表达式的值(包括字符串字面量)用的常量种类,只在这个层面上考虑的话,这个解答也没问题。
所以这种解答可以认为是合理的。
值得注意的是问题中“在运行时”既包括类加载阶段,也包括这个代码片段自身执行的时候。下文会再讨论这个细节与楼主原本给出的问题的关系。
碰到这种问题首先应该想到去查阅相关的规范,这里具体是Java语言规范与Java虚拟机规范,以及一些相关API的JavaDoc。很多人喜欢把“按道理说”当作口头禅,规范就是用来定义各种“道理”的——“为什么XXX是YYY的意思?”“因为规范里是这样定义的!”——无敌了。
在Java虚拟机规范中相关的定义有下面一些:
The Java Virtual Machine Specification, Second Edition 写道
2.3 Literals
A literal is the source code representation of a value of a primitive type (§2.4.1), the String type (§2.4.8), or the null type (§2.4). String literals and, more generally, strings that are the values of constant expressions are "interned" so as to share unique instances, using the method String.intern.
The null type has one value, the null reference, denoted by the literal null. The boolean type has two values, denoted by the literals true and false.
2.4.8 The Class String
Instances of class String represent sequences of Unicode characters (§2.1). A String object has a constant, unchanging value. String literals (§2.3) are references to instances of class String.
2.17.6 Creation of New Class Instances
A new class instance is explicitly created when one of the following situations occurs:
Evaluation of a class instance creation expression creates a new instance of the class whose name appears in the expression.
Invocation of the newInstance method of class Class creates a new instance of the class represented by the Class object for which the method was invoked.
A new class instance may be implicitly created in the following situations:
Loading of a class or interface that contains a String literal may create a new String object (§2.4.8) to represent that literal. This may not occur if the a String object has already been created to represent a previous occurrence of that literal, or if the String.intern method has been invoked on a String object representing the same string as the literal.
Execution of a string concatenation operator that is not part of a constant expression sometimes creates a new String object to represent the result. String concatenation operators may also create temporary wrapper objects for a value of a primitive type (§2.4.1).
Each of these situations identifies a particular constructor to be called with specified arguments (possibly none) as part of the class instance creation process.
5.1 The Runtime Constant Pool
...
● A string literal (§2.3) is derived from a CONSTANT_String_info structure (§4.4.3) in the binary representation of a class or interface. The CONSTANT_String_info structure gives the sequence of Unicode characters constituting the string literal.
● The Java programming language requires that identical string literals (that is, literals that contain the same sequence of characters) must refer to the same instance of class String. In addition, if the method String.intern is called on any string, the result is a reference to the same class instance that would be returned if that string appeared as a literal. Thus,
Java代码
("a" + "b" + "c").intern() == "abc"
must have the value true.
● To derive a string literal, the Java virtual machine examines the sequence of characters given by the CONSTANT_String_info structure.
○ If the method String.intern has previously been called on an instance of class String containing a sequence of Unicode characters identical to that given by the CONSTANT_String_info structure, then the result of string literal derivation is a reference to that same instance of class String.
○ Otherwise, a new instance of class String is created containing the sequence of Unicode characters given by the CONSTANT_String_info structure; that class instance is the result of string literal derivation. Finally, the intern method of the new String instance is invoked.
...
The remaining structures in the constant_pool table of the binary representation of a class or interface, the CONSTANT_NameAndType_info (§4.4.6) and CONSTANT_Utf8_info (§4.4.7) structures are only used indirectly when deriving symbolic references to classes, interfaces, methods, and fields, and when deriving string literals.
把Sun的JDK看作参考实现(reference implementation, RI),其中String.intern()的JavaDoc为:
JavaDoc 写道
public String intern()
Returns a canonical representation for the string object.
A pool of strings, initially empty, is maintained privately by the class String.
When the intern method is invoked, if the pool already contains a string equal to this String object as determined by the equals(Object) method, then the string from the pool is returned. Otherwise, this String object is added to the pool and a reference to this String object is returned.
It follows that for any two strings s and t, s.intern() == t.intern() is true if and only if s.equals(t) is true.
All literal strings and string-valued constant expressions are interned. String literals are defined in §3.10.5 of the Java Language Specification
Returns:
a string that has the same contents as this string, but is guaranteed to be from a pool of unique strings.
===============================================================
再换一个问题来问:
引用
问题:
Java代码
String s = new String("xyz");
涉及用户声明的几个String类型的变量?
答案也很简单:
引用
答案:一个,就是String s。
把问题换成下面这个版本,答案也一样:
引用
问题:
Java代码
String s = null;
涉及用户声明的几个String类型的变量?
Java里变量就是变量,引用类型的变量只是对某个对象实例或者null的引用,不是实例本身。声明变量的个数跟创建实例的个数没有必然关系,像是说:
Java代码
String s1 = "a";
String s2 = s1.concat("");
String s3 = null;
new String(s1);
这段代码会涉及3个String类型的变量,
1、s1,指向下面String实例的1
2、s2,指向与s1相同
3、s3,值为null,不指向任何实例
以及3个String实例,
1、"a"字面量对应的驻留的字符串常量的String实例
2、""字面量对应的驻留的字符串常量的String实例
(String.concat()是个有趣的方法,当发现传入的参数是空字符串时会返回this,所以这里不会额外创建新的String实例)
3、通过new String(String)创建的新String实例;没有任何变量指向它。
===============================================================
回到楼主开头引用的问题与“标准答案”
引用
问题:
Java代码
String s = new String("xyz");
创建了几个String Object?
答案:两个(一个是“xyz”,一个是指向“xyz”的引用对象s)
用归谬法论证。假定问题问的是“在执行这段代码片段时创建了几个String实例”。如果“标准答案”是正确的,那么下面的代码片段在执行时就应该创建4个String实例了:
Java代码
String s1 = new String("xyz");
String s2 = new String("xyz");
马上就会有人跳出来说上下两个"xyz"字面量都是引用了同一个String对象,所以不应该是创建了4个对象。
那么应该是多少个?
运行时的类加载过程与实际执行某个代码片段,两者必须分开讨论才有那么点意义。
为了执行问题中的代码片段,其所在的类必然要先被加载,而且同一个类最多只会被加载一次(要注意对JVM来说“同一个类”并不是类的全限定名相同就足够了,而是<类全限定名, 定义类加载器>一对都相同才行)。
根据上文引用的规范的内容,符合规范的JVM实现应该在类加载的过程中创建并驻留一个String实例作为常量来对应"xyz"字面量;具体是在类加载的resolve阶段进行的。这个常量是全局共享的,只在先前尚未有内容相同的字符串驻留过的前提下才需要创建新的String实例。
热心网友
时间:2024-11-13 22:54
String str=new String("a")
创建两个对象是正确的,当执行该语句时,系统会在栈中创建一个对象,在堆中创建一个字符串常量池,然后在里面寻找是否有“a“,如果有则通过栈中的对象引用此值,如果没有系统会再创建一个”a“来引用~~
所以说是创建了两个对象~~
希望对你有所帮助~~
热心网友
时间:2024-11-13 22:50
String类型是引用型的数据类型,也算是基本的数据类型,但是他比较特殊。
String str=new String("a")说明他是引用型的的,用了new关键字在堆里创建了一个字符串对象,然后是指向str的引用。
String str="a"是把string当基本类型的使用,直接给它初始化。
这两个的结果是一样的,但是存储的过程是不同的,一个在堆里,一个在栈里,对于学习后面的数据操作就可以看出来了。
多练习就理解了
热心网友
时间:2024-11-13 22:52
这个要看是在什么情况下 在编译阶段和运行阶段是不同的 都给你提示道这个程度了 剩下的你懂的哦(内存堆栈)