Java对象存储

Java对象存储教程

我们在 对象的创建与使用 的教程中了解到,对象的创建是通过对类进行 new。那么创建好的对象它在 jvm 内存 里面是怎么存在的的呢?

在学习 数组的内存空间 的时候,我们了解了数组它是怎么样存放的,对象的存储与数组一样,也分为堆区和栈区。

Java对象存储详解

在创建每个对象的时候,(java 里面对创建对象也叫做类的实例化)我们会给每个对象定义一个名字,然后 new 加类的名字来具体的对象来赋值。

我们以对象的创建与使用里面的例子,动物来描述,具体的存储如下图:

03 对象存储.png

从上图中我们可以看到,对象的名称在栈内存中存储(方便理解,其实是栈内存中存储的是对应的堆内存的地址),而对象的具体内容在对应的堆内存中,必须要使用 new 关键字来开辟堆内存空间,在堆内存中保持着对象的属性信息。

对象在使用之前是必须要被实例化的,如果一个对象被定义,但是没有被实例化,那么在运行过程中会抛出异常,java 程序将不会继续运行下去。

Java创建多个对象

前面我们已经介绍过创建一个对象,创建多个对象和创建一个对象一样,但是名字不能相同,我们还是以动物创建为例子,Animal.java 类

package com.haicoder.net.clas; /** * */ public class Animal { String clolr;//颜色 int age; //年龄 String animalName; public void eat(String foodName){ System.out.println("动物名字 : " + animalName +" 在吃 " + foodName); //打印出动物的名字,方法里面的具体操作 } public String getClolr() { return clolr; } public void setClolr(String clolr) { this.clolr = clolr; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getAnimalName() { return animalName; } public void setAnimalName(String animalName) { this.animalName = animalName; } }

创建不同动物对象

package com.haicoder.net.clas; /** * java 测试类 */ public class AnimalTest { public static void main(String[] args) { System.out.println("嗨客网(www.haicoder.net)"); Animal cat = new Animal(); //定义一个对象 cat.animalName = "猫"; cat.eat("鱼"); Animal dog = new Animal(); dog.animalName = "狗"; dog.eat("骨头"); System.out.println("Over"); } }

我们可以看到,我们为 Animal 类创建了 dog 和 cat 两个对象,他们的运行结果如下,他们是用 Animal 类 new 类两次,创建了两个不同的对象。

04 类创建多个对象.png

我们可以看到创建的两个动物,一个是猫一个是狗,他们都在做自己对应的事情。内存结构图如下:

05 创建不同对象.png

创建相同对象

package com.haicoder.net.clas; /** * java 测试类 */ public class AnimalTest { public static void main(String[] args) { System.out.println("嗨客网(www.haicoder.net)"); Animal cat = new Animal(); //定义一个对象 cat.animalName = "猫"; cat.eat("鱼"); Animal dog = cat; dog.animalName = "狗"; dog.eat("骨头"); System.out.println("猫对象的动物名字: " + cat.animalName); System.out.println("Over"); } }

我们在创建 dog 对象的时候,直接将 cat 的名字给了 dog,意思就是创建动物对象的时候, dog 和 cat 指向同一个堆内存地址。运行结果如下:

06 创建相同对象.png

我们看到,运行后的猫对象的名字也变成了狗了,因为猫和狗对象指向的堆内存空间是一样的,任何一个对象堆数据进行修改,另一个指向同一个堆的对象数据也会改变。内存结构如下:

07 堆地址空间.png

我们看到 cat 和 dog 指向的堆地址空间是一样的,所以如果两个对象名称指向同一个对象,那么任意一个对象改变了里面的数据信息,另位指向相同堆地址的对象就能够看到变化的数据。

Java匿名对象

我们知道,对象的创建的时候,会先定义一个对象名称,然后在 new 一个对象给该对象名称。对象的存储空间是先将名称存在栈上面,在将栈上面记录的地址指向堆。匿名对象表示只在堆上面开辟空间,不会占用栈的任何空间。

案例

package com.haicoder.net.clas; /** * java 测试类 */ public class AnimalTest { public static void main(String[] args) { System.out.println("嗨客网(www.haicoder.net)"); new Animal().eat("好吃的食物!"); } }

运行结果如下:

08 匿名对象.png

我们可以看到,匿名对象的创建与一般对象创建一样,只不过匿名对象没有对一个对象名称赋值,而是直接 new 然后调用对象里面的方法,打印结果,名字为 null ,是因为我们没有对对象里面的属性 animalName 赋值,String 类型的数据,默认值是 null

Java对象存储总结

Java 语言创建多个对象和创建一个对象一样,可以用 new 关键字加类名称来创建对象,创建多个对象的时候,我们如果用 new 来创建不同的对象的时候,他们指向的堆地址空间是不一样的,数据的变化不会影响其他的对象,如果对象创建赋值的时候通过其他已经创建好的对象赋值,那么指向相同的堆内存空间。

堆内存空间相同,那么一个数据变化,剩下的相同的指向该堆区域的对象数据也会变化。

匿名对象和普通对象的创建一样,都是通过 new 方法来创建,只不过,匿名对象只会在堆空间上面生成对象,在栈里面不会占用内存空间。