JAVA编程思想读书笔记(1--7章)

来源:互联网 发布:路由器限速软件 编辑:程序博客网 时间:2024/06/05 18:30
学校在大一开设了JAVA的课程,但是学到的内容实在有限。此次进行《JAVA编程思想》的阅读,算是查漏补缺,也是对JAVA各个部分建立更深的理解。把读书过程中的一些细碎但自己没有掌握的知识点整理下来,便于以后复习。

1.所有类的成员基本数据类型字段都有一个默认值,除了char是null外其他都是0.
    局部变量不适用

2.为了标识类库的唯一性,JAVA希望开发者使用自己的域名反转来作为包名,如:com.baidu.myproject。

3.每一个对象都是一个类的实例,包括自己的特性和行为,通过向对象发送消息来通知他调用自己的方法。在新建对象时获得一个引用,通过这个引用发送消息。

4.访问控制有两个理由:(1)不让使用类的程序员触及那些他们不应该触及的实现部分(2)允许改变类的内部工作方法而不影响使用

5.单根继承:JAVA中的所有类都继承自Object,这样做有很多好处,所有对象都可以轻松的在堆上创建,参数传递也很方便,垃圾回收器也容易了很多。垃圾回收器是JAVA很有特色的机制,他可以自动发现对象在何时不再被使用,从而销毁他(比如通过作用域的判断)

6.泛型的意义:如果没有泛型,容器中存放的都是Object,在取出使用时需要向下转型,这样会有风险。但是通过泛型,容器知道自己存放的是什么数据类型,也就不需要转型。

7.异常处理:JAVA的异常处理就好像在程序正常执行路径外并行的处理错误的另一条路径。JAVA中的异常不能被忽略,必须被处理,处理完会返回原中断点继续执行,就像是调试校正,增强了程序的健壮性,而且强制要求开发者在可能出现异常的地方进行捕获处理。

8.数据的存储,对象存储在堆中,对象引用存储在堆栈中,常量和程序代码放在一起或者存在ROM中,其他还有完全独立于程序的永久数据。
基本类型数据比较特殊,不通过new,而是直接存放一个值,存在堆栈中。通过基本类型的包装器类可以在堆上new出一个对象。

9.方法名和参数唯一确定一个方法。

10.表示二进制数:二进制数不能直接表示,只能通过别的数据类型来转换:如Integar.toBinaryString()。得到一个二进制字符串
        表示指数:1.39E-4=1.39 * 10^(-4)   e的大小写表示的是10的指数,如果想用真正的e请使用Math的静态成员E

11.  按位运算符:操作数必须是整型,操作时把操作数看做二进制数。非:~ 一元运算符,把操作数各位取反。与: &
            两个数对齐,每个位进行与运算,生成一个二进制结果。举个例子,可以用一个数&1来判断奇偶。或: |
      移位操作符:左移<<,右移>>, 这两种都是有符号数的移位,另外右移还有一个>>>,把操作数看做无符号数。

12.逗号操作符,只在for循环的控制表达式中使用,可以把逗号连接的几条语句顺序执行,如:
            for(int i=1,j=1;i<5;i++,j--)

13.break直接跳出循环,continue跳转到下一次循环开头
        可以使用标签实现goto类似的效果。标签是一个标签名加冒号,标签后跟一个循环(while或for)
        如一个标签label1:   带标签的跳转:break label1;continue label1;
        break标签:直接跳到标签处,不执行后面的循环
        continue标签:跳到标签处,然后进入标签后面的循环(当前的下一次循环,不是重新进入)

14.switch的判断值必须是int或char

15.构造器保障初始化:必须有一个方法来保证对象在创建时得到初始化,创建和初始化不可分割。为了让编译器找到方法采用名称和类名相同,没有返回值,因为只负责初始化,不给编译器增加负担。

16.方法重载:方法重载有两个原因,一方面为了使用多种创建对象的方式必须重载构造器,另一方面对于语义相同参数不同的方法没必要使用不同的方法名。
重载方法在处理基本类型参数时,参数会寻找与自身相同类型的方法,如果找不到就进行变量提升,让自己变大,如int 变long,(char会提升到int)然后再去找,这是实际参数较小的情况。实际参数大于所有方法参数类型的时候编译器会报错,必须在传入时进行强转。

17.this关键字:this一般用于在方法中作为当前对象的引用,当我们在一个方法中只用方法名调用本对象其他方法的时候实际上编译器会自动帮我们加上这个this。this还有一个特殊用途就是当我们想在一个构造器中调用另一个构造器的时候,直接this加参数,注意这一行必须放在第一行。

18.垃圾回收器工作机制:实际上,垃圾回收器的工作机制并不是唯一的,不同的JVM有不同的处理策略。一般来说,“自适应”方式比较流行。首先明白如何判断一个对象是否存活:认为一个活的对象肯定能在堆栈和静态存储区找到他的引用。这种情况下有两种工作模式,一种是标记清扫,一种是停止复制。标记清扫指的是遍历堆栈和静态存储区的引用,每找到一个活的就进行标记,遍历完成后将未标记的进行清理。这种方式速度很慢,但是非常适合垃圾较少的状态。停止复制工作模式下程序需要暂停,将所有存活的对象复制到新的内存中进行整理。当标记清扫中对空间碎片太多,就切换到停止复制进行整理;同样,当停止复制中发现垃圾较少就切换到标记清扫。
如果我们想要显式清理,可以使用fanalize方法,但是这个方法不代表清理,使用的范围也很小,只是在清理一些垃圾回收器无法识别的资源时使用,也可以用于判断本对象被正确清理。这个方法在清理前调用。

