1、初始化与清理的重要性

  1、许多C程序的错误都源于程序员忘记初始化变量,特别是使用程序库时,如果不知道如何初始化库的构件更容易出错

  2、当使用完一个元素时,这个元素就不会有什么影响了,所以很容易就会忘记,但是这个元素占用的资源一直存在,如果资源一直得不到释放,就会造成资源(内存)耗尽

2、构造器确保初始化:

  在java中,通过提供构造器,可以确保每个对象都会得到初始化。创建对象时,如果类对象有构造器,java就会在操作对象之前自动调用相应的构造器,从而保证了初始化进行。

3、static的含义

  static方法就是没有this的方法,在static方法的内部不能调用非静态方法,并且可以在没有创建任何对象的前提下,通过类本身调用static方法。

  static方法中为什么不能使用this关键字?

  当new 一个对象时并不是先在堆中开辟内存空间,而是先将类中的静态方法加载到方法区,然后再在堆内存中创建对象。所以说静态方法会随着类的加载而加载。当new一个对象时,该对象存在堆内存中,this关键字一般指该对象。

  程序最终都在内存中执行,变量只有在内存中存在时才会被访问,类的静态成员属于类本身,在类加载的时候就会被分配内存,可以通过类名直接访问,非静态成员属于类对象,只有在类创建对象的时候才会被分配内存,然后通过类的对象进行访问。

  static 方法不依赖任何对象就可以访问,因此对于静态方法来说,是没有this的,因为它不依赖于任何对象,既然都没有对象,所以就不会有this

4、清理:终结处理和垃当圾回收

  finalize()方法:假定对象(并非使用new)获得了一块 "特殊"的内存区域,由于垃圾回收器只知道释放那些由new 分配的内存, 所以它不知道该如何释放这块"特殊"的内存,为了应对这种情况,java允许在类中定义一个finalize()方法。它的工作原理是: 一旦垃圾回收器准备好释放对象占用的存储空间,将首先调用finalize()方法,并且在下一次垃圾回收动作发生时,才会真正回收对象占用的内存。

  有些程序员刚开始时可能会误把finalize()方法当做C++中的析构函数(C++中销毁对象必须用到这个函数)。所以有必要明确区分一下:C++中对象一定会被销毁,java里面的对象并非总是被垃圾回收。

  换句话说:

    (1) 对象可能不被垃圾回收

    (2) 垃圾回收并不等于 "析构" 

  这意味着当你不再需要某个对象之前,如果必须执行某些动作,那么得自己去做。

    (3) 垃圾回收只与内存有关

  使用垃圾回收器的唯一原因是为了回收程序不再使用的内存,但如果对象中含有其他对象,finalize()方法是不是就应该明确释放那些对象,不是的,无论对象是如何创建的垃圾回收器都会负责释放对象占据的内存。这就将对finalize()的需求限制到一种特殊情况,即通过某种创建对象方式以外的方式为对象分配了存储空间。(这段话有点拗口),但是java中一切都是对象,那特殊是指什么。

  特殊情况是说由于在分配内存时可能采用了类似C语言中的做法,而不是java中的通常做法。这种情况主要发生在使用 "本地方法" 的情况下,本地方法是一种在java中调用非 java代码的方式。

  通常,不能指望finalize()进行清理,必须创建其他的 "清理" 方法,并且明确调用。当对某个对象不再感兴趣,也就是说可以被清理了,这个对象应该处于某种状态,是它占用的内存可以被安全地释放。例如,要是对象代表了一个打开的文件,在对象被回收前程序员应该关闭这个文件。只要对象中存在没有被适当清理的部分,程序就存在隐晦的缺陷。finalize()可以用来最终发现这种情况。如果某次finalize()的动作使得缺陷被发现,那么就可以据此找出问题所在。

