1、局部变量:
局部变量通常存储在栈内存中。基本类型的局部变量(如int、float、char等)的变量名和值都直接存放在栈中。而引用类型的局部变量(如String、自定义对象等)的变量名存放在栈中,但变量指向的对象实例(即对象的值)则存放在堆中。
具体地说,当我们在方法中声明一个引用类型的局部变量并为其分配一个对象时(如String str = new String(“Hello”);),str这个变量名会被存放在栈中,而new String(“Hello”)创建的对象实例则会被存放在堆中。str这个变量名实际上是一个指向堆中对象实例的引用。
2、引用类型:
在Java中,引用类型是指那些可以指向对象实例的类型,如类、接口、数组等。引用类型的变量名存放在栈中,而变量指向的对象实例则存放在堆中。当我们通过new关键字创建一个对象实例时,JVM会在堆中为该对象实例分配内存空间,并返回一个指向该对象的引用。这个引用可以被赋值给一个引用类型的变量,从而让我们在代码中可以通过该变量来访问和操作该对象实例。
需要注意的是,栈中的数据大小和生命周期是可以确定的,当方法执行完毕后,栈帧会被销毁,栈中存储的局部变量也会被释放。而堆中的对象实例则由垃圾回收器负责回收,因此其大小和生命周期不需要确定,具有很大的灵活性。
另外,Java中还有一种特殊的引用类型叫做常量引用,它们通常指向常量池中的对象实例。常量池是JVM在内存中专门划分的一个区域,用于存储编译期生成的各种字面量和符号引用。常量池中的对象实例是不可变的,因此它们可以在多个引用之间共享。