Java String s = new String("xyz")。这行代码执行后,生成了多少个对象?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19672427/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 19:17:30  来源:igfitidea点击:

String s = new String("xyz"). How many objects has been made after this line of code execute?

javajvm

提问by smileVann

The commonly agreed answer to this interview question is that two objects are created by the code. But I don't think so; I wrote some code to confirm.

这个面试问题的普遍同意的答案是代码创建了两个对象。但我不这么认为;我写了一些代码来确认。

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());
    }
}

The output is:

输出是:

Application output

应用输出

Does this mean that only one object was created?

这是否意味着只创建了一个对象?

Reaffirm: My question is how many object was created by the following code:

重申:我的问题是以下代码创建了多少个对象:

String s = new String("xyz")

Instead of the StringTestcode.

而不是StringTest代码。

Inspired by @Don Branson, I debugged the below code:

受@Don Branson 的启发,我调试了以下代码:

public class test {
    public static void main(String[] args) {
        String s = new String("abc");
    }
}

And the result is:

结果是:

Enter image description here

在此处输入图片说明

The id of s is 84, and the id of "abc" is 82. What exactly does this mean?

s的id是84,“abc”的id是82,具体是什么意思?

采纳答案by The Coordinator

THERE ARE ERRORS BELOW DEPENDING ON THE JVM/JRE THAT YOU USE. IT IS BETTER TO NOT WORRY ABOUT THINGS LIKE THIS ANYWAYS. SEE COMMENTS SECTION FOR ANY CORRECTIONS/CONCERNS.

以下错误取决于您使用的 JVM/JRE。无论如何,最好不要担心这样的事情。有关任何更正/疑虑,请参阅评论部分。

First, this question really asks about this addressed here: Is String Literal Pool a collection of references to the String Object, Or a collection of Objects

首先,这个问题确实在这里提出了这个问题: 字符串文字池是对字符串对象的引用的集合,还是对象的集合

So, that is a guide for everyone on this matter.

所以,这是每个人在这个问题上的指南。

...

...

Given this line of code: String s = new String(“xyz”)

鉴于这行代码: String s = new String(“xyz”)

There are two ways of looking at this:

有两种方式看待这个问题:

(1) What happens when the line of code executes -- the literal moment it runs in the program?

(1) 当这行代码执行时会发生什么——它在程序中运行的字面意思?

(2) What is the net effect of how many Objectsare created by the statement?

(2)Objects语句创建了多少个的净效果是什么?

Answer:

回答:

1) After this executes, one additional object is created.

1)执行此操作后,会创建一个额外的对象。

a) The "xyz"Stringis created and interned when the JVM loads the classthat this line of code is contained in.

a)"xyz"String当 JVM 加载class包含这行代码的时,将创建并驻留。

  • If an "xyz"is already in the intern pool from some other code, then the literal might produce no new Stringobject.
  • 如果 an"xyz"已经在一些其他代码的实习池中,那么文字可能不会产生新String对象。

b) When new String sis created, the internal char[]is a copy of the interned"xyz"string.

b)String s创建new 时,内部char[]是内部"xyz"字符串的副本。

c) That means, when the line executes, there is only one additional object created.

c) 这意味着,当该行执行时,只会创建一个额外的对象。

The fact is the "xyz"object will have been created as soon as the class loaded and before this code section was ever run.

事实是"xyz",一旦加载了类,并且在运行此代码部分之前,对象就会被创建。

...next scenario ...

...下一个场景...

2) There are three objects created by the code (includingthe interned "a")

2)代码创建了三个对象(包括interned "a"

String s1 = "a";
String s2 = "a";
String s3 = new String("a");

a) s1 and s2 are just referenced,not objects, and they point to the same Stringin memory.

a) s1 和 s2 只是被引用,而不是对象,它们String在内存中指向相同。

b) The "a" is interned and is a compound object: one char[]object and the Stringobject itself. It consisting of two objects in memory.

b) "a" 是 intern 并且是一个复合对象:一个char[]对象和String对象本身。它由内存中的两个对象组成。

c) s3, new String("a")produces one more object. The new String("a")does not copy the char[]of "a", it only references it internally. Here is the method signature:

c) s3,再new String("a")产生一个对象。newString("a")不复制char[]“a”的,它只在内部引用它。这是方法签名:

public String2(String original) {
        this.value = original.value;
        this.hash = original.hash;
}

