Thinking in Java 学习笔记 一

继承在面向对象中如此重要,以至于经常被高度强调,新手往往有这样的印象:处处使用继承。这会导致难以使用并过分复杂的设计,实际上建立新类时,应该首先考虑组合,因为它更为简单清晰。

两种方式导致基类与子类的差别:在子类中增加新的方法、使子类和基类之间产生差异的方法(override)。

单根继承。是否所有类都继承自单一的类,java的答案是yes,终极的类为Object。

Java并没有赋予程序员销毁对象的权力,java完全采用了动态内存分配方式,采用垃圾回收器设计处理内存释放问题。

存储数据之处:

1)寄存器,不同于C/C++,java没有提供直接控制使用寄存器的方法。

2)堆栈 。位于通用RAM中,通过堆栈指针得到支持,向下分配,向上则为释放,仅次于寄存器。Java系统必须知道其中数据的确切生命周期,以便上下移动(约束了灵活性),所以某些Java数据存在其中,但对象并不在。

3)堆。一种通用的内存池(RAM中),存放着所有Java对象。不同于堆栈之处:编译器不需要知道数据将存活多久,当需要对象时,new自动在堆里分配存储。灵活性的代价:用堆分配清理要比堆栈消耗更多时间。

4)常量存储。常量通常直接放在程序代码内部,不被改变。在嵌入式系统中,又是放在ROM中。

5)非RAM存储。持久化对象,不受程序控制,如数据库等。

Java中的数组。为了安全性,java的数组与C/C++直接使用内存块不同,确保初始化,而且不能在范围之外访问(编译时报错,C/C++是可以访问,然后运行报错),初始化时有一个特定的值,拥有自己的关键字null

基本类型默认值(未初始化):boolean false,char ‘\u0000’(null),byte (byte)0,short (short)0,int 0,long 0L,float 0.0f,double 0.0d 这些基本字段的初始化仅限于类中属性,对局部变量并不初始化,而是与C/C++一样(任意值)。

对于未初始化,Java视为错误,而C++仅视为警告。

作用域,将一个较大的作用域的变量隐藏起来的做法,在java中是行不通的,即不能在小作用域中再次声明大作用域中已有的变量。另外java对象不具备和基本类型一样的生命周期 ,在作用域结束后,无法访问对象,但其并没有销毁,而是继续存在于内存中。等待垃圾回收器处理。

Java对类库,命名空间的引用使用倒置,如org.apache.*

只有用了new来创建,数据存储空间才被分配。

Java流程跳转中除了continue和break的直接使用外,还提供了label的使用,有点类似于C中的goto了;先标注一个label1:(冒号结尾),continue label1和break label1还是回到label入口以及终止迭代(label和当下的,两重)

JAVA构造的问题:没有构造器的时候,编译器将替你制造一个默认构造器 (无参数,内容不清楚),如果有了一个及以上的构造器 ,不再合成。

对于方法的调用:如Class a;a.b(c) ;内部表示为Class.b(a,c);

this的使用,不必过分使用this仅在需要的时候使用它,便于阅读。this可以用于构造器间的调用,如在一个构造器中使用this(i) 即可调用相应参数的constructor,但只能使用给一个。在类的内部,对于方法,其实编译器会默认加上this,而static就是没有this的方法。

Finalize()一旦垃圾回收器决定释放该对象,在释放前调用这个方法。如一个对象为circle,当他被创建的时候画到了屏幕上,那么如果不明确让它擦除,它可能永远得不到清理,在finalize中加入清理就可以了,一旦垃圾回收,就会清理(如果不回收,也不会清理)。Finalize一般的用途是清理通过创建对象外的方式分配空间的存储空间(正常的创建方式由垃圾回收处理)

对于局部变量,C++的销毁动作发生于{ }结束的时候(作用域),而对于用new创建的对象使用delete删除(调用相应析构),一旦忘了,那么永远不析构,内存泄露。Java不允许创建局部变量,只能用new创建 。但是却没有delete(因为有了垃圾回收器……)。如果JVM并未面临内存耗尽的情形,它是不会浪费时间去执行垃圾回收的恢复内存的……

