1.10对象的创建和生命周期

本贴最后更新于 3508 天前,其中的信息可能已经斗转星移

   在使用对象时,最关键的问题之一便是它们的生成和销毁的方式。每个对象为了生存都需要资源,尤其是内存。当我们不再需要一个对象时,它必须被清理掉,使其占有的资源可以被释放和重用。在相对简单的编程情况下,怎么清理对象似乎不是什么挑战:你创建了对象,根据需要使用它,然后它应该被销毁。然而,你很可能会遇到相对复杂的情况。

    例如,假设你正在为某个机场设计空中交通管理系统(同样的模型在仓库货柜管理系统、录像带出租系统或宠物寄宿店也适用)。一开始问题似乎很简单:创建一个容器老保存所有的飞机,然后为美宜佳飞进空中交通控制区域的飞机创建一个新的飞机对象,并将其置于容器中。对于清理工作,只需在飞机飞离此区域是删除相关的飞机对象即可。

    但是,可能还有别的系统记录着有关飞机的数据,也许这些数据不需要向主控制功能那样立即引人注意。例如,他可能记录着所有飞离机场的小型飞机的飞行计划。因此你需要有第二个容器来存放小型飞机;无论何时,只要创建的是小型飞机对象,那么它同时应该被置入第二个容器中。然后某个后台进程在空闲时对第二个容器内的对象进行操作。

    现在问题变得困难了:怎样才能知道何时销毁这些对象呢?当处理完某个对象之后,系统某个其它部分可能还在处理它。在其他很多场合中也会遇到同样的问题,在必须明确删除对象的编程系统中(例如:C++),此问题会变得十分麻烦。

    对象的数据位于何处?怎样控制对象的声明周期?C++认为效率控制是最重要的议题,所以给程序员提供了选择的权利。为了追求最大的执行速度,对象的存储空间和生命周期可以在编写程序时确定,这可以将对象置于堆栈(它们优势被称为自动变量(automatic variable)或限域变量(scoped variable))或静态存储区域内来实现。这种方式将存储空间分配和释放置于优先考虑的位置,某些情况下这样控制非常有价值。但是也牺牲了灵活性。因为必须在编写程序时知道对象确切的数量、生命周期和类型。如果试图解决更一般化的问题,例如计算机辅助设计、仓库管理或者空中交通控制,这种方式就显得过于受限了。

    第二种方式是在被称为对(heap)的内存池中动态的创建对象。在这种方式中,知道运行时才知道需要多少对象,它们的生命周期如何,以及它们的具体类型是什么。这些问题的答案只能在程序运行时相关代码被执行到的那一刻才能确定。如果需要一个对象,可以在需要的时候直接在堆中创建。因为存储空间运行的时候是被动态管理的,所以需要大量的时间在堆中分配存储空间,这可能要远远大于在堆栈中创建存储空间的时间。在堆栈中创建存储空间和释放存储空间通常各需要一条汇编指令即可,分别对应将栈顶指针向下移动和将栈顶指针向上移动。创建堆存储空间的的时间依赖于存储机制的设计。

    动态方式有这样一个一般性的逻辑假设:对象趋向于变得复杂,对于查找和释放存储空间的开销不会对对象的创建造成重大打击。动态方式所带来的更大的灵活性正是解决一般化编程问题的要点所在。

    Java完全采用了动态内存分配方式。每当想要创建新对象时,就要使用new关键字来构建此对象的动态实例。

    还有一个议题,就是对象的生命周期。对于允许在堆上创建对象的编程语言,编译器可以确定对象存活的时间,并可以自动销毁它。然而,如果在栈上创建对象,编译器就会对它的生命周期一无所知。在像C++这样的语言中,必须通过编程方式来确定何时销毁对象,这可能会因为不能正确处理而导致内存泄露(C++程序中的家常便饭)。Java提供了被称为“垃圾回收器”的机制,它可以自动发现对象何时不再使用,并继而销毁它。垃圾回收器非常有用,因为它减少了所必须考虑的议题和必须编写得代码。更重要的是,垃圾回收器提供了更高层的保障,可以避免暗藏的内存泄露问题,这个问题已经使许多C++项目折戟沉沙。

    Java的垃圾回收器被设计用来处理内存释放问题(尽管它不包括清理对象的其他方面)。垃圾回收器“知道”对象何时不再被使用,并自动释放对象占用的内存。这一点同所有对象都是继承自单根基类Object以及只能以一种方式创建对象(在堆上创建)这两个特性结合起来,使得Java编程的过程跟C++相比要简单得多,所以要做出的决策和要克服的障碍也要少很多。

总结

  1. 由空中交通管理系统引出对象应该何时被销毁。
  2. C++将对象放在堆栈中,存储空间跟生命周期在编写程序时确定。Java将对象放在堆中,需要时直接new,不用的时候垃圾回收器自动回收。
  3. 因为Java是动态管理存储空间,所以需要大量时间分配存储空间,其所用时间可能要远远大于C++在堆栈中创建存储空间的时间。
  4. 动态方式逻辑假设:对象越复杂,查找和释放对象用的时间所占比例越小。
  5. 自动释放对象占用内存同所有对象都是单根继承自基类Object以及只能以一种方式创建对象(在堆上创建)这两个特性结合起来使Java编程比C++编程简单。

----END----

  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3196 引用 • 8215 回帖
  • Java编程思想
    9 引用 • 4 回帖
  • 第1章对象导论
    9 引用 • 4 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...

