1、“.....须要把你对本地化环境的想法改变为。也就意味着要明白的垃圾回收器。在你明白这章里所推荐的内容时,有必要对的内存管理环境有个大概的了解。那我们就开始大概的了解下吧。垃圾回收器为你控制托管内存。不像本地运行环境,你不用负责对内存泄漏,不定指针,未初始化指针,或者个其它内存管理的服务问题。但垃圾回收器前不是个神话你样要自己清理。你要对非托管资源负责,例如文件句柄,数据链接,对象,对象,以及其它些系统对象。这有个好消息因为管理内存,明确的设计风格可以更容易的实现。循环引用,不管是简单关系还是复杂的网页对象,都非常容易。的标记以及严谨的高效算法可以检测到这些关系,并且完全的删除不可达的网页对象。是通过对从应用程序的根对象开始,通过树形结构的漫游来断定个对象是否可达的,而不是强迫每个对象都保持些引用跟踪,就是这样的。就是个很好的例子......”。
2、“.....是个的集合,而每个又是的集合,每个又是的集合,定义了这些类型的关系。这里就有些从到它的列的引用。而同时,也同样有个引用到它的容器上,也就是。包含引用到,最后每个对象都包含个引用到。如果这还不够复杂,那可以创建个,它提供对经过过滤后的数据表的顺序访问。这些都是由管理的。所有这些贯穿网页的引用构成了。释放内存是的责任。因为框架的设计者让你不必释放这些对象,这些复杂的网页对象引用不会造成问题。没有必须关心这些网页对象的合适的释放顺序,这是的工作。的设计结构可以简化这些问题,它可以识别这些网页对象就是垃圾。在应用程序结束了对的引用后,没有人可以引用到它的子对象了译注就是里的对象再也引用不到了。因此,网页里还有没有对象循环引用,已经点也不重要了,因为这些对象在应用程序都已经不能被访问到了,它们是垃圾了。垃圾回收器在它独立的线程上运行,用来从你的程序里移除不使用的内存......”。
3、“.....它还会压缩托管堆。压缩堆就是把托管堆中活动的对象移到起,这样就可以空出连续的内存。图展示了两个没有进行垃圾回收时的内存快照。所有的空闲内存会在垃圾回收进行后连续起来。图垃圾回收器不仅仅是移动不使用的内存,还移除动其它的对象,从而压缩使用的内存,让出最多的空闲内存。正如你刚开始了解的,垃圾回收器的全部责任就是内存管理。但,所有的系统资源都是你自己负责的。你可以通过给自己的类型定义个析构函数,来保证释放些系统资源。析构函数是在垃圾回收器把对象从内存移除前,由系统调用的。你可以,也必须这样来释放任何你所占用的非托管资源。对象的析构函数有时是在对象成为垃圾之后调用的,但是在内存归还之前。这个非确定的析构函数意味着在你无法控制对象析构与停止使用之间的关系译注对象的析构与对象的无法引用是两个完全不同的概念。关于,本人推荐读者参考下的框架程序设计修订版中讨论的垃圾回收器......”。
4、“.....并且这在设计上有个重大的分歧。有经验的程序员写的类总在构造函数内申请内存并且在析构函数中释放它们好的,坏的构造系统需要的资源销毁资源,使用系统资源的生存周期这是种很常见的风格,它保证资源无异常的释放。但这在里不工作,至少,与这不同。明确的析构函数不是环境或者的部份。强行用的风格在里使用析构函数不会让它正常的工作。在里,析构函数确实是正确的运行了,但它不是即时运行的。在前面那个例子里,代码最终在上,但在里,当析构函数存在时,它并不是在上。它会在后面的个未知时间上运行。你不知道是什么时候,你也无法知道是什么时候。依懒于析构函数同样会导致性能上的损失。须要析构的对象在垃圾回收器上放置了剂性能毒药。当发现个对象是垃圾但是须要析构时,它还不能直接从内存上删除这个对象。首先,它要调用析构函数,但析构函数的调用不是在垃圾回收器的同个线程上运行的。取而代之的是......”。
5、“.....继续它自己的工作,从内存上移除其它的垃圾。在下个回收时,那些被析构了的对象才会再从内存上移除。图展示了三个内存使用不同的情况。注意,那些须要析构的对象会待在内存里,直到下次回收。图这个顺序展示了析构函数在垃圾回收器上起的作用。对象会在内存里存在的时间更长,须要启动另个线程来运行垃圾回收器。这用使你相信那些须要析构的对象在内存至少多生存个回收循环。但,我是简化了这些事。实际上,因为另个的介入译注其实只有个,作者是想引用回收代的问题。,使得情况比这复杂得多。回收器采用代来优化这个问题。代可以帮助来很快的标识那些看上去看是垃圾的对象。所以从上次回后开始创建的对象称为第代对象,所有那些经过次回收后还存在的对象称为第代对象。所有那些经过次或者次以上回收后还存在的对象称为第代对象。分代的目的就是用来区分临时变量以及些应用程序的全局变量......”。
6、“.....以及些全局变量很快会成为第代对象,最终成为第代对象。通过限制检测第以及第代对象来优化它的工作。每个循环都检测第代对象。粗略假设个会超过次检测来检测第代对象,而要超过次来检测所有对象。再次考虑析构函数的开销个须要析构函数的对象可能要比个不用析构函数的对象在内存里多待上个回收循环。如果它还没有被析构,它将会移到第代对象。在第代对象中,个可以生存上个循环直到下个第代集合。结束时,记得个垃圾回收器负责内存管理的托管环境的最大好处内存泄漏,其它指针的服务问题不在是你的问题。非内存资源迫使你要使用析构函数来确保清理非内存资源。析构函数会对你的应用程序性能产生些影响,但你必须使用它们来防止资源泄漏译注请注意理解非内存资源是什么,般是指文件句柄,网络资源,或者其它不能在内存中存放的资源。通过实现接口来避免析构函数在垃圾回收器上造成的性能损失......”。
7、“.....原则选择变量初始化而不是赋值语句些类经常不只个构造函数。时间长,就难得让它的成员变量以及构造函数进行同步了。最好的确保这样的事不会发生的方法就是在声明就是的时间就直接初始化,而不是在每个构造函数内进行赋值。而且你应该使用初始化器语法同时为静态的和实例的变量进行初始化。在里,当你声明个变量时就自然的构造了这个成员变量。直接赋值,忽略你最终会给添加多少个构造函数,会正确的初始化。编译器会产生些代码,使得在你的任何个构造函数调用前,都会初始化你声明的实例变量。当你添加个新的构造函数时,就给你初始化了。当你添加了个新的变量,你不用在所有的构造函数里添加初始化代码直接在声明的地方对它进行初始化就行了。同样重要的是如果你没有明确的声明任何个构造函数,编译会默认的给你添加个,并且把所有的变量初始化过程都添加到这个构造函数里。初始化器更像是个到构造函数的方便的快捷方法......”。
8、“.....初始化会在执行类型的基类的构造函数之前被执行,并且它们是按你声明的先后关系顺序执行的。使用初始化器是个最简单的方法,在你的类型里来避免使用些没有赋值的变量,但这并不是很好。下面三种情况下,你不应该使用初始化器语法。首先就是,如果你是初始化个对象为,或者为。系统默认会在你任何代码执行前,为所有的内容都初始化为。系统置的初始化是基于底层的指令,对整个内存块设置。你的任何其它置的初始化语句是多余的。编译器忠实的添加额外的指令把内存设置为。这并没有错,只是效率不高。事实上,如果是处理值类型数据,这是很不值的,两条语句都是把变量置为。第个是通过设置包含的内存来置而第二个是通过指令,这对变量会产生装箱与拆箱操作。这很要花点额外的时间参见原则。第二个低效率的是在你为个对象添加两个构造函数时会产生。你使用初始化器初始化变量,而所有的构造函数也对这些变量进行了初始化......”。
9、“.....,当你创建个新的对象时,特别指定集合的大小,你创建了两个数组列表。其中个很快成为垃圾对象。初始化器在所有的构造函数之前会执行,构造函数会创建第个数组列表。编译器产生了这个的个版本,当然这是你决不会手动写出来的。,最后个原因要把初始化放到构造函数里就是促使异常的捕获。你不能在初始化器中使用块,任何在构造时因成员变量产生的异常可能衍生到对象的外面。你无法试图在你的类里来捕获它。你应该把那些初始化代码移到构造函数里,这样你就可以捕获异常从而保证你的代码很友好参见原则。变量初始化器是个最简单的方法,在忽略构造函数时来保证成员变量被正确的初始化。初始化器在所有的构造函数之前被执行。使用这样的语法意味着当你在为后来发布的版本中添加了构造函数时,不会忘记添加恰当的初始化到构造函数里。当构造函数与初始化生成同样的成员对象时,就使用初始化器。阅读简单而且易于维护......”。
1、手机端页面文档仅支持阅读 15 页,超过 15 页的文档需使用电脑才能全文阅读。
2、下载的内容跟在线预览是一致的,下载后除PDF外均可任意编辑、修改。
3、所有文档均不包含其他附件,文中所提的附件、附录,在线看不到的下载也不会有。