thinking in java 学习笔记5 初始化与清理

第五章 初始化与清理

 

今天是清明长假的第一天,看了自己的博客,人很少,呵呵,我想这和我第一次发布应用的情况也是一样的,但是我相信这一点随着自己的深入研究,自然会多起来,就我个人而言,第五章是这本书有趣的开始,有很多知识是我之前没有去碰过的,当然这些基础知识也相当重要,这让我想起了自己当时去面试,连很多基础的问题都不懂得回答,哎,所以说基础还是非常重要的.

 

好吧,看看今天有什么内容

 

 

 

.不安全编程

在许多c程序员忘记初始化变量,或者在使用程序库后,不记得清理,导致了元素占用一直没有释放,所以资源耗尽,导致程序出错,在java这边,很好的解决了这两个问题,而这一章书也是围绕着这两个点说的 初始化  清理

 

 

 

 

.构造器

构造器的名字,若命名为普通方法名,容易与正常方法冲突,又因为构造器是编译器的责任,故构造器的名字与类名同名(c++也是这样),若编译器探测到程序内无显式构造器,则会提供一个默认构造器,也就是无参构造器,对于java而言,创建与初始化是捆绑在一起的,   注:构造器无返回值

 

 

.方法重载

为什么需要方法重载,这样说一下程序,我记得我上软件工程选修课的时候,老师说过一句挺经典的话,程序是真实世界的反应,它不能真正帮你解决什么问题....我现在是有点感悟了,重载的意思在人类语言来说就是一个词表示多重含义,

比如看电视,看电脑,看书,重载了看这个方法,传入的参数类型不同而已,

区别重载方法的技巧,其实很简单,看他的方法签名就好了,方法签名就是方法名加参数列表(类型顺序不同,方法也不同,但是不建议这么做),thats all,有些人可能会问,返回值类型不同也可以区分啊,但是有时候你在调用有返回值的方法,但是你不需要它的返回值,例如  hello(); 你能判别这个方法是有返回值还是木有吗,呵呵,所以说以返回值判断是不行的,记得private void shit()和public void shit()这两个不是方法重载,会出错的...

 

 

.this关键字

这个this,作者是这样引出来的,a.peel(1),b.peel(2),对于这两个对象调用peel方法,怎么知道是哪个对象调用呢,其实编译器做了一些幕后工作,就是将该对象的引用作为第一参数传入到方法 故a.peel(a,1)

 

那么this是什么,我个人的平时用法就是this就是当前对象的引用,书上是这么说的,在方法内部获得对当前对象的引用,若在同一个类的方法内调用其他方法,可以不写this,this会自动应用

 

this应用的地方,1.引用成员变量,例如x.name;可以写成this.name

2.在构造器中调用构造器constructor(){this(“hello”);} 且必须写在第一句 注:在构造器外不能调用构造 器,this不能用于两个构造器

3.返回对象的值,可以用 return this;

注:静态方法内不能用this

 

 

.static

statci 方法内部不能调用非静态方法(对象引用的例外)与变量,非静态方法可以调用static方法与变量

 

 

.清理 垃圾回收器

这是一块比较大得内容,在下面的引用网络那里会详细研究

 

 

.初始化

我觉得是这一章最难懂的,

1.成员初始化

局部变量必须初始化,类变量可以不用(系统自动初始化)

 

2.构造器初始化

先初始化变量,在初始化构造器,java编译器为了安全起见

 

3.静态数据的初始化

static不能用于局部变量,这是真的,的确会出错

static数据最先初始化

 

.显示的静态初始化:后于变量,前于方法

1.static{}首次访问类的静态成员或方法,都会触动到static静态块的调用

2.首次生成类的对象时会调用,要注意是首次

 

.数组初始化

例如int【】 a

数组是一个对象

length属性,这是数组的固有成员,java数组内置边界检查,性能降低,但是安全性大大提高

Java中数组下标从0开始

在创建数组时,允许使用变量作为数组长度

Autoboxing:对于一个包装类类型的数组,可以直接对每个元素赋值上相应的基本数据类型

 

 

.可变参数列表

就是传说中的String... str应用于参数个数或者类型未知的场合

 

<!--[if !supportLists]-->u              <!--[endif]-->固定参数与可变参数的结合

<!--[if !supportLists]-->u              <!--[endif]-->可变参数列表的重载

<!--[if !supportLists]-->u              <!--[endif]-->非重载的情况,可变参数列可以输入空参数;有重载的情况不能输入空参数

 

 

.enum类型

 

没什么好讲的这个,这个以后再聊

 

