关于String内存分配的深入探讨

一.equals与==的区别
==:对于基本类型,比较的是它们的值。对于复合类型(直接在堆中分配空间),比较的是它们在内存中的地址。
equals:该方法属于Object,而所有类都继承于Object这个基类,因此每个类都有这个方法。Object类中equals的默认实现是return (this == obj);,即默认是比较对象的内存地址。但在库中的一些类会覆盖从写equals这个方法,如:String、Integer、Date这些类中equals有自身的实现,而不再是比较类在堆内存中的地址。String中的equals,首先判断==,如果地址相同,那一定是返回true;如果地址不相同,再比较字符串字面值是否相等。


JAVA中的变量和基本类型的值存放于栈内存,而New出来的对象本身存放于堆内存,指向对象的引用还是放在堆内存。例如一下代码

int  i=1;
String s =  new  String( "Hello World" );

变量i和s以及1存放在栈内存,而s指向的对象”Hello World”存放于堆内存。
这里写图片描述

注意:栈内存的特点是内存共享,这样设计是为了减小内存消耗,前面定义了i=1,i和1都在栈内存内,如果再定义一个j=1,此时将j放入栈内存中,然后查找栈内存是否有1,如果有的话则j指向1。
如果再给j赋值2,则在栈内存中查找是否有2,如果没有就在栈内存放一个2,然后j指向2。也就是如果常量在栈内存中,就将变量指向该常量,如果没有就在该栈内存增加一个该常量,并将变量指向该常量。
这里写图片描述
如果此时j++,此时原来的1的值不会变化,而是在栈内找一个值为2的常量,如果栈内存有就指向它,如果没有就在栈内存加入2并将该变量j指向这个2的常量。

之前讲的是int类型,那么String类型又有什么区别吗?

        String w="hello world";
        String q="hello world";
        String s=new String("hello world");
        String y=new String("hello world");

        System.out.println(w==q);
        System.out.println(s==y);
        System.out.println(s==w);

程序运行结果:
true
false
false
分析:
1.分析w==q
对于直接赋值的字符串常量w,q是存放在栈内存中的,由于栈内存就有数据共享,所以w,q所指向的是同一”hello world”。所以s==w返回true
这里写图片描述

2.分析s==y
而String s=new String(“hello world”);后,变量s在栈内存内,Hello World 这个String对象在堆内存内。同样String y=new String(“hello world”),也会在堆内存创建一个新的String对象,变量y也在栈内存中,所以当用“==”来比较内存地址时,显然指向的是两个String对象,所以返回false。
这里写图片描述
3.分析s==w
一个在栈内存中,一个在堆内存中,显然内存地址不一样,所以false.

三.如题

public class Main{
    private static final String MESSAGE="taobao";
    public static void main(String [] args) {
        String a ="tao"+"bao";
        String b="tao";
        String c="bao";
        System.out.println(a==MESSAGE);
        System.out.println((b+c)==MESSAGE);
    }
}

程序运行结果:
true
false

这道题主要考察的是String类型的认识以及编译器优化。
1.分析a==MESSAGE
String a = “tao” + “bao” ;和String a = “taobao” ;编译出的字节码是一样的。所以等到运行时,根据上面说的栈内存是数据共享原则,a和MESSAGE指向的是同一个字符串

2.分析(b+c)==MESSAGE
b+c只能等到运行时才能判定是什么字符串,编译器不会优化,想想这也是有道理的,编译器怕你对b的值改变,所以编译器不会优化。运行时b+c计算出来的”taobao”和栈内存里已经有的”taobao”是一个吗?不是。b+c计算出来的”taobao”应该是放在堆内存中的String对象。因此结果是false,也由此可以看出一个b+c在堆内存中,而MESSAGE在栈内存中。

四StringBuffer
那么JAVA对字符串的相加该用什么呢

public class Main{
    private static final String MESSAGE="taobao";
    public static void main(String [] args) {
        String a = "tao" + "bao";
        StringBuffer b = new StringBuffer("tao");
        b.append("bao");

        String c = String.valueOf(b);
        System.out.println(c);
        System.out.println(a == MESSAGE);
        System.out.println(c == MESSAGE);
    }
}

程序运行结果:
taobao
true
false

因此StringBuffer的字符串也是在堆内存中。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值