程序运行起来会在内存划分为如图几个区域:
堆区:类、对象、接口、数组 栈区:基本数据类型(String类型也会存放在栈区)
全局区:存放全局数据 常量区:存放常量 代码区:存放代码
看下面一段代码
public class PersonOBJ{ public static void main(String[] args){ class Person{ int age; String name; } Person a = new Person(); a.age = 10; a.name = "小明"; Person b = a;
System.out.println(a.name); System.out.println(b.name); } }
内存图:
存储地址以十六进制表示,存储地址类似房间门牌号,而变量(对象)相当于为门牌号命名,地址分配的十六进制数不是如图所示,而是取决于操作系统的分配,这么做只是为了方便说明。
Person a存放了一个对象new Person()的地址(比如说[0x123]),Person a其自身也有个地址(比如说[0x111]),但为了方便就简写成Person a存放了一个new Person()对象的地址(Person a [0x123])。
Person a =new Person();会在内存中开辟一个新的堆空间,堆空间存放一个存储地址为0x123的具有Person类属性的Person a对象
在new Person()创建对象后,赋给栈区Person a变量,Person a将引用对象new Person()所在堆区的地址[0x123]
访问并赋值对象属性(a.age=10),会查找对象所在堆区的地址[0x123],并赋值相应属性值;a.name="小明"以此类推。
Person b =a;
Person b仍然在栈区,把a变量(对象)赋给Person b实际上赋的值是堆区类的地址[0x123],也就是说两个变量指向了堆空间的同一个地址,这也就是为什么看到两个小明的原因。
上帝以自己为参照(模板)造人,使用这个模板可以创造很多很多人,将他们放在地球上。我们用一个人类(类)模板,使用new的方式创建一个人(对象),将其放入内存后存活了,该怎么运作就在内存里面怎么运作。内存存放对象实例取决于内存的大小,不停地创建对象必然占用内存越来越多迟早会占满。
内存有创建就应该要有回收,回收是靠java垃圾回收机制来做的,当Java虚拟机发现有一个对象没有指向的时候就会能为是一个垃圾(比如赋值null),在适当的时候(垃圾回收机制的调整处理)将其回收。
Java垃圾回收机制并不需要我们去管理怎样回收内存,这并不意味着Java程序不会造成内存泄露的危险,不停的创建对象而不去使用也有可能,但这种机率已经很小了。