关于java中堆内存以及常量池的理解

首先举个例子

String s1 = "hello";

String s2 = "hel" + new String("lo");

System.out.println(s1 == s2);//false

下面讨论为什么会出现这样的结果

     首先第一句话,在常量池中创建了一个hello数据(这个常量池严格意义上讲是在堆上面的),并把它的地址记录在了方法区的常量池中并且赋值给s1,第二句话,会先查看常量池中有没有“hello”这个数据,如果没有就在常量池中创建一个“hello”,再去堆中创建一个“hello”,如果有直接在堆中创建这个“hello”,并且str2不管原先常量池中有没有“hello”,它保存的都是堆中的“hello”的地址,所以两个地址不同,比较的结果肯定为false

接着看

String s3 = new String("hello");

String s4 = "hello";

System.out.println(s2 == s3)//false

System.out.println(s1 == s4)//true

     s3的原理与s2一样,因为在堆中的地址不同,所以s2 == s3为false,s4会先去常量池中查看有没有“hello”,有的话自己把它对应方法区的地址保存进s4,没有的话在常量池创建一个,把它的地址保存进s4,这里很明显,s1已经在常量池中创建了一个“hello”,这里只需要直接把方法区的地址保存进去就好了,所以s1 == s4结果为true

对Integer这个包装类一些看法

  int i= 10;

  Integer j = 10;//自动装箱

System.out.println(i == j);//true

原因是Integer会自动拆箱为int,所以结果为true

j++;//经过反编译之后可以发现其实是j = Integer.valueOf(j.intValue() + 1);

Integer y = 127;

Integet z = 127;

System.out.println(y == z);//true

y++;

z++;

System.out.println(y == z);//false

我们可以反编译发现都是调用Integer.valueOf();这个方法,那为什么结果不同呢,查看Integer.valueOf()源码发现,在-128-127之间的数,它会进行缓存,就是说-128-127之间的数在之前已经有了,直接存缓存区读出来就可以了,所以第一个y和z的里面存放的都是同一个127的地址,所以结果为true,而++之后超出了这个范围,Integer.valueOf()方法就会去new,两个new的地址肯定是不同的,所以结果为false

这里很疑惑的就是自己打印y,z就是赋值给他们的值,而不是地址,感觉很神奇

以上都是个人的一些见解,欢迎指出错误~~~

发布了10 篇原创文章 · 获赞 15 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/long_long_later/article/details/85252421