这一章是我学得最累的,太多东西需要记了,哎

 

 

 

 

 

 

 

还有几点没有明白的地方,1.初始化顺序,比如说静态块什么的,还有构造器,main方法,他们的执行顺序是怎么样的

2.可变参数列表,类型可以使随便一个类的类型吗,比如我有一个dog类,参数可以是dog... d

3.a类调用b类的c方法来改变a类中int d变量的值,为什么不成功

4构造器为什么可以使用非静态方法或者变量,有些书说构造器不是静态方法...

 

 

针对以上问题,我特地去问了老师,查了资料,也弄明白了差不多

 

 

1.初始化顺序是这样的静态变量 静态初始化块 变量 初始化块 构造器  静态方法 普通方法,注:main方法是程序的入口,但是没有生成对象的,只是调用了main方法而已

注:若是父类和子类,那么顺序是这样的:

父类--静态变量 

父类--静态初始化块 
子类--静态变量 
子类--静态初始化块 
父类--变量 
父类--初始化块 
父类--构造器 
子类--变量 
子类--初始化块 
子类--构造器 

 

 

 

2.我个人觉得是什么类型都可以吧,应该就和普通参数一样,不同的地方就是因为它长度可以变化..这一点不确定.

注:我认为基本类型是为了兼容c而出现的,听说java 9将不会有基本类型,总之可以说object是类的老祖宗,但是和基本类型这一部分是分开的,基本类型不是object的子类...

 

 

3.其实是一个很基础的问题,呵呵,基础不扎实我,因为java的参数传递都是以传值的方式,所以传入的是a的copy,若是基本类型,则传入的是其copy,那么肯定就无法改变啦,若是引用,传入的是引用的copy,那么意思就是指向同一个地方,那么就可以改变,所以说要改变可以使用基本类型的包装类

 

 

4.我觉得构造器虽然是静态方法,但它和具体对象相关,所以可以访问普通成员变量和非静态方法,这是老师给我的答复,不过针对网上说构造器不是静态方法,这一点待以后再讨论,有想法的同志可以留回复,大家一起讨论

 

http://blog.sina.com.cn/s/blog_6fb65ce90100oy76.html

 

 

 

 

 

 

 

 

 

 

 

 

 

注:java的垃圾回收器 引用网络资源http://www.cnblogs.com/laoyangHJ/articles/java_gc.html

这篇写得很详细,可惜图挂了

 

垃圾收集GC(Garbage Collection)是Java语言的核心技术之一,之前我们曾专门探讨过Java 7新增的垃圾回收器G1的新特性,但在JVM的内部运行机制上看,Java的垃圾回收原理与机制并未改变。垃圾收集的目的在于清除不再使用的对象。GC通过确定对象是否被活动对象引用来确定是否收集该对象。GC首先要判断该对象是否是时候可以收集。两种常用的方法是引用计数和对象引用遍历。

引用计数收集器

引用计数是垃圾收集器中的早期策略。在这种方法中,堆中每个对象(不是引用)都有一个引用计数。当一个对象被创建时,且将该对象分配给一个变量,该变量计数设置为1。当任何其它变量被赋值为这个对象的引用时,计数加1(a = b,则b引用的对象+1),但当一个对象的某个引用超过了生命周期或者被设置为一个新值时,对象的引用计数减1。任何引用计数为0的对象可以被当作垃圾收集。当一个对象被垃圾收集时,它引用的任何对象计数减1。

优点:引用计数收集器可以很快的执行,交织在程序运行中。对程序不被长时间打断的实时环境比较有利。

缺点: 无法检测出循环引用。如父对象有一个对子对象的引用,子对象反过来引用父对象。这样,他们的引用计数永远不可能为0.

跟踪收集器

早期的JVM使用引用计数,现在大多数JVM采用对象引用遍历。对象引用遍历从一组对象开始,沿着整个对象图上的每条链接,递归确定可到达(reachable)的对象。如果某对象不能从这些根对象的一个(至少一个)到达,则将它作为垃圾收集。在对象遍历阶段,GC必须记住哪些对象可以到达,以便删除不可到达的对象,这称为标记(marking)对象。

下一步,GC要删除不可到达的对象。删除时,有些GC只是简单的扫描堆栈,删除未标记的未标记的对象,并释放它们的内存以生成新的对象,这叫做清除(sweeping)。这种方法的问题在于内存会分成好多小段,而它们不足以用于新的对象,但是组合起来却很大。因此,许多GC可以重新组织内存中的对象,并进行压缩(compact),形成可利用的空间。

