《Head First Java》 知识要点(1-10章)

来源:互联网 发布:淘宝恶意退款报警5000 编辑:程序博客网 时间:2024/06/06 23:13
 

Head First Java》 知识要点(1-10章)

 

 

 

转载请注明出处:http://blog.csdn.net/CodingMouse/archive/2009/01/02/3687234.aspx 

 

    记得很早以前就买了这本《Head First Java》,然而却一定都未认真读完过,最近放假无聊就翻来看看,结果却发现里面的字句非常精妙,于是边读边整理。目前还未整理完,先将前十章的内容弄出来,全手敲出来的。因为原来是做文秘的,倒也不算麻烦。现将已整理的前10章内容给初学者作为学习参考之用。

 

*         Chapter 1 进入Java的世界(基本概念)

 

u       要点:

n         语句以分号结束。

n         程序块以{}划出范围。

n         用名称与类型声明变量。

n         等号是赋值运算符。

n         两个等号用来当等式等号运算符。

n         只要条件测试结果为真,while循环就会一直执行块内的程序。

n         boolean测试放在括号中:

while (x == 4) {}

 

*         Chapter 2 拜访对象村(类与对象)

 

u       要点:

n         面向对象设计扩展功能不需改动之前已经测试好的程序代码。

n         所有的Java程序都定义在类中。

n         类如同蓝图描述该类型的对象要如何创建。

n         对象自治,你无需在意它如何完成任务。

n         对象有已知的事物,并能执行工作。

n         对象本身已知道的事物称为实例变量,它代表对象的状态。

n         对象可执行的动作称为方法,它代表对象的行为。

n         创建类时,可能同时会需要创建独立、测试用的类。

n         类可以继承自较为抽象的类。

n         Java的程序在执行期是一组会互相交谈的对象。

 

*         Chapter 3 认识变量(primitive主数据类型和引用)

 

u       要点:

n         变量有两种:primitive主数据类型和引用。

n         变量的声明必须有类型和名称。

n         primitive主数据类型变量值是该值的字节所表示的。

n         引用变量的值代表位于堆之对象的存取方法。

n         引用变量如同遥控器,对引用变量使用圆点运算符可以如同按下遥控器按钮般地存取它的方法或实例变量。

n         没有引用到任何对象的引用变量的值为null值。

n         数组一定是个对象,不管所声明的元素是否为primitive主数据类型,并且没有primitive主数据类型的数组,只有装载primitive主数据类型的数组。

 

*         Chapter 4 对象的行为(方法操作实例变量)

 

u       要点:

n         类定义对象所知及所为。

n         对象所知者是实例变量。

n         对象所为者是方法。

n         方法可依据实例变量来展现不同的行为。

n         方法可使用参数,这代表你可以传入一个或多个值给方法。

n         传给方法的参数必须符合声明时的数量、顺序和类型。

n         传入与传出方法的值类型可以隐含地放大或是明确地缩小。

n         传给方法的参数值可以是直接指定的文字或数字(例如 2 ‘c’ 等)或者是与所声明参数相同类型的变量(还有其他东西可以传给方法,但我们的进度不不到那边)。

n         方法必须声明返回类型。使用void类型代表方法不返回任何东西。

n         如果方法声明了非void的返回类型,那就一定要返回与声明类型相同的值。

 

*         Chapter 5 超强力方法(编写程序)

 

