|
|
| Java编程思想读书笔记(第5-7章) |
作者:
文章来源:
访问次数:8次
加入时间:2007年03月29日
|
|
第2章 万事万物皆对象 一.所有对象都必须由你建立 1. 存储在哪里 1. 寄存器:我们在程序中无法控制 2. stack:存放基本类型的数据和对象的reference,但对象本身不存放在stack中,而是存放在Heap中 3. Heap:存放用new产生的数据 4. Static storage:存放在对象中用static定义的静态成员 5. Constant storage:存放常量 6. NON-RAM:硬盘等永久存储空间 2. 特例:基本型别 基本类型数据存放在Stack中,存放的是数据。而产生对象时,只把对象的reference存放在stack中,用于指向某个对象,对象本身存放在Heap中。 3. Java中的数组 当你产生某个存储对象的数组时,真正产生的其实是存储reference的数组。引数组建立后,其中的每一个reference都会被自动设为null,表示“不指向任何对象”。 二.建立新的数据型别:Class 1. 数据成员和函数 1.1 基本成员的缺省值 1) 当class的某个成员属于基本型别时,即使你没有为它提供初值,Java仍保证它有一个缺省值。 2) 只有当变量身份是“class内的成员时,Java才保证为该变量提供初值。 三.函数(Mehtods),引数(arguments),返回值(return values) 1. 引数列 当引数传递的是对象时,传递的是对象的reference。 四.注解用内嵌式文档 Java提供两种注解风格:/*XXXX*/、//XXXX 第3章 控制程序流程 一.使用Java运算符 1.关系运算符 1.) 当对两个对象运用关系运算符进行比较时,比较的是object reference,如: java/lang/Integer.java.html" target="_blank">Integer n1 = new java/lang/Integer.java.html" target="_blank">Integer(3); java/lang/Integer.java.html" target="_blank">Integer n2 = new java/lang/Integer.java.html" target="_blank">Integer(3); java/lang/System.java.html" target="_blank">System.out.println(n1==n2); 结果为false,因为两个object reference(n1和n2)值是不同的 2) quals()的缺省行为也是拿referenct来比较。不过Java中的class覆写了equals方法,如: java/lang/Integer.java.html" target="_blank">Integer n1 = new java/lang/Integer.java.html" target="_blank">Integer(3); java/lang/Integer.java.html" target="_blank">Integer n2 = new java/lang/Integer.java.html" target="_blank">Integer(3); java/lang/System.java.html" target="_blank">System.out.println(n1.quals(n2));//值为true 2. 逻辑运算符 1) 只能将and、or、not施用于boolean值身上。如果逻辑运算符两边的值存在non-boolean值,将会出错,如: int test1 = 1; java/lang/System.java.html" target="_blank">System.out.println((test && 1<2);//编辑出错,test是non-boolean值 3. 位移运算符 如果所操作的位移对象是char、byte、short,位移动作发生之前,其值会先被晋升为int,运算结果会是int。 二.流程控制 1. 迭代(iteration) 1.1 逗号运算符 逗号运算符只能用于for循环的控制表达式中的initialization和step两部分中,如:for(int i=0, j=I+1; I<5; i++, j=I*2) 1.2 break和continue break表示退出循环;continue表示退出本次循环,回来循环起始位置。 1.3 label label只有放在迭代语句之前才起作用,在label和迭代语句之间插入任何语句都不会起作用。 2. Switch switch中的选择器必须是int或char型,如: float i = 2; switch ( i )//将出错,因为i不是int或char之一 3. 计算细节 1) 从float或double转为整数值,总是以完全舍弃小数的方式进行。 4. Math.random()的输出范围是[0, 1]。 第4章 初始化和清理 一.以构造函数(constructor)确保初始化的进行 如果某个class具备构造函数,Java便会在对象生成之际,使用者有能力加以操作之前,自动调用其构造函数,于是便能名确保初始化动作一定被执行。 二.函数重载(Method overloading) 1. 区分重载函数 由于只能从函数名和函数的引数列来区分两个函数,而重载函数具有相同的函数名称,所以每个重载函数都必须具备独一无二的引数列。 2. Default构造函数 1) default构造函数是一种不带任何引数的构造函数。如果你所开发的class不具任何构造函数,编译器会自动为你生成一个default构造函数。 2) 如果你自行定义了任何一个构造函数(不论有无引数),编译器就不会为你生成default构造函数。 3) 如果定义了一个class,如 class Bush{ Bush(int I){} } 当想用new Bush();来产生class的实例时,会产生错误。因为在定义class时已定义了构造函数,所以编译器就不会为class生成default构造函数。当我们用new Bush()来产生实例时,会尝试调用default构造函数,但在class中没有default构造函数,所以会出错。如: class Sundae { Sundae(int i) {} } public class IceCream { public static void main(java/lang/String.java.html" target="_blank">String[] args) { //Sundae x = new Sundae();会编译出错,无构造函数Sundae() Sundae y = new Sundae(1); } } *:在定义一个class时,如果定义了自己的构造函数,最好同时定义一个default构造函数 3. 关键字this 1) this仅用于函数之内,能取得“唤起此一函数“的那个object reference。 2) 在构造函数中,通过this可以调用同一class中别的构造函数,如 public class Flower{ Flower (int petals){} Flower(java/lang/String.java.html" target="_blank">String ss){} Flower(int petals, Sting ss){ //petals++;调用另一个构造函数的语句必须在最起始的位置 this(petals); //this(ss);会产生错误,因为在一个构造函数中只能调用一个构造函数 } } **:1)在构造调用另一个构造函数,调用动作必须置于最起始的位置 2)不能在构造函数以外的任何函数内调用构造函数 3)在一个构造函数内只能调用一个构造函数 4. Static的意义 无法在static函数中调用non-static函数(反向可行)。为什么不能呢,我们看下面的例子。 例4.2.4.1 假设能在static函数中调用non-static函数,那么(a)处就将出错。因为在没有产生Movie class实例之前,在就不存在Movie class内的name实例,而在getName()中却要使用name实例,显然的错误的。 class Movie{ java/lang/String.java.html" target="_blank">String name = “”; Movie(){} public Movie(java/lang/String.java.html" target="_blank">String name) { this.name = name; } public static java/lang/String.java.html" target="_blank">String getName() { return name; } } public class Test{ public static void main(java/lang/String.java.html" target="_blank">String[] args){ //下面两名先产生实例后再调用getName()没有问题 //Movie movie1 = new Movie(“movie1”); //String name1 = movie1.getName(); //下面一名将出错 //String name2 = Movie.getname(); (a) } } 三.清理(cleanup):终结(finalization)与垃圾回收(garbage collection) 1)你的对象可能不会被回收 只有当程序不够内存时,垃圾回收器才会启动去回收不再被使用的对象的内存空间。某个对象所占用的空间可能永远不会被释放掉,因为你的程序可能永远不会逼近内存用完的那一刻,而垃圾回收器完全没有被启动以释放你的对象所占据的内存,那些空间便会在程序终止时才一次归还给操作系统 3) 只有在采用原生函数(native methods)时,才使用finalize()。 四.成员初始化(member initialization) 1) 函数中的变量不会被自动初始化,如 void f(){ int i; i++; } 将发生编译错误,因为i没有被初始化。 2) class的数据成员会被自动初始化,具体情况如下(见P220例子): 基本型别:boolean:false、char:null(u0000)、byte:0、short:0、int:0、 long:0 、float:0、double:0 第6章 重复运用classes 一.继承(inheritance) 1. 在derived class中overriding某个函数时,只能覆写base class中的接口,即base class中的public或protected或friendly函数。如果试图overriding一个private函数,虽然编译通过,但实际上你只是在derived class中添加了一个函数。如 class Cleanser{ private void prt(){//(b) java/lang/System.java.html" target="_blank">System.out.println("Cleanser.prt()"); } } public class ExplicitStatic extends Cleanser{ public void prt(){ java/lang/System.java.html" target="_blank">System.out.println("ExplicitStatic.prt()"); } public static void main(java/lang/String.java.html" target="_blank">String[] args){ Cleanser x = new ExplicitStatic(); x.prt();//(a) } } 因为Cleanser中的prt()是private,所以不能在其derived class中被覆写。ExplicitStatic中的prt()只是ExplicitStatic中的一个函数,所以当试图在(a)处通过多态来调用prt()时,会发生错误。如果把(b)处的private去掉,则结果为 ExplicitStatic.prt() 2. Super的使用 1)通过关键字super可以调用当前class的superclass(父类)。 例6.1.1.1 class Base{ Base(){java/lang/System.java.html" target="_blank">System.out.println("Base()");} public void scrub() { java/lang/System.java.html" target="_blank">System.out.println(" Base.scrub()"); } } class Cleanser extends Base{ private java/lang/String.java.html" target="_blank">String s = new java/lang/String.java.html" target="_blank">String("Cleanser"); public void append(java/lang/String.java.html" target="_blank">String a) { s+=a; } public void dilute() { append(" dilute()"); } public void apply() { append(" apply()"); } public void scrub() { append(" scrub()"); } public void print() { java/lang/System.java.html" target="_blank">System.out.println(s); } Cleanser(){ java/lang/System.java.html" target="_blank">System.out.println("Cleanser(): " + s); } public static void testStatic(){ java/lang/System.java.html" target="_blank">System.out.println("testStatic()"); } public static void main(java/lang/String.java.html" target="_blank">String[] args){ Cleanser x = new Cleanser(); x.dilute(); x.apply(); x.scrub(); x.print(); } } public class ExplicitStatic extends Cleanser{ ExplicitStatic(){ java/lang/System.java.html" target="_blank">System.out.println("ExplicitStatic()"); } public void scrub(){ append(" Detergen.scrub()"); super.testStatic(); super.scrub();//调用的是Cleanser.scrub() } public void foam() { append(" foam()"); } public static void main(java/lang/String.java.html" target="_blank">String[] args){ ExplicitStatic x = new ExplicitStatic(); x.dilute(); x.apply(); x.scrub(); x.foam(); x.print(); java/lang/System.java.html" target="_blank">System.out.println("Test base class:"); Cleanser.main(args); testStatic(); } } 运行结果: Base() Cleanser(): Cleanser ExplicitStatic() testStatic() Cleanser dilute() apply() Detergen.scrub() scrub() foam() Test base class: Base() Cleanser(): Cleanser Cleanser dilute() apply() scrub() testStatic() 2)通过super来调用superclass中的成员时,调用的是最近成员。 例6.1.1.2 class Base{ protected java/lang/String.java.html" target="_blank">String baseS = "Base";//(a) //private String baseS = "Base"; Base(){java/lang/System.java.html" target="_blank">System.out.println("Base()");} } class Cleanser extends Base{ protected java/lang/String.java.html" target="_blank">String baseS = "Cleanser";//(b) public java/lang/String.java.html" target="_blank">String s = new java/lang/String.java.html" target="_blank">String("Cleanser"); Cleanser(){ java/lang/System.java.html" target="_blank">System.out.println("Cleanser(): " + s); } Cleanser(java/lang/String.java.html" target="_blank">String a){ java/lang/System.java.html" target="_blank">System.out.println("Cleanser(" + a + "): s = " + s ); } } public class ExplicitStatic extends Cleanser{ java/lang/String.java.html" target="_blank">String s2 = s; java/lang/String.java.html" target="_blank">String baseS = super.baseS; //(c) ExplicitStatic(){ super("ExplicitStatic"); java/lang/System.java.html" target="_blank">System.out.println("ExplicitStatic():s2 = " + s2 + ", baseS = " + baseS + "super.baseS = " + super.baseS); baseS = "ExplicitStatic"; java/lang/System.java.html" target="_blank">System.out.println("baseS = " + baseS + " , super.baseS = " + super.baseS); } public static void main(java/lang/String.java.html" target="_blank">String[] args){ ExplicitStatic x = new ExplicitStatic(); } } 结果1: Base() Cleanser(ExplicitStatic): s = Cleanser ExplicitStatic():s2 = Cleanser, baseS = Cleanser,super.baseS = Cleanser baseS = ExplicitStatic , super.baseS = Cleanser 在上面例子中,在三个class中都存在String bases实例。在ExplicitStatic中如果直接调用baseS,则实际调用的是当前类ExplicitStatic中的baseS(即(c)处的成员);如果通过super.bases来调用baseS,则调用的是离当前类ExplicitStatic最近的baseS成员,即Cleanser class中的baseS实例(即(b)处),产生的结果如结果1所示。如果把(b)处语句注释掉,则将调用Base class中的baseS,结果如结果2所示。 结果2: Base() Cleanser(ExplicitStatic): s = Cleanser ExplicitStatic():s2 = Cleanser, baseS = Base,super.baseS = Base baseS = ExplicitStatic , super.baseS = Base 3. Base class的初始化 2.1 当你产生derived class对象时,其中会包含base class子对象(subobject)。这个子对象就和你另外产生的base class对象一模一样。 2.2 通过super()可调用base class的构造函数,但必须放在构造函数的第一行,并且只能在构造函数中运用。 2.3 初始化顺序为: 1) 加载代码(.class文件) 2) 初始化class的静态成员,初始化顺序了“从里到外”,即从base class开始。 3) 在derived class的构造函数中调用base class的构造函数。 如果在derived class的构造函数中没有通过super()显式调用调用base class的构造函数,编译器会调用bass class的default构造函数并自动生成相应的调用语句,从而产生一个base class实例。如果在derived class的构造函数中通过super()显示调用了父类的构造函数,则调用所指定的构造函数。调用构造函数的调用顺序是“从里到外”。 4) 调用derived class的构造函数。 **:当base class没有default构造函数时,必须在derived class的构造函数中通过super显示调用base class的构造函数。 例:下面代码的初始化过程为: 1) 装载ExplicitStatic的代码(装载ExplicitStatic.class文件)。 2) 发现ExplicitStatic有关键字extends,装载ExplicitStatic的base class的代码(装载Cleanser.class文件)。 3) 发现Cleanser有关键字extends,装载Cleanser的base class的代码(装载Base.class文件)。 4) 初始化Base class中的静态成员。 5) 初始化Cleanser class中的静态成员。 6) 初始化ExplicitStatic class中的静态成员。 如果把(c)处的代码注释掉,那么初始化工作到此就结束了。 7) 为ExplicitStatic对象分配存储空间,并把存储空间初始化为0。 8) 在ExplicitStatic class的构造中调用super("ExplicitStatic")(在ExplicitStatic class的构造函数中显式调用父类的构造函数),试图产生一个Cleanser class实例。 9) 为Cleanser对象分配存储空间,并把存储空间初始化为0。 10) 由于Cleanser class又是继承自Base class,
|
|
|