为此,GC需要停止其他的活动活动。这种方法意味着所有与应用程序相关的工作停止,只有GC运行。结果,在响应期间增减了许多混杂请求。另外,更复杂的 GC不断增加或同时运行以减少或者清除应用程序的中断。有的GC使用单线程完成这项工作,有的则采用多线程以增加效率。

一些常用的垃圾收集器

(1)标记-清除收集器

这种收集器首先遍历对象图并标记可到达的对象,然后扫描堆栈以寻找未标记对象并释放它们的内存。这种收集器一般使用单线程工作并停止其他操作。并且,由于它只是清除了那些未标记的对象,而并没有对标记对象进行压缩,导致会产生大量内存碎片,从而浪费内存。

(2)标记-压缩收集器

有时也叫标记-清除-压缩收集器,与标记-清除收集器有相同的标记阶段。在第二阶段,则把标记对象复制到堆栈的新域中以便压缩堆栈。这种收集器也停止其他操作。

(3)复制收集器

这种收集器将堆栈分为两个域,常称为半空间。每次仅使用一半的空间,JVM生成的新对象则放在另一半空间中。GC运行时,它把可到达对象复制到另一半空间,从而压缩了堆栈。这种方法适用于短生存期的对象,持续复制长生存期的对象则导致效率降低。并且对于指定大小堆来说,需要两倍大小的内存,因为任何时候都只使用其中的一半。

 (4) 增量收集器

增量收集器把堆栈分为多个域,每次仅从一个域收集垃圾,也可理解为把堆栈分成一小块一小块,每次仅对某一个块进行垃圾收集。这会造成较小的应用程序中断时间,使得用户一般不能觉察到垃圾收集器正在工作。

(5)分代收集器

复制收集器的缺点是:每次收集时,所有的标记对象都要被拷贝,从而导致一些生命周期很长的对象被来回拷贝多次,消耗大量的时间。而分代收集器则可解决这个问题,分代收集器把堆栈分为两个或多个域,用以存放不同寿命的对象。JVM生成的新对象一般放在其中的某个域中。过一段时间,继续存在的对象(非短命对象)将获得使用期并转入更长寿命的域中。分代收集器对不同的域使用不同的算法以优化性能。

并行收集器

并行收集器使用某种传统的算法并使用多线程并行的执行它们的工作。在多CPU机器上使用多线程技术可以显著的提高java应用程序的可扩展性。

最后,贴出一个非常简单的跟踪收集器的例图,以便大家加深对收集器的理解:

跟踪收集器的例图

跟踪收集器图例

使用垃圾收集器要注意的地方

下面将提出一些有关垃圾收集器要注意的地方,垃圾收集器知识很多,下面只列出一部分必要的知识:

(1)每个对象只能调用finalize( )方法一次。如果在finalize( )方法执行时产生异常(exception),则该对象仍可以被垃圾收集器收集。

(2)垃圾收集器跟踪每一个对象,收集那些不可触及的对象(即该对象不再被程序引用 了),回收其占有的内存空间。但在进行垃圾收集的时候,垃圾收集器会调用该对象的finalize( )方法(如果有)。如果在finalize()方法中,又使得该对象被程序引用(俗称复活了),则该对象就变成了可触及的对象,暂时不会被垃圾收集了。但是由于每个对象只能调用一次finalize( )方法,所以每个对象也只可能 "复活 "一次。

(3)Java语言允许程序员为任何方法添加finalize( )方法,该方法会在垃圾收集器交换回收对象之前被调用。但不要过分依赖该方法对系统资源进行回收和再利用,因为该方法调用后的执行结果是不可预知的。

(4)垃圾收集器不可以被强制执行,但程序员可以通过调研System.gc方法来建议执行垃圾收集。记住,只是建议。一般不建议自己写System.gc,因为会加大垃圾收集工作量。

详解Java GC的工作原理

概要: JVM内存结构由堆、栈、本地方法栈、方法区等部分组成,另外JVM分别对新生代和旧生代采用不同的垃圾回收机制。

1. 首先来看一下JVM内存结构,它是由堆、栈、本地方法栈、方法区等部分组成,结构图如下所示。

 

JVM内存组成结构

 

1)堆

所有通过new创建的对象的内存都在堆中分配,其大小可以通过-Xmx和-Xms来控制。堆被划分为新生代和旧生代,新生代又被进一步划分为Eden和Survivor区,最后Survivor由FromSpace和ToSpace组成,结构图如下所示:

 

JVM内存结构之堆

 

