产生String类对象的内存图和两个String对象的相等比较
为什么用==比较两个值相等的String对象,返回值是false?
因为字符串对象是存在常量池中的,两个String对象引用在比较地址值的时候,两个引用都是指向的是堆内存中的两个String对象,堆内存中的两个对象的地址值肯定不相等,所以返回false
图解1
内存图
方法区: 保存类(包括类的成员变量和方法)和一些方法以及静态变量+字符串常量池
字符串常量池: 凡是双引号括起来的都在字符串常量池中有一份
过程
运行代码String s1="abcdef";
程序运行,首先类加载,StringTest01和String类(参数String[]是一个String类,可以new一个String[]点击类看一下是数组还是String类,放到方法区,然后main方法进行压栈执行,执行String s1="abcdef",String s1作为方法内的变量放在main方法栈帧中,实际是个引用,保存的是字符串abcdef在内存中的地址abcdef在字符串常量池中,指向常量池中的"abcdef"对象。===》引用s1直接指向常量池字符串对象
运行代码String s2="abcdef" + “xy”;
String s2也作为局部变量放在栈帧中的一块内存中,出现双引号, 看常量池中有没有此字符串对象,有的话,不创建,没有的话, 创建,常量池有"abcdef"对象,则不再创建此对象,直接使用, 常量池没有 xy,创建xy对象,不过此时的"xy"对象没有任何 引用指向它。"abcdef”对象被s1引用指向着。然后两个字符串对 象进行拼接"abcdef"+"xy"="abcdefxy",又出现了字符串“abcdefxy”,则 看常量池有没有此对象,没有则创建,有的话,直接使用,常量池 没有,则创建字符串对象"abcdefxy",然后s2引用指向常量池中的 字符串“abcdefxy”对象。=============》引用s2直接指向常量池字符串对象
运行代码String s3 =new String("xy");=============》引用s3指向堆中的String对象
出现双引号,看常量池中有没有此字符串对象,有的话,不创建,没有的话,创建,常量池有xy,创 建xy对象,然后出现new关键字了,则在堆中创建String对象,不过String对象中的成员变量value指向 常量池中"xy"对象,String s3作为局部变量,作为堆内存中String对象的引用,指向堆中的String对象。
String对象的构造方法
图解2 ============>pojo对象中的String内存图
内存图
过程
程序加载,UserTest类和String类和User类都放到方法区,还有对应类的成员变量和方法都在方法区,不过开始类的成员变量值为Null,然后main方法压栈执行,给main方法分配栈帧【一个方法一个栈帧】,执行User user = new User(110,"张三"),user作为局部变量在栈中分配内存,并作为引用指向在堆内存中创建的User对象,User对象在创建时,运行其构造方法,把值110,和“张三”分别赋值给成员变量,name为String类型的引用,出现双引号,张三作为字符串对象,先去看常量池有没有,没有则创建,有直接使用,所以直接让其成员变量name指向字符串常量池中的"张三"
可能会出现的面试题(请看注释)
如下图所示,因为s1和s2引用直接指向常量池的同一个"hello"对象,引用存的是hello字符串对象的地址值,所以s1==s2比较地址值也相等
x和y引用指向的是堆中的两个对象,堆中不可能出现两个地址值一样的对象,所以两个引用保存的地址值不同,所以x==y比较地址值的时候,返回为false,而传入的构造参数相同,是被两个不同的String对象中的成员变量String类型的name引用指向的常量池中的"xyz",两个不同String对象的name引用保存的是一个值
总结【比较两个String对象相等】
比较String类型的相等问题时,如果两个String类型引用都直接指向字符串,而且这两个字符串值一样,那么两个String作==比较时就返回为true,如果两个String对象 引用指向的是两个new出来的String对象,那么再比较这两个对象引用时一定返回为false