u       极限编程(XP

极限编程(XP)是一种新型的软件开发方法论。它的构想是结合了许多种程序员真想这么做的方法而成的。XP的概念于20世纪90年代出现,并已经被从两人工作室到福特汽车等级的大企业所采用。XP的推进力来自于客户会得到他想要的、想要的时候就能够取得甚至在开发过程后期变更规格时也是如此。

 

XP是由一组被证明有效的施行方法所组成的,这些方法都是被设计来共同动作,但许多人只选择性地实行部分的XP规则。这些方法包括了:

(1)       多次经常性的小规模发布。

(2)       避免加入规格没有的功能(不管未来会用到的功能性有多诱人)。

(3)       先写测试用的程序。

(4)       正常工作上下班。

(5)       随时随地重构(refactor),也就是改善程序代码。

(6)       保持简单。

(7)       双双结伴进行工作,并经常交换伴侣(不是说那个)以便让大家都清楚全局。

 

建议阅读专门的书籍,以免一知半解地胡乱应用。

 

u       要点:

n         你的Java程序应该从高层的设计开始。

n         你通常会在创建新的类时写出下列3种东西:

伪码

测试码

真实码

n         伪码应该描述要做什么事情而不是如何做。

n         使用伪码来帮助测试码的设计。

n         实现方法之前应该要编写测试码。

n         如果知道要执行多少次,应该要使用for循环而不是while循环。

n         使用前置或后置的递增为变量加 1(比如x++)。

n         使用前置或后置的递减来对变量减 1(比如x--)。

n         使用Integer.parseInt()来取得String的整数值。

n         Integer.parseInt()只会在所给的String为数字时有作用。

n         使用break命令来提前跳出循环。

 

*         Chapter 6 使用Java函数库(认识JavaAPI

 

u       要点:

n         ArrayList是个 Java API 的类。

n         使用add()来新增ArrayList的元素。

n         使用remove()来删除ArrayList中的元素。

n         要寻找某项元素的位置,使用indexOf()

n         使用isEmpty()来判别ArrayList是否为空。

n         要取得ArrayList的大小,可以使用size()方法。

n         传统的数组可以用length这个变量取得大小。

n         ArrayList会自动地调整大小。

n         你可以用参数类型来声明数组内容的类型,例如ArrayList<Button>会声明带有Button类型元素的ArrayList

n         虽然ArrayList只能携带对象而不是primitive主数据类型,但编译器能够自动地将primitive主数据类型包装成Object以存放在ArrayList中。

n         类会用包来组织。

n         类有完整的名称,那是由包的名称与类的名称所组成的。ArrayList事实上叫做java.util.ArrayList

n         除了java.lang之外,使用到其他包的类都需要指定全名。

n         也可以在原始程序代码的最开始部分下import指令来说明所使用到的包。

 

*         Chapter 7 对象村的优质生活(继承与多态)

 

u       要点:

n         子类是extends父类出来的。

n         子类会继承父类所有public类型的实例变量和方法,但不会继承父类所有private类型的变量和方法。

n         继承下来的方法可以被覆盖掉,但实例变量不能被覆盖掉。

n         使用IS-A测试来验证继承结构的合理性。

n         IS-A关系是单方向的,河马是动物,但动物不一定是河马。

n         当某个方法在子类中被覆盖过,调用这个方法时会调用到覆盖过的版本。

n         如果类YextendsX,且类Y是类Z的父类,则Z应该能通过IS-A X的测试。

 

*         Chapter 8 深入多态(接口与抽象类)

 

u       为什么Java不支持多重继承?

    因为多重继承会有称为致命方块的问题。允许致命方块的程序语言会产生某种很糟糕的复杂性问题,因为你必须要有某种规则来处理可能出现的模糊性。额外的规则意味着你必须同时学习这些规则与观察适用这些规则的特殊状况。因此Java基于简单化的原则而不允许这种致命方块的出现。好吧,问题还是没有解决……但是Java有个解决方案,使用接口。接口解决致命方块的办法很简单:把全部的方法设为抽象的!如此一来,子类就得要实现此方法,因此Java虚拟机在执行期间就不会搞不清楚要用哪一个继承版本。因此,接口是Java中变相实现多重继承的救星!

   

u       问答:

Ø         问:

等一下!接口并不是真正的多重继承,因为你无法在它里面实现程序代码,不是吗?如果是这样,那还要接口做什么?

Ø         答:

多态、多态、多态。接口有无比的适用性,若你以接口取代具体的子类或抽象的父类作为参数或返回类型,则你就可以传入任何有实现该接口的东西。这么说吧,使用接口你就可以继承超过一个以上的来源。类可以extend过某个父类,并且实现其他的接口。同时其他的类也可以实现同一个接口。因此你就可以为不同的需求组合出不同的继承层次。

事实上,如果使用接口来编写程序,你就是在说:不管你来自哪里,只要你实现这个接口,别人就会知道你一定会履行这个合约

大部分良好的设计也不需要在抽象的层次定义出实现细节,我们所需的只是个共同的合约定义。让细节在具体的子类上实现也是很合理的。

 

u       要如何判断应该是设计类、子类、抽象类或接口呢?

Ø         如果新的类无法对其他的类通过IS-A测试时,就设计不继承其他类的类。

Ø         只有在需要某类的特殊化版本时,以覆盖或增加新的方法来继承现有的类。

Ø         当你需要定义一群子类的模板,又不想让程序员初始化此模板时,设计出抽象的类给它们用。

Ø         如果想要定义出类可以扮演的角色,使用接口。

 

u       要点:

n         如果不想让某个类被初始化,就以abstract这个关键词将它标记为抽象的。

n         抽象的类可以带有抽象和非抽象的方法。

n         如果类带有抽象的方法,则此类必定标识为抽象的。

n         抽象的方法没有内容,它的声明是以分号结束。

n         抽象的方法必须在具体的类中运行。

n         Java所有的类都是Objectjava.lang.Object)直接或间接的子类。

n         方法可以声明Object的参数或返回类型。

n         不管实际上所引用的对象是什么类型,只有在引用变量的类型就是带有某方法的类型时才能调用该方法。

n         Object引用变量在没有类型转换的情况下不能赋值给其他的类型,若堆上的对象类型与所要转换的类型不兼容,则此转换会在执行期产生异常。

类型转换的例子:Dog d = (Dog) x.getObject(aDog);

n         ArrayList<Object>取出的对象只能被Object引用,不然就要用类型转换来改变。

n         Java不允许多重继承,因为那样会有致命方块的问题。

n         接口就好像是100%纯天然抽象类。

n         interface这个关键词取代class来声明接口。

n         实现接口时要使用implements这个关键词。

例如:Dog implements Pet

n         Class可以实现多个接口。

n         实现某接口的类必须实现它所有的方法,因为这些方法都是publicabstract的。

n         要从子类调用父类的方法可以用super这个关键词来引用。

例如:super.RunReport();

 

*         Chapter 9 对象的前世今生(构造器与垃圾收集器)

 

u       要点:

n         我们关心栈与堆这两种内存空间。

n         实例变量是声明在类中方法之外的地方。

n         局部变量声明在方法或方法的参数上。

n         所有局部变量都存在于栈上相对应的堆栈块中。

n         对象引用变量与primitive主数据类型变量都是放在栈上。

n         不管是实例变量或局部变量,对象本身都会在堆上。

 

u       要点:

n         实例变量保存在所属的对象中,位于堆上。

n         如果实例变量是个对对象的引用,则引用与对象都是在堆上。

n         构造函数是个会在新建对象的时候执行的程序代码。

n         构造函数必须与类同名且没有返回类型。

n         你可以用构造函数来初始被创建对象的状态。

n         如果你没有写构造函数,编译器会帮你安排一个。

n         默认的构造函数是没有参数的。

n         如果你写了构造函数,则编译器就不会调用。

n         最好能有无参数的构造函数让人可以选择使用默认值。

n         重载的构造函数意思是有超过一个以上的构造函数。

n         重载的构造函数必须有不同的参数。

n         两个构造函数的参数必须不同。

n         实例变量用默认值,原始的默认值是 0/0.0/false,引用的默认值是null

 

u       变量的“Life”(生命周期)与“Scope”(作用域)的差别:

Ø         Life(生命周期)

只要变量的堆栈块还存在于堆栈上,局部变量就算活着。也就是说,活到方法执行完毕为止。

Ø         Scope(作用域)

局部变量的范围只限于声明它的方法之内。当此方法调用别的方法时,该变量还活着,但不在目前的范围内。执行其他方法完毕返回时,范围也就跟着回来。

 

u       变量的生命周期如何影响对象的生命周期?

Ø         除非有对对象的引用,否则该对象一点意义也没有。

Ø         如果你无法取得对象的引用,则此对象只是浪费空间罢了。

Ø         但若对象是无法取得的,垃圾收集器(GC)会知道该怎么做。那种对象迟早会葬送在GC的手上。

 

u       释放对象引用的三种方法:

    当最后一个引用消失时,对象就会变成可回收的。

      引用永久性的离开它的范围。如:

    void go() {

        Life z = new Life();  // z会在方法结束时消失

    }

      引用被赋值到其他的对象上。

    Life z = new Life();

    z = new Life();         // 第一个对象会在z被赋值到别处时挂掉

      直接将引用设定为null

    Life z = new Life();

    z = null;              // 第一个对象会在z被赋值为null时击毙

   

u       null的真相:

Ø         当你把引用设为null时,你就等于是抹除遥控器的功能。换句话说,你会拿到一个没有电视的遥控器。null是代表的字节组合(实际上是什么只有Java虚拟机才会知道)。

Ø         如果你真地按下这种遥控器上的按钮,什么事情也不会发生。但在Java上,你是不能对null引用按钮的。因为Java虚拟机会知道(这是运行期,不是编译时的错误)你期待喵喵叫,但是却没有Cat可以执行!

Ø         null引用使用圆点运算符会在执行期遇到NullPointerException这样的错误。

 

*         Chapter 10 数字很重要(数字与静态)

 

u       静态的final变量的两种初始化方法:

Ø         声明的时候:

    public class Foo {

        public static final int FOO_X = 25;

}

Ø         在静态初始化程序中:

            public class Bar {

                public static final double BAR_SIGN;

                // 下面这段程序会在类被加载时执行

                static {

BAR_SIGN = (double) Math.random();
}

            }

 

u       要点:

n         静态的方法应该用类的名称来调用,而不是用对象引用变量。

n         静态的方法可以直接调用而不需要堆上的实例。

n         静态的方法是一个非常实用的方法,它不需特别的实例变量值。

n         静态的方法不能存取非静态的方法。

n         如果类只有静态的方法,你可以将构造函数标记为private的以避免被初始化。

n         静态变量为该变量所属类的成员所共享。静态变量只会有一份,而不是每个实例都有自己的一份。

n         静态方法可以存取静态变量。

n         Java中的常量是把变量同时标记为staticfinal的。

n         final的静态变量值必须在声明或静态初始化程序中赋值:

static {

    DOG_CODE = 420;

}

n         常量的命名惯例是全部使用大写字母。

n         final值一旦被赋值就不能更改。

n         final的方法不能被覆盖。

n         final的类不能被继承。

 

u       Java中的格式化说明

    下面是一个典型的示例:

System.out.println(String.format("I have %,.2f bugs to fix.", 476578.09876));

    输出结果为:I have 476,578.10 bugs to fix.

   

Ø         格式化说明的格式:

格式化说明最多会有5个部分(不包括%符号)。下面的[]符号里面都是选择性的项目,因此只有%type是必要的。格式化说明的顺序是有规定的,必须要以这个顺序来指定。

        %[argument number][flags][width][.precision]type

Ø         格式化说明各项参数说明:

(1)       [argument number] – 如果要格式化的参数超过一个以上,可以在这里指定是哪一个;我们稍后会讨论这部分。

(2)       [flags] – 特定类型的特定选项,例如数字要加逗号或正负号。

(3)       [width] – 最小的字符数,注意:这不是总数;输出可以超过此宽度,若不足则会主动补零。

(4)       [.precision] – 精确度,注意前面有个圆点符号。

(5)       type – 一定要指定的类型标识。

 

在格式化指令中一定要给定类型,如果还要指定其他项目的话,要把类型摆在最后。

 

下面再给出一个超过一项以上的参数对示例:

  int one = 20456654;

    double two = 100567890.248907;

    String s = String.format("The rank is %,d out of %,.2f", one, two);

    System.out.println(s);

    输出结果为:The rank is 20,456,654 out of 100,567,890.25

 

Ø         关于日期时间格式化:

        都与数字有关,那日期呢?

    数值与日期时间格式化的主要差别在于日期格式的类型是用“t”开头的两个字符来表示,下面有几个范例(以下输出均为简体中文OS下的测试结果):

ü         完整的日期与时间:%tc

        示例:System.out.println(String.format("%tc", new Date()));

        输出:星期五 一月 02 13:47:09 CST 2009

ü         只有时间:%tr

        示例:System.out.println(String.format("%tr", new Date()));

        输出:01:47:09 下午

ü         周、月、日:%tA %tB %td

        示例1

Date today = new Date();

System.out.println(String.format("%tA, %tB %td", today, today, today));

        输出:星期五, 一月 02

        示例2(同上,但不用重复给参数):

Date today = new Date();

System.out.println(String.format("%tA, %<tB %<td", today));

说明:“<”这个符号是个特殊的指示,用来告诉格式化程序重复利用之前用过的参数。

           

u       操作日期:

Ø         有关操作日期的小提示:

(1)       要取得当前的日期时间就用java.util.Date,操作日期的其余功能可以从java.util.Calendar上面找。

(2)       取得继承过Calendar(抽象类)对象的方法:

Calendar cal = Calendar.getInstance();

       

Ø         运用Calendar对象:

(1)       字段会保存状态 – Calendar对象使用许多字段来表示某些事物的最终状态,也就是日期和时间。比如说你可以读取和设定它的yearmonth字段。

(2)       日期和时间可以运算 – Calendar 的方法能够让你对不同的字段作加法或减法的运算,比如说对month字段加一个月或对year减去三年。

(3)       日期与时间可以用millisecond来表示 – Calendar可以让你将日期转换微秒的表示法,或将微秒换成日期。(更精确的说法是相对于197011的微秒数),因此你可以执行精确的相对时间计算。

 

运用Calendar对象的范例(以下输出均为简体中文OS下的测试结果):

示例:

    Calendar c = Calendar.getInstance();

    c.set(2004, 1, 7, 15, 40);  // 将时间设定为20041715:40,注意月份是零基的

    long day1 = c.getTimeInMillis();  // 将目前时间转换为以millisecond表示

    day1 += 1000 * 60 * 60;

    c.setTimeInMillis(day1);  // c的时间加上一个小时

      System.out.println("new hour " + c.get(c.HOUR_OF_DAY));

      c.add(c.DATE, 35);  // 加上35天,所以c已经到了2

      System.out.println("add 35 days " + c.getTime());

      c.roll(c.DATE, 35);  // 滚动35天,注意:只有日期字段会动,月份不会动

      System.out.println("roll 35 days " + c.getTime());

      c.set(c.DATE, 1);  // 直接设定DATE的值

      System.out.println("set to 1 " + c.getTime());

输出:

    new hour 16

add 35 days Sat Mar 13 16:40:42 CST 2004

roll 35 days Wed Mar 17 16:40:42 CST 2004

set to 1 Mon Mar 01 16:40:42 CST 2004

 

 

 

到这里就先告一段落吧!等我把后面的内容读完后再整理给大家。

 

 

 

                                                         By CodingMouse

                                                         2009年1月2日

原创粉丝点击