新生代。新建的对象都是用新生代分配内存,Eden空间不足的时候,会把存活的对象转移到Survivor中,新生代大小可以由-Xmn来控制,也可以用-XX:SurvivorRatio来控制Eden和Survivor的比例旧生代。用于存放新生代中经过多次垃圾回收仍然存活的对象

2)栈

每个线程执行每个方法的时候都会在栈中申请一个栈帧,每个栈帧包括局部变量区和操作数栈,用于存放此次方法调用过程中的临时变量、参数和中间结果

3)本地方法栈

用于支持native方法的执行,存储了每个native方法调用的状态

4)方法区

存放了要加载的类信息、静态变量、final类型的常量、属性和方法信息。JVM用持久代(PermanetGeneration)来存放方法区,可通过-XX:PermSize和-XX:MaxPermSize来指定最小值和最大值。介绍完了JVM内存组成结构,下面我们再来看一下JVM垃圾回收机制。

2. JVM垃圾回收机制

JVM分别对新生代和旧生代采用不同的垃圾回收机制

新生代的GC:

新生代通常存活时间较短,因此基于Copying算法来进行回收,所谓Copying算法就是扫描出存活的对象,并复制到一块新的完全未使用的空间中,对应于新生代,就是在Eden和FromSpace或ToSpace之间copy。新生代采用空闲指针的方式来控制GC触发,指针保持最后一个分配的对象在新生代区间的位置,当有新的对象要分配内存时,用于检查空间是否足够,不够就触发GC。当连续分配对象时,对象会逐渐从eden到survivor,最后到旧生代,

用javavisualVM来查看,能明显观察到新生代满了后,会把对象转移到旧生代,然后清空继续装载,当旧生代也满了后,就会报outofmemory的异常,如下图所示:

 

outofmemory的异常

 

在执行机制上JVM提供了串行GC(SerialGC)、并行回收GC(ParallelScavenge)和并行GC(ParNew)

1)串行GC

在整个扫描和复制过程采用单线程的方式来进行,适用于单CPU、新生代空间较小及对暂停时间要求不是非常高的应用上,是client级别默认的GC方式,可以通过-XX:+UseSerialGC来强制指定

2)并行回收GC

在整个扫描和复制过程采用多线程的方式来进行,适用于多CPU、对暂停时间要求较短的应用上,是server级别默认采用的GC方式,可用-XX:+UseParallelGC来强制指定,用-XX:ParallelGCThreads=4来指定线程数

3)并行GC

与旧生代的并发GC配合使用

旧生代的GC:

旧生代与新生代不同,对象存活的时间比较长,比较稳定,因此采用标记(Mark)算法来进行回收,所谓标记就是扫描出存活的对象,然后再进行回收未被标记的对象,回收后对用空出的空间要么进行合并,要么标记出来便于下次进行分配,总之就是要减少内存碎片带来的效率损耗。在执行机制上JVM提供了串行GC(SerialMSC)、并行GC(parallelMSC)和并发GC(CMS),具体算法细节还有待进一步深入研究。

以上各种GC机制是需要组合使用的,指定方式由下表所示:

 

GC机制组合使用

 

 

 

java 美女5   最喜欢的美女

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
《Thinking in Java》是一本经典的Java编程入门教材,通过阅读该书可以系统地学习Java编程的基础知识和高级概念。阅读过程中,我结合自己的学习体验和实践,进行了详细的学习笔记。 首先,该书从基础语法开始介绍,包括数据类型、控制语句、数组等。对于初学者来说,这些基础知识是最基本的,通过书中的示例代码和解析,我能够更好地理解这些概念和语法规则。 其次,书中对面向对象编程进行了深入的讲解。通过学习面向对象的思想,我明白了类、对象、继承、多态等概念的含义和使用方法。同时,书中还讲解了接口、内部类、异常处理等较为高级的概念,极大地拓宽了我的Java知识面。 另外,该书还介绍了Java的常见类库和工具,如字符串操作、集合框架、输入输出、线程等。这些内容对于实际开发非常有用,而且书中的示例代码也能帮助我更好地理解和应用这些类库和工具。 此外,该书通过大量的实例和案例,生动地展示了Java编程的实战应用。这些实例涵盖了各种不同的应用场景,从简单的程序到复杂的项目,都有所涉及。通过分析这些实例,我不仅可以学习到实际编程的技巧,还能提高自己的解决问题的能力。 总的来说,读完《Thinking in Java》后,我对Java编程有了更深入的理解和掌握。通过学习笔记的整理,我不仅复习了各个知识点,还加深了对这些概念的理解。希望这份学习笔记能够帮助到其他想要学习Java的同学,让他们能够更快地入门和掌握这门编程语言。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值