关于Java中final的一个例子

最近在顺着”Java工程师成神之路”里列的条目一个一个看下来,看到final关键字那部分时,发现一个看似简单的关键字其实也是很多很多的内容在里面的,能跟对象类型、JVM内存结构关联在一起。

栗子
public class Test {

    public static void main(String[] args) {

        String a = "helloworld";
        final String b = "hello";
        String d = "hello";
        String c = b + "world";
        String e = d + "world";

        System.out.println((a == c));
        System.out.println((a == e));
    }
}

上面的例子看起来很简单,同学们可以先自己判断一下结果是多少
|
|
|
|
|
|
|
|

true
false

下面我来解释下为什么会是true、false。
首先我们要知道JVM内存模型中有栈、堆(常量池)、方法区(运行时常量池)以及其他一些部分。

  • String a = “helloworld”在编译时生成的对象本身是在字符串常量池中。
  • final String b = “hello” 因为有final 所以是final常量,存放于方法区中。
  • String c = b + “world” 中的 b 是个直接引用常量,编译期间会直接优化成 String c = “helloworld” ,所以其实是跟 a 指向常量池中同一个字符串。
  • String e = d + “world” 中的 d 是变量,无法提前优化。编译时生成于堆中。

最后补充一下字符串的创建过程:

  • “” 引号创建的字符串在字符串池中
  • new 创建字符串时首先查看池中是否有相同值的字符串,如果有,则拷贝一份到堆中,然后返回堆中的地址;如果池中没有,则在堆中创建一份,然后返回堆中的地址(注意,此时不需要从堆中复制到池中,否则导致浪费池的空间)

还有顺便说一个知识点,就是当 Integer 的数值在 -128 到 127 之间时,会有一个拆箱的操作,变成 int 也就是基本类型。

猜你喜欢

转载自blog.csdn.net/u012895369/article/details/80464530