为类中成员变量赋值,在声明的时候就可以了;在C++中这么做确实无效的,尽管很多新手都是这么做的~

构造器初始化可以灵活用于变量初始赋值,但是要牢记:无法阻止自动初始化的运行 ,即对于一个int,constructor中赋值为7,但其仍然是先置0,再赋值为7。散布在类中各个变量会在constructor调用前逐个初始化。

Static变量只会初始化一次,发生在类的第一个对象创建的时候(顺序上先于一般变量初始化),也就是在class文件第一次被加载的时候。

Constructor虽然没有显式的表明,其实也是静态方法 。New使用创建对象时,分配中间清零,分配数据类型的默认初始值:数字为0,布尔(false)和字符相同,引用被设置为null。

在类中,static的域static{ },其中的语句在class载入时调用一次,其实同constructor,对于类中没有static声明的,仅为{ }内的语句,则每次一个对象实例化的时候都执行一遍。(这两个一般用于static与非static对象的初始化)

Java中定义数组可以用int[] a或者int a[],含义相同(不知道编译的时候都换成哪种?),后一种是C++的习惯,前一种更为达意,即一个整形数组变量——a。编译器不允许指定数组的大小,这样声明也没有给对象分配空间,你拥有的仅仅只是一个引用。数组初始化通过{}内赋值完成,空间分配同new。数组有默认成员变量length,超出这个边界——exception,而非如C++容忍访问内存。数组通过new后,仍然只是一个引用数组,只有当创建的对象赋给引用,初始化才算结束。

对于对象的print行为,如果没有定义toString访问,默认打印类名@地址。

enum枚举这个类看起来是一种新的数据类型,实际只是在产生了某些编译器行为,很大程度上你可以将它当做其他类来处理。事实上确实有自己的方法如ordinal、toString。

访问控制(隐藏具体实现)与“最初的实现并不恰当”有关 。但是修改代码面临许多的压力,在面向对象设计中考虑:“如何把变动的事物与不变的事物分离开来”。这种观念的体现之一就是类库。这一目标通常可以通过约定来实现。public、protected、private的出现也是为了明确开放的(通常意味很少变动或不变的)、封闭的(内部改动不影响功能)、继承。Package与默认权限则是将类捆绑为一个组件。Package代表了组件的概念,对于类的定位也有好的作用,这样的命名规则也为访问控制提供了支持。

Java解释器的运行过程:寻找环境变量CLASSPATH,查找.class文件的根目录。从根目录开始,解释器将获得的包的名称中的点号改为反斜杠,已CLASSPATH为根产生一个路径名称(根据操作系统的不同,a.b.c将解析为a\b\c或a/b/c)。

对于protected变量,继承来说,包A中的类继承了包B中的类,那么子类同样只有自己所在包的包权限。

类本身只有两种权限:public与默认的包访问权限。

有关public类的一些限制:对于每一个编译单元(文件),只能有一个public类,并且类的名称必须完全与编译单元的名称相同 ,不然会得到编译错误。当然编译单元中不带public类也是可以的。

复用类的概念就是,继承、组成。组成指的就是在一个类中引用另一个类。通常对于继承而言,最好将子类中的方法声明为public(而非暧昧的默认包权限),因为继承常常发生于不同的包之间。Java会自动在子类的构造器中插入对基类构造器的条用,确保基类的初始化 。如果基类没有默认构造器,在子类中直接调用带参数的构造器(必须在其中增加对基类构造的调用,不然要报错)。编译器虽然强制要求去初始化基类,但是却并不监督将成员变量也初始化,这点必须自己注意。

复用的第三种关系为代理,Java没有提供直接支持(为什么),这个介于继承与组合间的中庸之道。(这货貌似是设计模式吧,貌似~~)

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值