19.初始化:对象的成员变量初始化(定义时赋值)是在构造器前执行的,静态成员变量比较特殊,只在类第一次实例化或者调用类的静态变量时(以及静态方法)调用,调用时所有静态变量都会初始化。初始化顺序是先静态后非静态

20.可变参数列表:在JAVA SE5中加入的新特性,允许方法的参数是可变长度的,如:void add(Integar......numbers)因为要求是对象所以使用了包装类,你可以直接对这个numbers数组进行遍历操作来达到效果。
但是这样会让方法重载出现风险,因为可变参数列表允许不传入任何参数,所以不传入参数调用时两个不同的重载方法有可能无法让编译器做出判断。


21.枚举:枚举的本质是一个类,但是通常只作为一个数据类型。首先需要有几个整型常量定义,然后定义enum:
public enum Fruit{
    APPLE,BANANA,ORANGE}
然后可以这样生成一个泛型实例:Fruit a=Fruit.APPLE。
这个对象可以作为正常的数据类型传入方法,与switch配合最佳:
switch(a){
    case APPLE: break;
}
直接将这个泛型实例与整型常量进行比较即可。

22.控制访问权限的原因:从应用的角度看,类库的消费者不关心类库的具体实现,没必要了解类的具体实现,也不希望客户端的代码有所修改。当类库编写者希望对代码进行重构和优化时,如果没有权限控制,就不知道客户端调用了哪些方法和变量,也就无法修改。借助访问权限控制,类库编写者只向用户提供他们需要的方法,重构也就不会影响客户端代码。

23.包:包可以看做一个类库,包的作用是指定代码中类的唯一性,通过import告知编译器这个类的所属,也可以直接用包名加类名来使用一个类,一般用作者域名反转作为前缀来保证包名的唯一性。我在开发中遇到过使用不同包的两个同名的类,这时候的处理方法是一个类直接用类名(找import的包),另一个用包名加类名使用。代码第一行的pakage也是指出本类的归属,方便在其他地方找到。包还有一个作用,影响成员的可见性。
在引用JAVA官方类库中的类的时候是非常方便的,只需要直接import,但是如果需要使用我们自定义的包中的类,就需要配置电脑的CLASSPATH。他的工作过程是这样的,借助声明的包名和类名,系统在CLASSPATH中遍历文件,找到这个包名和类名对应的.class文件(java文件编译后),然后解释器对class文件进行解释。这里要说到一个.java文件就是一个编译单元,只能包括一个public类型的类。当然我们也可以通过在编译器中引入jar包来使用。
如果我们import static 类.* 的话,就可以直接用方法名使用这个类的静态方法(工具类)
另外,同一目录下的类即使没有显示给出package,也认为是同一个包中的。

24.访问权限:
类成员的访问权限:private仅本类可见,protected包可见及子类可见,public全部可见。可以通过将构造器设置私有来禁止其他对象通过构造器创建类。默认包可见。
类的访问权限:只有默认和public,默认是仅本包内可见。也就是说最低也是包内的类可以看见这个类。


25.代码复用很重要的一个方面是类的复用,方式有组合、继承和代理。组合就是在类中使用已存在的类的实例,也就是用已存在的类生成新类。继承不必多说,子类获取父类全部数据行为。代理在JAVA中并不直接支持,只是一种复用方式,即在新类中定义和旧类同名的方法,然后在里面调用旧类对象的相关方法。这样新类也有了这个方法,通过代码复用。

26.在每一个子类对象内部都有一个父类对象,这个父类对象只能通过构造器生成,而且编译器会在子类的构造器中默认先调用父类的构造器 (无参)。如果父类没有无参构造器,子类必须在构造器第一行使用super(x)调用父类构造器并传入合适的参数。
于是我们可以得出一个更加完整的初始化顺序,首先编译器在解释编译文件的时候注意到这个类有一个父类,于是先到基类中进行static变量的初始化,然后回到子类中进行static和非static变量的初始化,然后进行构造器执行,这其中又会调用父类构造器,父类会进行非静态变量的初始化,之后子类的构造器剩余部分继续执行。

27.final关键字:
修饰成员变量的时候表示一次赋值,不可修改。基本数据类型比较好理解,修饰对象的话就表示这个引用不能再指向其他对象。但是并不能保证这个对象内部的属性不发生改变,这是JAVA无法保证的。修饰方法的参数时候效果类似,方法体中参数值不能更改,引用不能指向其他对象。
修饰方法表示不能被覆盖,针对的是子类。private修饰的方法默认自带final,这也好理解,因为只有自己能看到。
修饰一个类表示这个类不能被继承。

28.继承中的可见性:
能够被子类继承的变量和方法可见性和父类保持一致,public和protected修饰的变量和方法能够被子类拥有,子类可以直接使用变量,或者对方法进行覆盖。父类的private成员子类是没有的。这里有一个问题,如果子类对象调用继承的public方法,方法中使用了父类的私有变量,会不会出问题呢。答案是不会的,我们知道当在子类中覆盖一个方法时默认第一行是用suoer调用父类的方法,每个子类对象中都有一个父类对象,所以其实是父类对象在接收消息调用方法,也就不会有问题。

原创粉丝点击