当使用一个类实例化多个对象时,多个对象之间是什么关系?他们各自的数据会不会发生混淆?这次课跟大家讲解一下这个问题。学完本次课,大家应该对对象在内存中的表示方式有一个初步的了解,为理解更深入的面向对象概念打一个基础。

编程任务:小明家的狗狗

我们还是通过一个程序任务来理解相关概念。先看看任务描述:小明养了两只小狗,一只叫旺财,白色,3岁;另一只叫小强,黄色,2岁。我们通过键盘向小狗发出指令,当我们输入旺财的时候,旺财需要做自我介绍。当我们输入小强的时候,小强要做自我介绍。当我们输入的既不是旺财,又不是小强的时候,输出“木有这只小狗”。我们用面向对象的方法来完成这个任务。

 创建类和对象

使用面向对象的方法编写程序,通常包含如下三个核心步骤:

1.创建与待解决问题相关的类

2.定义属于某类的对象

3.使用new关键字实例化该对象

从编程任务的描述我们可以看到。两只小狗的共同状态特征是姓名和年龄,行为特征是"自我介绍",因此,可以声明一个Dog类如下:

第一步:新建一个项目:DemoDogs

第二步:在项目中新增一个类:AppMain,项目的入口主函数main放在该类中。

新建AppMain类

AppMain类代码如下:

第三步:在项目中新增一个类:Dog,类代码如下:

public class Dog {
int age;
String name; public void Introduce(){
System.out.println("我是"+name+",我今年"+age+"岁了");
}
}

第四步:修改AppMain类的main函数:

public class AppMain {

    public static void main(String[] args) {
// TODO Auto-generated method stub
Dog dog1 = new Dog();
Dog dog2 = new Dog();
}
}

对象实例化的过程解释

我们来看一下定义并实例化一个对象的具体过程。Dog dog1 = new Dog();这样一条语句,可以分成3个步骤来理解。在具体讲解之前,我们先要弄清一个事实:在运行程序的时候,数据是放在内存中的。

首先,Dog dog1部分,会在计算机栈内存中分配一块空间,这块空间的名称是dog1,并且dog1的值只能是一个内存地址,该地址里存放的必须是一个Dog对象。

其次,new Dog()部分,会在堆内存里面分配一块区域(在右边图中用两个橙色方格来表示,白色部分表示的是内存其它区域),假设刚分配到的这块内存区域的地址是0x1000(至于真实地址是什么,我们就没必要知道了,cpu自己知道就行了)。这块内存区域用来存放Dog对象的成员变量,即一个name成员变量和一个age成员变量。

最后,第三个步骤是赋值操作,赋值操作就是将刚才new出来的Dog对象所在的内存空间地址0x1000赋值给变量dog1。

请注意:这里将dog1称为变量,只是为了表述方便。其实dog1所代表的是内存中一个Dog对象,所以以后我们直接称dog1为对象dog1,或者实例dog1,不再称为变量。

现在我们还没有给dog1的成员变量赋任何值,也就是说我们只知道dog1是一条狗,但还不知道他叫什么,不知道他几岁。我们现在在程序里给dog1设置一些数据。

public class AppMain {

    public static void main(String[] args) {
// TODO Auto-generated method stub
Dog dog1 = new Dog();
dog1.name = "旺财";
dog1.age = 3; Dog dog2 = new Dog();
dog2.name = "小强";
dog2.age = 2;
}
}

这里有一点需要说明一下,对象dog1的成员name和age没有赋过任何值的时候,他们有一个默认值。任何基础数据类型的变量,如果从来没有给这个变量赋过值的话,JVM会给变量分配一个默认值。Int类型的默认值是0,string类型默认值是空字符串,空字符串用一对双引号表示。其它数据类型的默认值我们以后会慢慢接触到。如果给对象dog1的成员变量赋值,比如dog1.name=“旺财”;默认值就会更改为“旺财“。