5、垃圾回收器如何工作

  引用计数:引用记数是一种简单但速度很慢的垃圾回收技术,每个对象都含有一个引用计数器,当有引用连接到对象时,引用计数加1,当引用离开作用域或被设置为null 时,引用计数减1。虽然管理引用记数的开销不大,但这项开销在整个程序生命周期中将持续发生。垃圾回收器会在含有全部对象的列表上遍历,当发现某个对象的引用计数为0时,就释放其占用的空间(引用记数模式经常会在计数值为0时立即释放对象)。这种方法有个缺陷,如果对象之间存在循环引用,可能会出现 "对象应该被回收,但引用计数不为0的情况"。对垃圾回收器而言,定位这样的交互自引用的对象组所需的工作量巨大。引用记数常用来说明垃圾收集的工作方式。

  在一些更快的模式中,垃圾回收器并非基于引用记数记数,其依据的思想是: 对任何 "活" 的对象,一定能最终追溯到其存活在堆栈或静态存储区之中的引用。这个引用链可能会穿过数个对象层次。所以,如果从堆栈和静态存储区开始,遍历所有的引用,就能找到所有 "活" 的对象,对于发现的每个引用,必须追踪它所引用的对象,然后是此对象所包含的所有引用,如此反复进行,直到 "根源于堆栈和静态存储区的引用" 所形成的网络全部被访问为止。你所访问过的对象必须都是 "活" 的。这就解决了 "交互自引用的对象组" 的问题。

  在上述方式下,java虚拟机采用一种自适应的垃圾回收技术。如何处理找到的存活对象,取决于不同的java虚拟机实现。有一种做法叫 停止-----复制。显然这意味着先暂停程序的运行(所以它不属于后台回收模式),然后将所有存活的对象从当前堆复制到另一个堆,没有被复制的全部都是垃圾。当对象被复制到新堆时,它们是一个挨着一个的,所以新堆保持紧凑排列,然后就可以按前述方法简单、直接地分配新空间。当把对象从一处搬到另一处时,所有指向它的那些引用都必须修正(对象的引用从A处将指向B处)。位于堆或静态存储区的引用可以直接被修正,但可能还有其他指向这些对象的引用,它们在遍历的过程中才能被找到(可以想象成有个表格,将旧地址映射到新地址)

  对于这种方法来说,效率会降低,这有两个原因,首先,得有两个堆,然后得在这两个分离的堆之间来回复制,从而得维护比实际需要多一倍的空间。第二个问题是复制。程序进入稳定状态之后,可能只会产生少量垃圾,甚至没有垃圾,尽管如此,复制式回收器仍然会将所有内存自一处复制到另一处,这很浪费。 为了避免这种情况,一些java虚拟机会进行检查:要是没有新垃圾产生,就会转换到另一种模式。这种模式成为标记-----清扫。对一般用途而言,标记---清扫方式速度相当慢,但是如果只产生少量垃圾甚至不产生垃圾时,速度就会很快了。

  标记----清扫所依据的思路同样是从堆栈和静态存储区出发,遍历所有的引用,进而找出所有存活的对象。每当找到一个存活的对象,就会给对象设一个标记,这个过程中不会回收任何对象。只有全部标记工作完成的时候,清理动作才会开始。在清理过程中,没有标记的对象将被释放,不会发生任何复制动作。所以剩下的堆空间是不连续的,垃圾回收器要是希望得到连续空间的话,就得重新整理剩下的对象。

  停止----复制的意思是这种垃圾回收动作不是在后台进行的,垃圾回收动作发生的同时,程序将会被暂停。当可用内存数量较低时,Sun版本的垃圾回收器会暂停运行程序,同样,标记----清扫工作也必须在程序暂停的情况下才能进行。

  在java虚拟机中,内存分配以较大的 "块" 为单位,如果对象较大,会占用单独的块。严格来说,停止----复制 要求在释放旧对象之前,必须先把所有存活对象从旧堆复制到新堆,这会导致大量内存复制行为。有了 "块" 之后,垃圾回收器在回收的时候就可以往废弃的块里拷贝对象了。每个块都用相应的代数来记录它是否还存活。通常,如果块在某处被引用,其代数会增加,垃圾回收器将对上次回收动作之后新分配的块进行整理。这对处理大量短命的临时对象很有帮助。垃圾回收器会定期进行完整的清理动作----大型对象仍然不会被复制(只是其代数会增加),内含小型对象的那些块则被复制并整理。java虚拟机会进行监视,如果所有对象都很稳定,垃圾回收器的效率降低的话,就切换到标记-----清扫方式,同样,java虚拟机会跟踪标记----清扫的效果,要是堆空间出现很多碎片,就会切换到停止-----复制方式,这就是 "自适应"  技术。

6、成员初始化

  对象的创建过程: 假设有个dog 类

  1、即使没有显式的使用static关键字,构造器实际上也是静态方法,因此,当首次创建类型为dog的对象时(构造器可以看成静态方法),或者dog类的静态方法/静态域首次被访问时,java解释器必须查找类路径,定位 dog.class文件

  2、载入dog.class (创建一个class 对象),有关静态初始化的所有动作都会执行。因此,静态初始化只在 class 对象首次加载的时候进行一次。

  3、当 new Dog() 创建对象的时候,首先将在堆上为 Dog对象分配足够的存储空间。

  4、这块存储空间会被清零,就自动的将Dog对象中所有基本类型数据都设置成了默认值,引用则被设置成了 null。

  5、执行所有出现于字段定义处的初始化动作

  6、执行构造器

