Thinking in Java 4th chap5笔记-初始化与清理
初始化和清理1.this关键字如果有同一个类型的两个对象a和b,如何才能让这两个对象同时调用peel方法呢:如:Banana a = new Banana();Banana b = new Banana;a.peel(1);b.peel(2);如果只有一个peel方法,它如何知道是被a还是b调用呢?为了能用简便,面向对象的语法来编写代码,即"发送消息给对象";编译器做了一些幕后工作,他暗自把“所操作对象的引用”作为第一个参数传递给了peel->所以上述两个方法的调用变成了这样:a.peel(a,1),b.peel(b,1);这是内部的表示形式;虽然我们不能这样书写代码,并试图通过编译,不过这种写法的确能帮你了解实际发生的事情。如果你希望在方法内部获得对当前对象的引用,由于这个引用是编译器“偷偷”传入的,没有什么标识符可用;但为此有一个专门的关键字:this;this关键字只能在方法内部使用,表示“对调用方法的那个对象”的引用;当前方法的this引用会自动引用于同一类的其他方法->只有当需要明确指出对当前对象引用的时候,才需要使用this关键字;如需要返回当前对象的引用的时候,就常常在return语句里这样写:return this;注:有人执意将this放在每一个方法调用和字段引用前,认为这样“更清晰更明确”。但是千万别这么做,我们使用高级语言的原因之一就是它帮我们做一些事情。要是把this放在一些没有必要的地方,就会使读你程序的人不知所措,因为别人写的代码不会到处用this。遵循一种一致而直观的编程风格能节省时间和金钱.1.通过this返回对当前对象的引用,所以很容易在一条语句中对同一个对象执行多种操作;2.一些必要的地方才需要调用this3.构造器中调用构造器,this添加参数列表-产生对符合此列表的某个构造器的明确调用(除构造器之外,编译器禁止在其他任何方法调用构造器)4.解决参数名称和数据成员名称一致,数据成员采用this.的形式引用5.static方法就是没有this的方法,在static方法的内部不能调用非静态方法(这不是完全不可能,如果你传递一个对象的引用到静态方法里(静态方法可以创建其自身的对象),然后通过这个引用(和this效果相同)就可以调用非静态方法和访问非静态数据成员了。但通常要达到这样的效果,你只需写一个非静态方法即可);反过来可以;可以在没有创建对象的前提下;仅仅通过类本身调用static方法,这实际上正是static方法的主要用途;有些人认为static不是面向对象的,因为它的确具有全局函数的语义;使用static方法时,由于不存在this,所以不是通过“向对象发送消息”的方式来完成的;的确,要是在代码中出现了大量的static方法,就该重新考虑一下自己的设计了;然而static的概念有其实用之处,许多时候都用到它;对于它是否真的面向对象,留给理论家去讨论吧;2.终结清理和垃圾回收1.对象可能不被垃圾回收2.垃圾回收并不等于析构3.垃圾回收只与内存有关垃圾回收本身也有开销finalize:假定工作原理:一旦垃圾回收器准备好释放对象占用的存储空间,将首先调用finalize方法,并且在下一次垃圾回收动作发生时,才会真正的回收对象占用的内存;【不过要是“垃圾回收”没有发生的话,则无法释放;这个策略是恰当的,只要程序没有濒临存储空间用完的一刻;对象占用的空间总也得不到释放;因为垃圾回收也是有开销的】通过某种创建对象方式以外的方式为对象分配了存储空间:是由于在分配内存的时候可能使用了C语言的做法,这种做法主要发生在使用“本地”方法的情况下;本地方法是一种在Java中调用非Java代码的方式。本地方法目前只支持C/C++,但他们可以调用其他语言写的代码,所以实际上可以调用任何代码;非Java代码中,也许会调用类似C的的malloc函数系列来分配存储空间,而且除非调用了free函数,否则存储空间将得不到释放,从而造成内存泄露;当然free是C/C++的函数,所以要在finalize中用本地方法调用它;【记住:无论是垃圾回收还是终结,都不保证一定会发生。如果Java虚拟(jvm)并未面临内存耗尽的情况,它是不会浪费时间去执行垃圾回收以恢复内存的】3.Java堆模型1.一些java虚拟机的堆实现中,更像一个传送带,每分配一个新对象,就往前移动一格;对象存储空间的分配速度非常快,Java的“堆”指针只是简单的移动到尚未分配的区域;(C++的堆像一个院子,每个对象都负责管理自己的地盘,一段时间后,对象可能被销毁,但地盘必须加以重用);不过Java的堆并不完全像传送带那样工作,否则会导致频繁的内存页面调度,会显著影响性能;而垃圾回收介入之后,它工作时,一面回收空间,一面使队中的对象紧凑排列,这样“堆指针”就可以很容易移动到更靠近传送带的开始处;也就尽量避免了页面错误->通过垃圾回收器对对象重新排列,实现了一种告诉的,有无限空间可供分配的堆模型.4.垃圾回收机制:1.引用计数:垃圾回收器在含有全部对象的列表遍历,发现某个对象的引用计数为0,就是释放其占用的空间;不过对于对象之间的循环引用,则会出现“对象应该被回收,不过引用计数不为0”;对于垃圾回收器而言,定位这样的交叉引用的对象组所需的工作量极大;2.更快的模式:对任何“活”的对象,一定能最终追溯到其存活在堆栈或静态存储区之中的引用;因此,如果从堆栈和静态存储区开始,遍历所有的引用,就能找到所有活着的对象;停止-复制标记-清扫两种方式程序将暂停自适应的,分代的,停止-复制,标记-清扫式垃圾回收器3.java虚拟机许多附加技术->JIT(just in time)编译器技术->新版JDK的Java HotSpot技术6.初始化1.方法局部变量,编译时错误保证;【当然编译器可以为局部变量赋一个默认值,不过未初始化的局部变量更有可能是程序员的疏忽,所以采用默认值反而会掩盖这种失误,因此强制程序员提供一个初始值,往往可以找到程序中的bug】2.类的内部,变量定义的先后顺序决定了初始化的顺序;会在任何方法(包括构造器)被调用之前得到初始化3.静态数据初始化,无论创建多少个对象,静态数据都只占用一份存储区域->静态初始化只有在必要时才进行->4.构造器可以看成是静态方法;首次创建类对象/访问类的静态方法,静态域->载入类.class->静态初始化,只在class加载的时候初始化一次->new,在堆上为该对象分配足够的存储空间->这块存储空间请0,所有基本类型被置默认值,引用null->执行所有出现于字段定义处的初始化动作->执行构造器->5.static{},静态子句;{},实例初始化子句;www.zzzyk.com6.数组初始化int[]array= {};int[] array = new int[]{}->前者只能用在数组定义处,而后者可以传参可变参数列表,如int...args,String...args;可变参数列表使重载过程变的复杂了->如f(Integer...args);f(Long...args)->当调用f()的时候则编译出错,因为不知道该调用哪个f方法->可以给每个方法都就加上一个非可变参数->你应该总是只在方法的一个版本上使用可变参数列表,或者压根就不是用它;7.enum枚举是类,且有自己的方法;enum的名字能够倍加清楚的表明程序意欲何为的;创建enum时,编译器会自动添加一些有用的特性,如创建toString方法,很方便的显示每个enum实例的名字;还会创建ordinal方法,表示某个特定enum常量的声明顺序;static values方法,用来按照enum常量的声明顺序,产生由这些常量构成的数组;与switch是绝佳的组合;直接将所得到的类型直接拿来使用,而不必过多的考虑,将enum用作另一种创建数据类型的方式;在枚举之前,我们需要创建一个整型常量集,但是这些常量值并不会将其自身的取值限制在这个常量集的范围内,因此显的更有风险; 更难以使用;当然以前这样的枚举安全机制:(个人认为还是可以满足需求的,只不过没有一些编译器添加的有用的特性,而且序列化的时候会有问题)public class Orie补充:软件开发 , Java ,
上一个:Thinking in Java 4th chap6笔记-访问权限控制
下一个:public void doFilter(ServletRequest request, ServletResponse response,
- 更多JAVA疑问解答:
- java怎么在线读取ftp服务器上的文件内容
- 关于程序员的职业规划
- HTML和JSP矛盾吗?
- java小程序如何打包?
- java怎么split路径文件名?
- jsp+javaBean中Column 'ordersPrice' specified twice的错误
- Java TCP/IP Socket网络编程系列
- 大家来讨论一下我到底该用什么好?Swing 还是 JavaFX
- 关于Hibernate实体自身多对一的抓取问题
- 关于apache2+tomcat群集出现的问题
- spring 获取上下文问题
- SSH 导入导出excel 谁有这块的资料吗?
- Ext TreePanel 刷新问题
- springmvc 加载一个jsp页面执行多个方法 报404
- checkbox数组action怎么向页面传值