刚才我们分析的是dog1对象在实例化时成员变量的内存结构,现在我们再分析一下成员方法的内存分配情况。JVM将成员变量存放在堆内存中,成员方法存放在另一块内存空间中,叫做“方法区” 这块区域存放了Dog类的信息,其中就包括成员方法。方法区中的成员方法会和堆内存中的成员变量关联对应起来吗?当然会,JVM会帮助我们完成这个工作。JVM会按照一定机制将这块方法区中的方法与堆内存区中的成员变量相互关联起来,当执行dog1.name = “旺财”这条语句的时候,会将字符串“旺财”送到dog1的”堆内存“区的成员变量name中,当执行dog1.Introduce()这条语句的时候,会调用dog1的方法区中introduce方法。注意:下面这几条语句都是错误的语句,大家想一想为社么错误。

这就是单个对象的实例化过程。这种用图形的方式描述对象的内存结构,对理解类和对象的一些重要概念有很大帮助,希望大家能够理解并掌握这种画图方法,以后如果遇到难以理解的问题,可以按这个方法自己画一画,往往很容易就能帮助我们理清思路。

现在再看看新增dog2对象的内存结构。

dog1对象表示的是堆内存中创建出来的一个Dog对象,成员变量在堆内存,方法在方法区。现在看看新增一个dog2对象时发生了什么。与刚才的分析一样,栈内存会有一个对象名称dog2,代表的是在堆内存中创建的另一个Dog对象,成员变量放在堆内存中,这块成员变量区域与上面dog1的内存区域是两个不同的区域,dog2的成员变量与dog1的成员变量之间相互独立,互不影响。这就叫做每个对象都拥有一份成员变量的拷贝。

然而,dog2的方法区却和dog1的方法区是共用的。也就是说,introduce方法只有一份,dog1.introduce()语句所调用的代码和dog2.introduce()语句所调用的代码是同一份代码,但是为什么输出结果不一样呢?原因是在程序运行过程中,JVM可以根据是由哪个对象发起对introduce方法的调用,方法中所用到的成员变量数据就使用哪个对象的数据,这样,对象dog1调用introduce(),方法里的name和age用的是dog1的name和p的age,而dog2调用introduce时,方法里的name和age用的就是dog2对象的name和age。

搞清楚上述概念后,剩余的代码请读者自己完成。