《java编程思想》 初始化与清理的更多相关文章

  1. Java编程思想——初始化与清理

    PS:最近一直忙于项目开发..所以一直没有写博客..趁着空闲期间来一发.. 学习内容: 1.初始化 2.清理 1.初始化   虽然自己的Java基础还是比较良好的..但是在解读编程思想的时候还是发现了 ...

  2. 《Java编程思想》——初始化与清理(一)读书笔记

    第一次写这个,这一章都用word写的,结果复制过来没图片....只能上传word文档了.以后改用markdown比较好 word文档地址:<Java编程思想>--初始化与清理(一)读书笔记

  3. 《 Java 编程思想》CH05 初始化与清理

    < Java 编程思想>CH05 初始化与清理 用构造器确保初始化 在 Java 中,通过提供构造器,类的设计者可确保每个对象都会得到初始化.Java 会保证初始化的进行.构造器采用与类相 ...

  4. 《java编程思想》读书笔记(一)开篇&第五章(1)

    2017 ---新篇章  今天终于找到阅读<java编程思想>这本书方法了,表示打开了一个新世界. 第一章:对象导论 内容不多但也有20页,主要是对整本书的一个概括.因为已经有过完整JAV ...

  5. Java编程思想(11~17)

    [注:此博客旨在从<Java编程思想>这本书的目录结构上来检验自己的Java基础知识,只为笔记之用] 第十一章 持有对象 11.1 泛型和类型安全的容器>eg: List<St ...

  6. Java编程思想 (1~10)

    [注:此博客旨在从<Java编程思想>这本书的目录结构上来检验自己的Java基础知识,只为笔记之用] 第一章 对象导论 1.万物皆对象2.程序就是对象的集合3.每个对象都是由其它对象所构成 ...

  7. Java编程思想(前十章)

    Java编程思想 有C++编程基础的条件下, 前10章可以快速过一下,都是基本语法,不需要花太多时间. 着重中后段的一些章节,类型信息.泛型.容器.IO.并发等. 中文翻译版 阅读地址 对于一个架构师 ...

  8. 《Java编程思想第四版完整中文高清版.pdf》-笔记

    D.2.1 安插自己的测试代码 插入下述“显式”计时代码,对程序进行评测: long start = System.currentTimeMillis(); // 要计时的运算代码放在这儿 long ...

  9. 《Java编程思想》阅读笔记一

    Java编程思想 这是一个通过对<Java编程思想>(Think in java)第四版进行阅读同时对java内容查漏补缺的系列.一些基础的知识不会被罗列出来,这里只会列出一些程序员经常会 ...

  10. Java编程思想(第4版) 中文清晰PDF完整版

    Java编程思想(第4版) 中文清晰PDF完整版 [日期:2014-08-11] 来源:Linux社区  作者:Linux [字体:大 中 小]     <Java编程思想>这本书赢得了全 ...

随机推荐

  1. a++与++a的陷阱与盲区

    故事发生在2019.7.15的3.pm,正在复习数据结构题目,写了一句如下指令(以下函数运行在win10的dev编译器下面) #include<bits/stdc++.h> using n ...

  2. Ubuntu系统下环境安装遇到依赖冲突问题

    问题场景:在ubuntu系统下使用docker拉了一个python3.6的镜像,要在该容器中安装vim结果总是报已安装某些依赖的版本不满足要求 解决方法: 1.安装aptitude apt-get i ...

  3. python自动化第二课 - python基础

    1.标识符(identitifier),识别身份 定义:在编程语言中,标识符就是用户编程时使用的名字,用于给变量.常量.函数.语句块等命名 标识符命令规范: 1)英文,数字以及下划线(_)但不能以数字 ...

  4. Redis 中的客户端

    Redis 是一个客户端服务端的程序,服务端提供数据存储等等服务,客户端连接服务端并通过向服务端发送命令,读取或写入数据,简单来说,客户端就是某种工具,我们通过它与 Redis 服务端进行通讯并完成数 ...

  5. 用libvlc 抓取解码后的帧数据

    vlc是一套优秀的开源媒体库,其特点是提供了完整的流媒体框架, 用它可以非常方便的实现抓取解码帧的功能. 与此功能有关的关键API为 libvlc_video_set_callbacks /*设置回调 ...

  6. css中:overflow:hidden清除浮动的原理

    要想彻底清除浮动的影响,适合的属性不是 clear 而是 overflow. 一般使用 overflow:hidden,利用 BFC 的“结界”特性彻底解决浮动对外部或兄弟元素的影响. 1. 前言: ...

  7. DOM-XSS攻击原理与防御

    XSS的中文名称叫跨站脚本,是WEB漏洞中比较常见的一种,特点就是可以将恶意HTML/JavaScript代码注入到受害用户浏览的网页上,从而达到劫持用户会话的目的.XSS根据恶意脚本的传递方式可以分 ...

  8. Mysql5.7及以上版本 ONLY_FULL_GROUP_BY报错

    近期在开发过程中,因为项目开发环境连接的mysql数据库是阿里云的数据库,而阿里云的数据库版本是5.6的.而测试环境的mysql是自己安装的5.7.因此在开发过程中有小伙伴不注意写了有关group b ...

  9. 使用SpringBoot + JavaMailSender 发送邮件报错 Mail server connection failed;Could not connect to SMTP host

    说明: 出于安全考虑,阿里云默认封禁 TCP 25 端口出方向的访问流量,无法在阿里云上的云服务器通过 TCP 25 端口连接外部地址. [官方提示]:如果您需要使用阿里云上的云服务器对外部发送邮件, ...

  10. 记一次Xmrig挖矿木马排查过程

    问题现象 Linux 服务器收到报警信息,主机 CPU 跑满. 自动创建运行 Docker 容器 xmrig, 导致其他运行中容器被迫停止. 问题原因 通过 top 命令可以看到有一个 xmrig 进 ...