推荐标签 标签

  • 数据库

    据说 99% 的性能瓶颈都在数据库。

    345 引用 • 742 回帖
  • flomo

    flomo 是新一代 「卡片笔记」 ,专注在碎片化时代,促进你的记录,帮你积累更多知识资产。

    6 引用 • 140 回帖
  • OpenResty

    OpenResty 是一个基于 NGINX 与 Lua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。用于方便地搭建能够处理超高并发、扩展性极高的动态 Web 应用、Web 服务和动态网关。

    17 引用 • 54 关注
  • 链滴

    链滴是一个记录生活的地方。

    记录生活,连接点滴

    171 引用 • 3848 回帖 • 2 关注
  • 安全

    安全永远都不是一个小问题。

    203 引用 • 818 回帖
  • MongoDB

    MongoDB(来自于英文单词“Humongous”,中文含义为“庞大”)是一个基于分布式文件存储的数据库,由 C++ 语言编写。旨在为应用提供可扩展的高性能数据存储解决方案。MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。它支持的数据结构非常松散,是类似 JSON 的 BSON 格式,因此可以存储比较复杂的数据类型。

    90 引用 • 59 回帖 • 7 关注
  • WebComponents

    Web Components 是 W3C 定义的标准,它给了前端开发者扩展浏览器标签的能力,可以方便地定制可复用组件,更好的进行模块化开发,解放了前端开发者的生产力。

    1 引用 • 10 关注
  • GitLab

    GitLab 是利用 Ruby 一个开源的版本管理系统,实现一个自托管的 Git 项目仓库,可通过 Web 界面操作公开或私有项目。

    46 引用 • 72 回帖
  • 倾城之链
    23 引用 • 66 回帖 • 162 关注
  • 程序员

    程序员是从事程序开发、程序维护的专业人员。

    588 引用 • 3538 回帖
  • 友情链接

    确认过眼神后的灵魂连接,站在链在!

    24 引用 • 373 回帖 • 1 关注
  • 资讯

    资讯是用户因为及时地获得它并利用它而能够在相对短的时间内给自己带来价值的信息,资讯有时效性和地域性。

    56 引用 • 85 回帖
  • MyBatis

    MyBatis 本是 Apache 软件基金会 的一个开源项目 iBatis,2010 年这个项目由 Apache 软件基金会迁移到了 google code,并且改名为 MyBatis ,2013 年 11 月再次迁移到了 GitHub。

    173 引用 • 414 回帖 • 367 关注
  • CongSec

    本标签主要用于分享网络空间安全专业的学习笔记

    1 引用 • 1 回帖 • 28 关注
  • SQLServer

    SQL Server 是由 [微软] 开发和推广的关系数据库管理系统(DBMS),它最初是由 微软、Sybase 和 Ashton-Tate 三家公司共同开发的,并于 1988 年推出了第一个 OS/2 版本。

    21 引用 • 31 回帖
  • 以太坊

    以太坊(Ethereum)并不是一个机构,而是一款能够在区块链上实现智能合约、开源的底层系统。以太坊是一个平台和一种编程语言 Solidity,使开发人员能够建立和发布下一代去中心化应用。 以太坊可以用来编程、分散、担保和交易任何事物:投票、域名、金融交易所、众筹、公司管理、合同和知识产权等等。

    34 引用 • 367 回帖 • 5 关注
  • gRpc
    11 引用 • 9 回帖 • 93 关注
  • 一些有用的避坑指南。

    69 引用 • 93 回帖 • 1 关注
  • HBase

    HBase 是一个分布式的、面向列的开源数据库,该技术来源于 Fay Chang 所撰写的 Google 论文 “Bigtable:一个结构化数据的分布式存储系统”。就像 Bigtable 利用了 Google 文件系统所提供的分布式数据存储一样,HBase 在 Hadoop 之上提供了类似于 Bigtable 的能力。

    17 引用 • 6 回帖 • 61 关注
  • Kafka

    Kafka 是一种高吞吐量的分布式发布订阅消息系统,它可以处理消费者规模的网站中的所有动作流数据。 这种动作(网页浏览,搜索和其他用户的行动)是现代系统中许多功能的基础。 这些数据通常是由于吞吐量的要求而通过处理日志和日志聚合来解决。

    36 引用 • 35 回帖 • 2 关注
  • JetBrains

    JetBrains 是一家捷克的软件开发公司,该公司位于捷克的布拉格,并在俄国的圣彼得堡及美国麻州波士顿都设有办公室,该公司最为人所熟知的产品是 Java 编程语言开发撰写时所用的集成开发环境:IntelliJ IDEA

    18 引用 • 54 回帖
  • 京东

    京东是中国最大的自营式电商企业,2015 年第一季度在中国自营式 B2C 电商市场的占有率为 56.3%。2014 年 5 月,京东在美国纳斯达克证券交易所正式挂牌上市(股票代码:JD),是中国第一个成功赴美上市的大型综合型电商平台,与腾讯、百度等中国互联网巨头共同跻身全球前十大互联网公司排行榜。

    14 引用 • 102 回帖 • 316 关注
  • abitmean

    有点意思就行了

    36 关注
  • OkHttp

    OkHttp 是一款 HTTP & HTTP/2 客户端库,专为 Android 和 Java 应用打造。

    16 引用 • 6 回帖 • 85 关注
  • 阿里巴巴

    阿里巴巴网络技术有限公司(简称:阿里巴巴集团)是以曾担任英语教师的马云为首的 18 人,于 1999 年在中国杭州创立,他们相信互联网能够创造公平的竞争环境,让小企业通过创新与科技扩展业务,并在参与国内或全球市场竞争时处于更有利的位置。

    43 引用 • 221 回帖 • 71 关注
  • 负能量

    上帝为你关上了一扇门,然后就去睡觉了....努力不一定能成功,但不努力一定很轻松 (° ー °〃)

    89 引用 • 1243 回帖 • 411 关注
  • C

    C 语言是一门通用计算机编程语言,应用广泛。C 语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言。

    85 引用 • 165 回帖 • 1 关注