Java入门:创建多个对象的更多相关文章

  1. 《Effective Java》—— 创建与销毁对象

    本篇主要总结的是<Effecticve Java>中关于创建和销毁对象的内容. 比如: 何时以及如何创建对象 何时以及如何避免创建对象 如何确保及时销毁 如何管理对象销毁前的清理动作 考虑 ...

  2. 和我一起学Effective Java之创建和销毁对象

    前言 主要学习创建和销毁对象: 1.何时以及如何创建对象 2.何时以及如何避免创建对象 3.如何确保它们能够适时地销毁 4.如何管理对象销毁之前必须进行的清理动作 正文 一.用静态工厂方法代替构造器 ...

  3. Effective Java - [2. 创建与销毁对象]

    让对象的创建与销毁在掌控中. Item 1: 使用静态工厂方法而非使用构造函数 public static Boolean valueOf(boolean b) { return b ? Boolea ...

  4. Java入门 - 语言基础 - 04.对象和类

    原文地址:http://www.work100.net/training/java-object-class.html 更多教程:光束云 - 免费课程 对象和类 序号 文内章节 视频 1 概述 2 J ...

  5. Java进阶 创建和销毁对象

    最近准备写点Javase的东西,希望可以帮助大家写出更好的代码. 1.给不可实例化的类提供私有构造器 比如:每个项目中都有很多工具类,提供了很多static类型的方法供大家使用,谁也不希望看到下面的代 ...

  6. Java入门系列-11-类和对象

    这篇文章为你搞懂类和对象的使用 对象:用来描述客观事物的实体,由一组属性和方法组成,万物皆对象. 属性:就是对象的特征,像身高.体重.颜色 方法:对象的行为,如跑.跳 类:类是模子,定义对象将会拥有的 ...

  7. Java入门笔记 03-面向对象(下)

    介绍:除了前面介绍的关于类.对象的基本语法之外,下面继续介绍Java面向对象的特性. 一. 包装类: 从JDK 1.5以后,Java就提供了自动装箱和自动拆箱操作,即: 自动装箱:将一个基本类型的变量 ...

  8. Java入门笔记 03-面向对象(上)

    介绍:Java是面向对象的程序设计语言,类是面向对象的重要内容,可以把类当成是一种自定义类型,可以使用类来定义变量,这种类型的变量统称为引用变量.也就是说,所有类都是引用类型.Java也支持面向对象的 ...

  9. 针对安卓java入门:类和对象

    定义类 class Dog { String name; int age; void jump(){ } } 生成对象: public class Test { public static void ...

  10. 【读书笔记】《Effective Java》——创建和销毁对象

    Item 1. 考虑用静态工厂方法替代构造器 获得一个类的实例时我们都会采取一个共有的构造器.Foo x = new Foo(): 同时我们应该掌握另一种方法就是静态工厂方法(static facto ...

随机推荐

  1. Teamproject Week7 --Scrum Meeting #1 2014.10.28

    这是团队的第一次会议,具体议题如下: 1)我们明确了团队成员的职责所需: PM职责:根据项目范围.质量.时间与成本的综合因素的考虑,进行项目的总体规划与阶段计划.  控制项目组各成员的工作进度,即时了 ...

  2. Daily Scrumming* 2015.10.29(Day 10)

    一.总体情况总结 二.今明两天任务表 Member Today’s Task Tomorrow’s Task 江昊 了解微信API,与社团服务平台创业公司嗨社团创始人沟通,了解其平台运营方案与商业模式 ...

  3. 2018-2019-20172321 《Java软件结构与数据结构》第八周学习总结

    2018-2019-20172321 <Java软件结构与数据结构>第八周学习总结 教材学习内容总结 第12章 优先队列与堆 一.概述 堆 堆的前提就是他首先是一个完全二叉树,其次就是满足 ...

  4. 对TCP/IP网络参数进行调整

    对TCP/IP网络参数进行调整 调整TCP/IP网络参数,可以增强抗SYN Flood的能力,命令如下所示:# echo 'net.ipv4.tcp_syncookies = 1' >> ...

  5. 软工网络15团队作业8——Beta阶段敏捷冲刺(Day2)

    提供当天站立式会议照片一张 每个人的工作 1.讨论项目每个成员的昨天进展 赵铭: 根据计划安排,继续学习数据库. 吴慧婷:做Beta阶段的计划,并为界面设计寻找素材,学习界面优化. 陈敏: 根据任务, ...

  6. Delphi中BCD和Currency类型

    用了这些年的Delphi,竟然对Currency及TBCDField一知半解,下文给了很好的讲解,值得一读. 一.       BCD类型 BCD即Binary-Coded Decimal?,在Del ...

  7. lucene介绍

    1.https://blog.csdn.net/shuaicihai/article/details/65111523 2.https://www.cnblogs.com/rodge-run/p/65 ...

  8. Jquery插件收集【m了慢慢学】

    1. Simple Effects for Drop-Down Lists 一个jQuery插件用于将普通的select控件转成一个带有一些简单扩展效果的下拉列表. 2. X-editable 这个插 ...

  9. MySQL复制 -- 复制出错怎么办?

    假如我们生产环境复制出错?该怎么办呢? 下面提供几种办法: 1. 手工处理,补回不一致数据(可以利用主库来补数据.也可以利用binlog来补数据) 2.用开源工具来解决一致性问题 3.自己造轮子,解决 ...

  10. Java Junit测试框架

    Java    Junit测试框架 1.相关概念 Ø JUnit:是一个开发源代码的Java测试框架,用于编写和运行可重复的测试.它是用于单元测试框架体系xUnit的一个实例(用于java语言).主要 ...