Java内存机制和内存地址【已解决】

注:我将原博主内容进行进一步说明,方便大家理解。

问题

String s = new String(“hello”)和String s = “hello”;的区别?

区别

String s = new String(“hello”)会在栈中创建一个变量,在堆中创建一个对象,栈中变量指向堆中的对象,String s = “hello”在栈中创建一个变量,变量值就是字符串。
注:当字符串常量池中有对象hello时括号内成立!

注意

==与equals()的区别:

==:比较引用类型比较的是地址值是否相同
equals:比较引用类型默认也是比较地址值是否相同,而String类重写了equals()方法,比较的是内容是否相同。
例1

public class StringDemo2 {
    public static void main(String[] args) {
        String s1 = new String("hello");
        String s2 = "hello";
        System.out.println(s1 == s2);// false
        System.out.println(s1.equals(s2));// true
    }
}
**运行结果:**

> false 
> true

图片说明
在这里插入图片描述

例1详解

首先,通过main()方法进栈。
然后再栈中定义一个对象s1,去堆中开辟一个内存空间,将内存空间的引用赋值给s1,“hello”是常量,然后去字符串常量池 查看是否有hello字符串对象,没有的话分配一个空间存放hello,并且将其空间地址存入堆中new出来的空间中。
在栈中定义一个对象s2,然后去字符串常量池中查看是否有”hello”字符串对象,有,直接把”hello”的地址赋值给s2.
即s1中存的是堆中分配的空间,堆中分配的空间中存的是字符串常量池中分配空间存放”hello”的空间的地址值。而s2中之间存的是字符串常量池中分配空间存放”hello”的空间的地址值。
由于s1与s2中存放的地址不同,所以输出false。因为,类String重写了equals()方法,它比较的是引用类型的 的值是否相等,所以输出true。即结果为false、true。
例2

  System.out.println("内存地址测试");
        String s1 = new String("hello");
        String s2 = new String("hello");
        System.out.println(s1);
        System.out.println(s2);
        System.out.println(s1 == s2);// false
        System.out.println(s1.equals(s2));// true

        String s3 = new String("hello");
        String s4 = "hello";
        System.out.println(s3 == s4);// false
        System.out.println(s3.equals(s4));// true
        //
        String s5 = "hello";
        String s6 = "hello";
        System.out.println(s5 == s6);// true
        System.out.println(s5.equals(s6));// true
内存地址测试
hello
hello
false
true
false
true
true
true

注:这里需要大家注意堆与栈的理解

Java 中的堆和栈
例2详解

Java把内存划分成两种:一种是栈内存,一种是堆内存。
在函数中定义的一些基本类型的变量和对象的引用变量都在函数的栈内存中分配。
当在一段代码块定义一个变量时,Java就在栈中为这个变量分配内存空间,当超过变量的作用域后,Java会自动释放掉为该变量所分配的内存空间,该内存空间可以立即被另作他用。
堆内存用来存放由new创建的对象和数组。
在堆中分配的内存,由Java虚拟机的自动垃圾回收器来管理。
在堆中产生了一个数组或对象后,还可以在栈中定义一个特殊的变量,让栈中这个变量的取值等于数组或对象在堆内存中的首地址,栈中的这个变量就成了数组或对象的引用变量。
引用变量就相当于是为数组或对象起的一个名称,以后就可以在程序中使用栈中的引用变量来访问堆中的数组或对象。

s1~s6用equals()的比较不解释,都是比较的值,均为true。以下讲解==

s1、s2:二者均为new出来的,各自在堆中分配有空间,并各自将堆首地址赋值给s1、s2。空间地址不同,==比较为false。但是各自在堆中空间中保存的值均为在字符串常量池中的同一个对象的地址。所以equals()值相等,为true。
s3、s4同上例1一样。
s5、s6都是在常量池中取值,二者都指向常量池中同一对象,其地址值相同,所以结果为true。
例2

   System.out.println("栈中数据测试");
        String s1 = "hello";
        String s2 = "world";
        String s3 = "helloworld";
        System.out.println(s3 == s1 + s2);// false
        System.out.println(s3.equals((s1 + s2)));// true
        System.out.println(s3 == "hello" + "world");//true
        System.out.println(s3.equals("hello" + "world"));// true```
栈中数据测试
false
true
true
true
例3详解

equals()比较方法不解释,比较值,均相等,均为true。
s1与s2相加是先在字符串常量池中开一个空间,然后拼接,这个空间的地址就是s1与s2拼接后的地址。与s3的地址不同,所以输出为false。
s3与”hello”+”world”作比较,”hello”+”world”先拼接成”helloworld”,然后再去字符串常量池中找是否有”helloworld”,有,所以和s3共用一个字符串对象,则为true。

原文:https://blog.csdn.net/zhouhuocleverset/article/details/61935578

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值