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

编程任务:小明家的狗狗

我们还是通过一个程序任务来理解相关概念。先看看任务描述:小明养了两只小狗,一只叫旺财,白色,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. 硬件设计原理图Checklist 参考案例二 【转载】

    类别 描述 检视规则 原理图需要进行检视,提交集体检视是需要完成自检,确保没有低级问题. 检视规则 原理图要和公司团队和可以邀请的专家一起进行检视. 检视规则 第一次原理图发出进行集体检视后所有的修改 ...

  2. ASP.net四则运算《《《策略模式

    Calculator.cs using System; using System.Collections.Generic; using System.Linq; using System.Web; / ...

  3. Parallel学习

    Parallel给cpu的核有关系,在Parallel中,写入需要并行执行的方法,比如:方法1需要3秒:方法2需要6秒:方法3需要9秒: 并行情况下,加上任务分配,上下文切换需要1秒,执行方法总耗时只 ...

  4. 项目冲刺Beta第一篇博客

    Beta版本冲刺计划安排 1.当天站立式会议照片: 2.工作分工: 团队成员 分工 张洪滨060  排行榜界面美化 陈敬轩059  注册成功界面美化 黄兴067  登录界面美化 林国梽068  答题界 ...

  5. 项目冲刺Beta第三篇博客

    Beta版本冲刺计划安排 1.当天站立式会议照片: 2.工作分工: 团队成员 分工 张洪滨060  排行榜界面美化 陈敬轩059  注册成功界面美化 黄兴067  登录界面美化 林国梽068  答题界 ...

  6. 【大数据应用技术】作业八|爬虫综合大作业Molly134

    本次作业的要求来自:https://edu.cnblogs.com/campus/gzcc/GZCC-16SE2/homework/3075 前言:本次作业是爬取CBO中国票房2010-2019年每年 ...

  7. UTC时间与北京时间

    经常混淆于此,特地研究了一下,记录在此以备忘. 整个地球分为二十四时区,每个时区都有自己的本地时间.在国际无线电通信场合,为了统一起见,使用一个统一的时间,称为通用协调时(UTC, Universal ...

  8. 通过cmd命令安装、卸载、启动和停止Windows Service(InstallUtil.exe)

    步骤: 1.运行--〉cmd:打开cmd命令框 2.在命令行里定位到InstallUtil.exe所在的位置 InstallUtil.exe 默认的安装位置是在C:/Windows/Microsoft ...

  9. 固态盘经常性蓝屏处理方法(WIN7/8)

    型号:intel 520S 大小;120G 我的是笔记本,这段时间辞职,有了时间折腾自己的电脑系统了,想装WIN8来着,PE下直接把固态盘的分区都干掉了,分了C,D(40G,剩下的空间),安装阶段完美 ...

  10. [官网]SQLSERVER ON linux 的最低要求 以及安装方法

    快速入门:在 Red Hat 上安装 SQL Server 并创建数据库 总体说明: 适用于: SQL Server (仅限 Linux)Azure SQL 数据库Azure SQL 数据仓库并行数据 ...