One interned String("a")equals 2 Objects. And one new String("a")equals one more object. Net effect from code is three objects.

一名实习生String("a")等于 2 Objects。一个new String("a")等于一个对象。代码的净效果是三个对象。

回答by Giulio Franco

2 or 3 objects are created, depending on how smart the compiler is.

创建 2 或 3 个对象,具体取决于编译器的智能程度。

Nevertheless, your test is junk, because hashCodeof Strings is based on the content of the String, and not on their identity. If you want to check for identity, you should use System.identityHashCodeor just ==comparison.

然而,你的测试是垃圾,因为hashCodeStrings的基础上的内容String,而不是他们的身份。如果你想检查身份,你应该使用System.identityHashCode或只是==比较。

The compiler and the runtime are allowed (not forced) to optimize string creation whenever possible. So, they optimize literal strings, by using a single literal for the three strings you have. Anyway, the newoperator mustreturn a newobject (i.e. a newly allocated one). String optimization at runtime is possible if the static method String.valueOfis used instead. But I don't know if any caching is actually applied by current JREs (maybe it's more expensive to check a hash table than to just allocate a new String)

编译器和运行时被允许(不是强制)尽可能优化字符串的创建。因此,他们通过对您拥有的三个字符串使用单个文字来优化文字字符串。无论如何,new操作员必须返回一个对象(即一个新分配的对象)。如果String.valueOf改为使用静态方法,则可以在运行时进行字符串优化。但我不知道当前的 JRE 是否实际应用了任何缓存(也许检查哈希表比只分配一个新的更昂贵String

回答by Don Branson

I ran it in the Eclipse debugger. In that context, two objects are created, one with the id 17, the other 22:

我在 Eclipse 调试器中运行它。在这种情况下,创建了两个对象,一个 id 为 17,另一个为 22:

enter image description here

在此处输入图片说明

回答by Drifter64

Just because all your hash codes are the same does not mean that you are looking at the same object. Two objects are created. Let's break this down.

仅仅因为您所有的哈希码都相同并不意味着您正在查看相同的对象。创建了两个对象。让我们分解一下。

String s = new String(“xyz”);

In the part ' new String("xyz") ', an address is returned to the new string "xyz". When you say ' String s = ', this assigns that returned address to this object, so that they point to the same place, but the new string and string s are two seperate objects.

在'new String("xyz")'部分,一个地址被返回给新的字符串“xyz”。当你说' String s = '时,这会将返回的地址分配给这个对象,以便它们指向同一个地方,但新的字符串和字符串 s 是两个单独的对象。

回答by user2663609

Two objects will be created for this:

为此将创建两个对象:

String s = new String("abc");

One in the heap and the other in the "string constant pool" (SCP). The reference swill pointing to salways, and GC is not allowed in the SCP area, so all objects on SCP will be destroyed automatically at the time of JVM shutdown.

一个在堆中,另一个在“字符串常量池”(SCP)中。引用s会指向salways,在SCP区不允许GC,所以在JVM关闭的时候,SCP上的所有对象都会被自动销毁。

For example:

例如:

Here by using a heap object reference we are getting the corresponding SCP object reference by call of intern()

这里通过使用堆对象引用,我们通过调用 intern() 获取相应的 SCP 对象引用

String s1 = new String("abc");
String s2 = s1.intern(); // SCP object reference
System.out.println(s1==s2); // false
String s3 = "abc";
System.out.println(s2==s3); //True s3 reference to SCP object here

回答by Musaddique

There are two ways to create string objects in Java:

Java中有两种创建字符串对象的方法:

  1. Using the new operator, i.e.

    String s1 = new String("abc");
    
  2. Using a string literal, i.e.

    String s2 = "abc";
    
  1. 使用 new 运算符,即

    String s1 = new String("abc");
    
  2. 使用字符串文字,即

    String s2 = "abc";
    


Now string allocation is costly in both time and memory so the JVM (Java Virtual Machine) performs some tasks. WHAT TASKS?

现在字符串分配在时间和内存上都是昂贵的,因此 JVM(Java 虚拟机)执行一些任务。什么任务?

See, whenever you are using the newoperator the object is created, and the JVM will not look in the string pool. It is just going to create the object, but when you are using the string literals for creating string objects then the JVM will perform the task of looking in the string pool

看,每当您使用new运算符时,都会创建对象,JVM 不会在字符串池中查找。它只是要创建对象,但是当您使用字符串文字来创建字符串对象时,JVM 将执行在字符串池中查找的任务

I.e., when you write

即,当你写

String s2 = "abc";

the JVM will look in the string pool and check if "abc" already exists or not. If it exists then a reference is returned to the already existing string "abc" and a new object is not created and if it doesn't exists then an object is created.

JVM 将查看字符串池并检查“abc”是否已经存在。如果它存在,则返回对已经存在的字符串“abc”的引用,并且不创建新对象,如果它不存在,则创建一个对象。

So in your case (a)

所以在你的情况下(a)

String s1 = new String("abc");
  • Since newis used the object is created
  • 由于new使用了对象被创建

(b)

(二)

String s2 = "abc";
  • using a string literal an object is created and "abc" is not in the string pool and therefore the object is created.
  • 使用字符串文字创建一个对象,而“abc”不在字符串池中,因此创建了该对象。

(c)

(C)

String s2 = "abc";
  • Again using a string literal and "abc" is in the string pool, and therefore the object is not created.
  • 再次使用字符串文字并且“abc”在字符串池中,因此不会创建对象。


You can also check it out by using the following code:

您还可以使用以下代码进行检查:

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");
    }
}

