Java 基础,String 产生了几个对象。怎么判断。

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java 基础,String 产生了几个对象。怎么判断。相关的知识,希望对你有一定的参考价值。

fun()
String s=new String("abc");
String s1="abc";
String s2=new String("abc");

请问一共产生了多少个对象,怎么判断。

三个对象,其中 s、s2分别指向堆中的两个对象,s1指向String pool中的一个对象。

这涉及到JVM中String 的机制,当你new 一个String时,总会在堆中新建一个对象,然后String 引用指向这个对象,然后检查String pool(字符串池)中有没有和这个字符串内容一样的字符串,没有的话,将此字符串加入String pool。
当你用形如 String a = "abc",声明一个字符串时,jvm先检查串池里有没有 abc 这个字符串,有的话直接指向此字符串,没有的话在串池中增加这个字符串,然后指向它。
你可以试试 String a ="abc"; String b = "abc"; System.out.print(a == b) 输出true
此时,a 和 b都指向 串池中的 "abc"
而 String a = new ("abc"); String b = "abc"; System.out.print(a == b) 输出false
此时,a指向堆中的"abc"对象,b指向串池中的"abc"对象
"=="比较的是两个引用变量所指向的是否是同一个对象,是的话则返回true,否则false追问

你搞错了,总共4个对象产生。S1指向S的地址。

追答

那你试试 System.out.println(s1 == s); 看看结果是啥。

追问

false

追答

s1指向的是堆中的一个对象。
s指向的是String pool中的对象。
s2指向的是堆中的另一个对象啊。

前面我有个地方说错了当你new 一个String时,先检查String pool中有没有和这个字符串内容一样的字符串,没有的话,将此字符串加入String pool,然后把这个对象的引用赋值给new出来的实例。
相当于 s1指向堆中的对象,那个对象中有一个引用,指向String pool中的"abc"

追问

嗯,现在确实搞懂了。确实是三个新对象,我这么说就好理解了,产生出两个堆对象S、S2,另外一个在是String pool里。S1只是指向String pool里,大概你之前标识有错误。

参考技术A 3个对象,可以通过jVisualVM,写一段OQL来查询 >> select instance:s from java.lang.String s where s.toString()=="abc"
s 会产生两个,一个在字符串常量池,一个在堆里;
s1的字面量已经在字符串常量池存在,所以直接引用;
s2同一,但是字符串常量池已经存在,所以直接引用,只在堆里分配一个就可以
参考技术B 一共4个对象3个String对象和一个abc的String对象追问

网上教程是说:2个new对象,和一个poor对象,和一个堆对象。我大概知道,但是怎么测试对象。

追答

.这个属于很理论的问题..没见过什么测试用的软件
叫和老师交给你1+1=2一样 你问他用什么测试 ...

参考技术C s和s1指向同一个“abc”,s2是new出来新建的存储区。 参考技术D 先去看看什么是对象吧,就是两个对象s,s2

String s=new String("abc")创建了几个对象?

String str=new String("abc");   紧接着这段代码之后的往往是这个问题,那就是这行代码究竟创建了几个String对象呢?

相信大家对这道题并不陌生,答案也是众所周知的,2个。

接下来我们就从这道题展开,一起回顾一下与创建String对象相关的一些JAVA知识。  

我们可以把上面这行代码分成String str、=、"abc"和new String()四部分来看待。String str只是定义了一个名为str的String类型的变量,因此它并没有创建对象;=是对变量str进行初始化,将某个对象的引用(或者叫句柄)赋值给它,显然也没有创建对象;现在只剩下new String("abc")了。那么,new String("abc")为什么又能被看成"abc"和new String()呢?

我们来看一下被我们调用了的String的构造器:  

public String(String original) {  //other code ...  }   大家都知道,我们常用的创建一个类的实例(对象)的方法有以下两种:

一、使用new创建对象。 

二、调用Class类的newInstance方法,利用反射机制创建对象。

我们正是使用new调用了String类的上面那个构造器方法创建了一个对象,并将它的引用赋值给了str变量。同时我们注意到,被调用的构造器方法接受的参数也是一个String对象,这个对象正是"abc"。由此我们又要引入另外一种创建String对象的方式的讨论——引号内包含文本。

 

这种方式是String特有的,并且它与new的方式存在很大区别。  

String str="abc";  

毫无疑问,这行代码创建了一个String对象。  

String a="abc";  String b="abc";   那这里呢?

答案还是一个。  

String a="ab"+"cd";   再看看这里呢?

答案是三个。

说到这里,我们就需要引入对字符串池相关知识的回顾了。  

在JAVA虚拟机(JVM)中存在着一个字符串池,其中保存着很多String对象,并且可以被共享使用,因此它提高了效率。由于String类是final的,它的值一经创建就不可改变,因此我们不用担心String对象共享而带来程序的混乱。字符串池由String类维护,我们可以调用intern()方法来访问字符串池。  

我们再回头看看String a="abc";,这行代码被执行的时候,JAVA虚拟机首先在字符串池中查找是否已经存在了值为"abc"的这么一个对象,它的判断依据是String类equals(Object obj)方法的返回值。如果有,则不再创建新的对象,直接返回已存在对象的引用;如果没有,则先创建这个对象,然后把它加入到字符串池中,再将它的引用返回。因此,我们不难理解前面三个例子中头两个例子为什么是这个答案了。

 

只有使用引号包含文本的方式创建的String对象之间使用“+”连接产生的新对象才会被加入字符串池中。对于所有包含new方式新建对象(包括null)的“+”连接表达式,它所产生的新对象都不会被加入字符串池中,对此我们不再赘述。因此我们提倡大家用引号包含文本的方式来创建String对象以提高效率,实际上这也是我们在编程中常采用的。

 

栈(stack):主要保存基本类型(或者叫内置类型)(char、byte、short、int、long、float、double、boolean)和对象的引用,数据可以共享,速度仅次于寄存器(register),快于堆。 

堆(heap):用于存储对象

 

以上是关于Java 基础,String 产生了几个对象。怎么判断。的主要内容,如果未能解决你的问题,请参考以下文章

Java基础 -- String 类和常量池String s1 = new String(“abc”)这句话创建了几个字符串对象8 种基本类型的包装类和常量池

string创建了多少个对象 Java

java中string类创建对象

java中String s = new String("abc")创建了几个对象

流程图详解 new String(“abc“) 创建了几个字符串对象

流程图详解 new String(“abc“) 创建了几个字符串对象