Java 字符串s=新字符串(“xyz”)。执行这行代码后,生成了多少个对象?
对于这个访谈问题,大家普遍同意的答案是代码创建了两个对象。但我不这么认为;我写了一些代码来确认Java 字符串s=新字符串(“xyz”)。执行这行代码后,生成了多少个对象?,java,jvm,Java,Jvm,对于这个访谈问题,大家普遍同意的答案是代码创建了两个对象。但我不这么认为;我写了一些代码来确认 public class StringTest { public static void main(String[] args) { String s1 = "a"; String s2 = "a"; String s3 = new String("a"); System.out.println("s1: "+s1.hashCod
public class StringTest {
public static void main(String[] args) {
String s1 = "a";
String s2 = "a";
String s3 = new String("a");
System.out.println("s1: "+s1.hashCode());
System.out.println("s2: "+s2.hashCode());
System.out.println("s3: "+s3.hashCode());
}
}
输出为:
这是否意味着只创建了一个对象
重申:我的问题是有多少对象是由以下代码创建的:
String s = new String("xyz")
class String_Check
{
public static void main(String[] n)
{
String s1 = new String("abc");
String s2 = "abc";
String s3 = "abc";
if (s1==s2)
System.out.println("s1==s2");
if(s1==s3)
System.out.println("s1==s3");
if(s2==s3)
System.out.println("s2==s3");
}
}
而不是StringTest
代码
受@Don Branson的启发,我调试了以下代码:
public class test {
public static void main(String[] args) {
String s = new String("abc");
}
}
结果是:
s的id是84,“abc”的id是82。这到底意味着什么?根据编译器的智能程度,会创建2或3个对象 然而,您的测试是垃圾测试,因为
String
s的hashCode
是基于字符串的内容,而不是基于它们的身份。如果要检查标识,应使用System.identityHashCode
或只进行=
比较
只要有可能,编译器和运行时都可以(而不是强制)优化字符串创建。因此,他们优化了文本字符串,通过对现有的三个字符串使用单个文本。
无论如何,new
操作符必须返回一个新对象(即新分配的对象)。
如果使用静态方法String.valueOf
,则可以在运行时优化字符串。但我不知道当前JRE是否实际应用了任何缓存(检查哈希表可能比只分配一个新的字符串要昂贵)我在Eclipse调试器中运行了它。在该上下文中,将创建两个对象,一个id为17,另一个id为22:
仅仅因为所有哈希代码都相同,并不意味着您正在查看同一个对象。将创建两个对象。让我们来分析一下
String s = new String(“xyz”);
在“新字符串(“xyz”)部分中,将向新字符串“xyz”返回一个地址。当您说“String s=”时,这会将返回的地址分配给该对象,以便它们指向相同的位置,但新字符串和字符串s是两个独立的对象。根据您使用的JVM/JRE,下面会出现错误。无论如何,最好不要担心这样的事情。有关任何更正/问题,请参见评论部分。
首先,这个问题实际上是关于这里所讨论的问题:
所以,这是每个人在这个问题上的指南
给定这行代码:String s=新字符串(“xyz”)
有两种方式来看待这一点:
(1) 当代码行执行时会发生什么——它在程序中运行的文字时刻
(2) 语句创建了多少对象
的净效果是什么
答复:
1) 执行此操作后,将创建一个附加对象。
a) 当JVM加载包含此行代码的类时,将创建并插入“xyz”
字符串
- 如果某个
“xyz”
已从其他代码位于实习生池中,则该文本可能不会生成新的字符串
对象
b) 创建新的字符串s
时,内部char[]
是插入的“xyz”
字符串的副本
c) 这意味着,当执行行时,只会创建一个附加对象
事实上,“xyz”
对象将在类加载后以及运行此代码部分之前创建
…下一个场景
2) 代码创建了三个对象(包括插入的“a”
)
a) s1和s2只是引用,而不是对象,它们指向内存中相同的String
b) “a”是内部的,是一个复合对象:一个char[]
对象和String
对象本身。它由内存中的两个对象组成
c) s3,新字符串(“a”)
生成一个以上的对象。新的字符串(“a”)
不会复制“a”的char[]
,它只在内部引用它。以下是方法签名:
public String2(String original) {
this.value = original.value;
this.hash = original.hash;
}
一个插入的字符串
(“a”)
等于2个对象
。一个新字符串(“a”)
等于多个对象。代码的净效果是三个对象。将为此创建两个对象:
String s = new String("abc");
一个在堆中,另一个在“字符串常量池”(SCP)中。引用s
将始终指向s
,并且SCP区域中不允许使用GC,因此在JVM关闭时,SCP上的所有对象都将自动销毁
例如:
在这里,通过使用堆对象引用,我们通过调用intern()获得相应的SCP对象引用
有两种方法可以在Java中创建字符串对象:
使用新运算符,即
String s1 = new String("abc");
使用字符串文字,即
String s2 = "abc";
现在字符串分配在时间和内存上都很昂贵,所以JVM(Java虚拟机)执行一些任务。什么任务
请参阅,无论何时使用new
操作符,都会创建对象,并且JVM不会查看字符串池。它只是要创建对象,但是当您使用字符串文本创建字符串对象时,JVM将执行在字符串池中查找的任务
也就是说,当你写作的时候
String s2 = "abc";
JVM将查看字符串池并检查“abc”是否已经存在。如果存在,则返回对已存在字符串“abc”的引用,并且不创建新对象;如果不存在,则创建对象
那么你的情况呢
(a)
- 由于使用了
new
,因此创建了对象
(b)
- 使用字符串文字创建对象,并且“abc”不在
字符串池,从而创建对象
(c)
- 再次使用字符串文字和“abc”在t中
String s2 = "abc";
String s1 = new String("abc");
String s2 = "abc";
String s2 = "abc";
class String_Check
{
public static void main(String[] n)
{
String s1 = new String("abc");
String s2 = "abc";
String s3 = "abc";
if (s1==s2)
System.out.println("s1==s2");
if(s1==s3)
System.out.println("s1==s3");
if(s2==s3)
System.out.println("s2==s3");
}
}
String s="
Fred";
System.out.println(s.hashCode());
s=s+"47";
System.out.println(s.hashCode());
s=s.substring(2,5);
System.out.println(s.hashCode());
s=s.toUpperCase();
System.out.println(s.hashCode());
s=s.toString();
System.out.println(s.hashCode());
Fred--2198155 //1st object ---------------- String s="Fred"
Fred47--2112428622 //2nd object ---------------- s=s+"47"
ed4--100213 //3rd object ---------------- s=s.substring(2,5)
ED4--68469 //4th object ---------------- s=s.toUpperCase()
ED4--68469 //this is retrieved from the string constant pool -------- s=s.toString();
String s="FRED";
System.out.println(s.hashCode());
s=s+"47";
System.out.println(s.hashCode());
s=s.substring(2,5);
System.out.println(s.hashCode());
s=s.toUpperCase();
System.out.println(s.hashCode());
s=s.toString();
System.out.println(s.hashCode());
FRED--2166379 //1st object ---------------- String s="Fred"
FRED47--2081891886 //2nd object ---------------- s=s+"47"
ED4--68469 //3rd object ---------------- s=s.substring(2,5)
ED4--68469 //this is retrieved from the string constant pool ------- s=s.toUpperCase()
ED4--68469 //this is retrieved from the string constant pool -------- s=s.toString()
String s1="Pune";
String s2="Mumbai";
String s3="Pune";
String s4=new String("Mumbai");
System.out.println("S1 :"+s1.hashCode()); //S1 :2499228
System.out.println("S2 :"+s2.hashCode()); //S2 :-1979126203
System.out.println("S3 :"+s3.hashCode()); //S3 :2499228
System.out.println("S4 :"+s4.hashCode()); //S4 :-1979126203
System.out.println(s2==s4); // false
public class Rajesh {
public static void main(String[] args){
String s1=new String("Rajesh");
System.out.println(s1+s1.intern());
}
}
RajeshRajesh //s1=Rajesh+s2.intern()=Rajesh
public String(String original) {
int size = original.count;
char[] originalValue = original.value;
char[] v;
if (originalValue.length > size) {
// The array representing the String is bigger than the new
// String itself. Perhaps this constructor is being called
// in order to trim the baggage, so make a copy of the array.
int off = original.offset;
v = Arrays.copyOfRange(originalValue, off, off+size);
} else {
// The array representing the String is the same
// size as the String, so no point in making a copy.
v = originalValue;
}
this.offset = 0;
this.count = size;
this.value = v;
}
String s1 = "abc";
String s2 = "abc";
String s3 = new String("abc");
String s4 = s3.intern();
System.out.println("s1: "+System.identityHashCode(s1));
System.out.println("s2: "+System.identityHashCode(s2));
System.out.println("s3: "+System.identityHashCode(s3));
System.out.println("s4: "+System.identityHashCode(s4));
String s1 ="Brajesh";
String s = new String("Brajesh");//it will create only one object in heap area
public static void main(String[] args)
{
String str = "atul";
String string = new String("manoj");
String string2 = "manoj";
System.out.println(str == string);
}
**/** Cache the hash code for the string */
private int hash; // Default to 0
public int hashCode() {
int h = hash;
if (h == 0 && value.length > 0) {
char val[] = value;
for (int i = 0; i < value.length; i++) {
**h = 31 * h + val[i];**
}
hash = h;
}
return h;
}**
String s = new String("xyz");