I hope this helps... Note that ==is used to see if the objects are equal and the equals(Object)method is used to see if content are equal.

我希望这会==有所帮助...注意,它用于查看对象是否相等,而该equals(Object)方法用于查看内容是否相等。

回答by siddhartha

There is a concept called string pool in Java. A string pool (string intern pool) is a special storage area in the Java heap. When a string is created and if the string already exists in the pool, the reference of the existing string will be returned, instead of creating a new object and returning its reference.

Java中有一个叫做字符串池的概念。字符串池(string intern pool)是Java堆中一个特殊的存储区域。创建字符串时,如果字符串已存在于池中,则将返回现有字符串的引用,而不是创建新对象并返回其引用。

So String s = new String(“xyz”)it will create two objects.

所以String s = new String(“xyz”)它会创建两个对象。

  1. The first object will be created in the Java permanent heap memory as part of the argument we are passing - "XYZ". And it will be created in the String Literal Pool.

  2. The second object will be created within the Java heap memory - which will be created as part of the newoperator.

  1. 第一个对象将在 Java 永久堆内存中创建,作为我们传递的参数“XYZ”的一部分。它将在字符串文字池中创建。

  2. 第二个对象将在 Java 堆内存中创建 - 这将作为new操作符的一部分创建。

回答by Audrius Meskauskas

java.lang.Stringoverrides the hashCode()method so that the value depends on the contentof the string.

java.lang.String覆盖该hashCode()方法,以便该值取决于字符串的内容

As a result, hashCode()does not tell you anything about the number of instances. It may be the same string or may be another instance with no single byte shared. Same about equals(). This explains your output.

因此,hashCode()不会告诉您有关实例数量的任何信息。它可能是同一个字符串,也可能是另一个没有共享单个字节的实例。一样equals()。这解释了您的输出。

Use System.identityHashCode(..)for this kind of research.

使用System.identityHashCode(..)进行此类研究。

And may the source be with you.

并且可以在源与你同在

回答by Nithish

I used the hashcode()method to find the number of string objects created. The hashcode()method digests the data stored in the reference variable into a single hash value.

我使用该hashcode()方法来查找创建的字符串对象的数量。该hashcode()方法将存储在引用变量中的数据消化为单个散列值。

CASE1:

情况1:

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());

The output is:

输出是:

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();

So 4 objects created in total.

所以总共创建了 4 个对象。

CASE 2:

案例2:

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());

The output is:

输出是:

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() 

3 objects created in total.

总共创建了 3 个对象。

回答by Kiran Kawade

        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

As we can see in the above program we are getting a similar hashcode for s2 and s4 respectively although we are getting false using == operator. == operator is used for reference comparison.

正如我们在上面的程序中看到的,我们分别为 s2 和 s4 获得了类似的哈希码,尽管我们使用 == 运算符得到了错误。== 运算符用于引用比较。

Two objects have been created at "String s4=new String("Mumbai")", one in heap memory and one in stack memory. Therefore s2 compares with s4 which is created in heap memory, not with stack memory.

在“String s4=new String("Mumbai")”处创建了两个对象,一个在堆内存中,一个在堆栈内存中。因此 s2 与在堆内存中创建的 s4 进行比较,而不是在堆栈内存中。