已阅读5页,还剩27页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第一章Smalltalk 的五大基本特征 Alan Kay 总结了Smalltalk 的五大基本特征。这是第一种成功的面向对象程序设计语言,也是Java 的基础语言。通过这些特征,我们可理解“纯粹”的面向对象程序设计方法是什么样的:(1) 所有东西都是对象。可将对象想象成一种新型变量;它保存着数据,但可要求它对自身进行操作。理论上讲,可从要解决的问题身上提出所有概念性的组件,然后在程序中将其表达为一个对象。(2) 程序是一大堆对象的组合;通过消息传递,各对象知道自己该做些什么。为了向对象发出请求,需向那个对象“发送一条消息”。更具体地讲,可将消息想象为一个调用请求,它调用的是从属于目标对象的一个子例程或函数。(3) 每个对象都有自己的存储空间,可容纳其他对象。或者说,通过封装现有对象,可制作出新型对象。所以,尽管对象的概念非常简单,但在程序中却可达到任意高的复杂程度。(4) 每个对象都有一种类型。根据语法,每个对象都是某个“类”的一个“实例”。其中,“类”(Class)是“类型”(Type)的同义词。一个类最重要的特征就是“能将什么消息发给它?”。(5) 同一类所有对象都能接收相同的消息。这实际是别有含义的一种说法,大家不久便能理解。由于类型为“圆”(Circle)的一个对象也属于类型为“形状”(Shape)的一个对象,所以一个圆完全能接收形状消息。这意味着可让程序代码统一指挥“形状”,令其自动控制所有符合“形状”描述的对象,其中自然包括“圆”。这一特性称为对象的“可替换性”,是OOP 最重要的概念之一。有人强调“类型”决定了接口,而“类”是那个接口的一种特殊实现方式。接口每一个对象都需要接受和“发送”信息,“接口”(Interface)规定了可对一个特定的对象发出哪些请求。接口是为了实现方案的隐藏。好处:、防止程序员接触不该接触的东西(不需要接触)、使得库的设计人员可以在不影响程序员的情况下修改内部结构。如同公共汽车一样。我们不知道他的行驶路线,我们只知道他可以到达我们要去的目的地。即使路线修改了,我们仍然不用担心,因为我们知道,她可以到达我们要去的地方,而路线或许不同了。封装java的3个显示关键字和1个默认关键字public (公共的)所有人都可以用private(私有的)只有自己可以用protected(受保护的)自己和自己的子女可以用默认的friendly(友好的)没有显示说明时,默认的。在同一个Package下可以用。(包装访问)组织与继承组织比继承更清晰简单灵活。组织就是类之间的相互包含。继承是创建一个新类,它拥有extends(关键字)父类的部分成员(除private和构造函数)。这个新类与父类有相同的类型,尽管具体的成员不同(子类扩展)。多态性(Polymorphism)我们来看这个函数void doStuff(Shape s) s.erase(); / . s.draw();这个函数可与任何“几何形状”(Shape)通信,所以完全独立于它要描绘(draw)和删除(erase)的任何特定类型的对象。如果我们在其他一些程序里使用doStuff()函数:Shape c = new Circle();Shape t = new Triangle();Shape l = new Line();doStuff(c);doStuff(t);doStuff(l);凡是doStuff()能发给一个Shape的消息,Circle也能接收。因为他们是同一类型。Circle继承了Shape。编译器在编译的时候并不知道自己要操作的准确类,是Circle还是Triangle,在执行的时候才由编译器和系统负责对细节控制,使之得到我们期望的结果。这就是多态性。(中用Virtual)这种方法称为“动态绑定”。抽象类当一个类只希望为自己的衍生类提供接口时,可用abstract。抽象方法也可以用关键字abstract描述。继承抽象类的方法如果不实现其中的抽象方法,那么它也会变成抽象类。抽象类不能被实例化。interface 关键字延伸了抽象类的概念。完全禁止所有函数的定义。对象的创建和存在时间对象的回收对于静态的对象无需考虑,编译器已经做好了。动态的可以手动释放,如C+ 也可以利用GC有JRE所提供的 “垃圾收集器”将为你完成。Delphi中默认没有垃圾收集器,但可以安装。java中可以强迫垃圾回收,如:System.gc() ,Runtime.gc(),当然还有finalize()方法,使用System.runFinalization集合于继承器(迭代器)集合也称为“容器”。他提供读写操作。如“推”(Push),“添加”(Add)等相似操作。对集合可以用继承器(Iterator)来操作他们。例:Iterator iter = c.iterator();while(iter.hasNext()Object obj = iter.next();do Something with obj;“容器”的种类:为适应不同的需要。如:集、队列、散列表、树、堆栈等。例如:Vector和List的区别。他们拥有一致的接口和外部行为。然而相同的操作对他们却有不同开销。Vector的随机访问是等时的。而List则要付出更多的不同开销,远一点的对象可能要长的时间。我们所要记住的是集合是一个用来置放对象的储藏所,我们关心的是他是否能满足我们的需要,而无需关心她的内部结构设计。单根结构所有的类都继承一个终极基础类:Object单根结构的优点:、单根结构中的所有对象都有一个通用的接口,他们最终都属于相同类型。、实现类似中的模版功能。、单根结构中的所有对象都可以保证拥有一些特定的功能。一个单根结构,加上所有对象都在内存堆中创建,大大简化了参数传递。方便实现垃圾收集器。第二章用引用操纵对象操纵对象的标示符实际是指向对象的“句柄”(Handle)。电视(对象)与遥控器(句柄)的关系。创建一个句柄,如String s;指向一个对象 (初始化)S = asdf ;创建一个对象并用一个句柄操作String s = new String(asdf);所有对象都必须创建。有六个地方都可以保存数据:(1)寄存器:由编译器分配 这是速度最快的地方,数据位于和其他所有方式都不同的一个地方:处理器的内部.不过,寄存器的数量十分有限,所以寄存器是根据需要由编译器分配.我们对此没有直接的控制权,也不可能在自己的程序里找到寄存器存在的任何迹象.(2)堆栈:保存对象的句柄,而不是对象本身堆栈位于常规RAM(随机访问存储器)内,但可通过它的“堆栈指针”获得处理的直接支持.这是一种特别快.特别有效的数据保存方式,仅次于寄存器.创建程序时, java编译器必须准确地知道堆栈内保存的所有数据的“长度”以及“存在时间”.这是由于它必须生成相应的代码,以便向上 与向下移动指针.这一限制无疑影响了程序的灵活性,所以尽管有些java数据要保存在堆栈里特别是对象句柄,但java 对象并不放到其中. (3)堆: 使用“new”关键字。保存对象,可以事先不知道此对象的信息一种常规用途的内存池(也在ram区域)其中保存java对象.与堆栈不同,“内存堆”或“堆”(heap)最吸引人的地方在于编译器不必知道要从堆里分配多少存储 空间,也不必知道存储的数据要在堆里停留多长的时间.因此,用堆保存数据时会得到更大的灵活性.要求创建一个对象时, 只需用new命令编制相关的代码即可.执行这些代码时,会在堆里自动进行数据的保存.当然,为达到这种灵活性,必然会 付出一定的代价:在堆里分配存储空间时会花掉更长的时间 (4)静态存储:这儿的“静态”(static)是指“位于固定位置”(尽管也在ram里)程序运行期间,静态存储的数据将随时等候调用.可用static关键字指出一个对象的特定元素是静态的.java对象本身永远 都不会置入静态存储空间. (5)常数存储常数值通常直接置于程序代码内部.这样做是安全的,因为它们永远都不会改变.有的常数需要严格地保护, 所以可考虑将它们置入只读存储器(rom). (6)非ram存储若数据完全独立于一个程序之外,则程序不运行时仍可存在,并在程序的控制范围之外.其中两个最主要的例子便是“流式对 象”与“固定对象”.对于流式对象,对象会变成字节流,通常会发给另一台机器.而对于固定对象,对象保存在磁盘中.即使程序中止运行,它们仍可保持自己的状态不变.对于这些类型的数据存储,一个特别有用的技巧就是它们能存在于其他媒体中.使用栈比堆快,因为栈是存放句柄的,只需要创建固定长度,所以比较快。而堆是任意长度,所以慢。特殊类型,主要类型 主类型 大小最小值 最大值 封装器类型 默认值 boolean Boolean false char 16-bit Unicode-0 Unicode216-1 Character null byte 8-bit -128 +127 Byte (byte)0 short 16-bit -215 +215-1 Short (short)0 int 32-bit -231 +231-1 Integer 0 long 64-bit -263 +263-1 Long 0L float 32-bit IEEE754IEEE754 Float 0.0f double 64-bit IEEE754IEEE754 Double 0.0d void Void主类型保存在堆栈中,封装器类型则保存在堆中高精度数字BigInteger 和 BigDecimal(封装器类型)BigInteger支持任意精度的整数BigDecimal支持任意精度的定点数字(币值)数组:java编译时系统会自动进行检查。以小的开销换取安全性(数组越界问题)作用域大括号内创建新的数据类型:类Class ATyepName 创建这种类型的对象:ATyepName a = new AtyepName();方法的基本组成部分:名字、参数、返回值和方法体。构建一个Java程序名字可视性为了给一个类库生成不会与其它名字混淆的名字,JAVA采用了与Internet域名相似的指定符运用其它构件Import java.util.ArrayList; 导入库Satic关键字static 声明的方法可以直接用类名调用,不需要new第三章Java运算符: 一个运算符可能改变运算对象的值。这也叫“副作用”(Side Effect)。所以用的时候要小心。运算符类型 运算符 Unary + - + - rest. Arithmetic(and Shift) * / % + - Relational = B?X:Y Assignment =(and Compound assignment like *=)优先级:一般优先级很难记住,所以必要的时候用()来确定。赋值:注意:对象赋值。例如:A=B(A、B为句柄);此时A、B都将指向B原先指向的对象。此时A将成为B的别名。无论A或者B对对象的改变都是一样的。当对象作为参数传递时也是传递句柄,所以往往会改变对象本身。自动递增和自动递减递增操作符+ 放前面是先递增后取值, 放后面是先取值后递增.递减操作符同上关系运算符当两个对象相比较时,请看 Integer n1 = new Integer(48); Integer n2 = new Integer(48);System.out.println(n1=n2); /ture of false?句柄比较,falseSystem.out.println(n1.equals(n2); /true of false ?对象比较,true逻辑运算符“短路”,当出现false的时候,不需要判断下面的,就可以知道表达式的值。减少运算量。位运算符: & 与| 或 非 异或移位运算符则将运算符左边的运算对象向右移动运算符右侧指定的位数。“有符号”右移位运算符使用了“符号扩展”:若值为正,则在高位插入0;若值为负,则在高位插入1(java特有)无符号”右移位运算符(),它使用了“零扩展”:无论正负,都在高位插入0若对char,byte或者short进行移位处理,那么在移位进行之前,它们会自动转换成一个int。只有右侧的5个低位才会用到。这样可防止我们在一个int数里移动不切实际的位数。移位符号可以和赋值“=”一起用。=,先移位,后赋值。三元操作符static int ternary(int i) return i 10 ? i * 100 : i * 10;逗号操作符需要用到逗号的唯一场合就是for循环类型转换操作符void caata() int i = 200; long l = (long)i; long l2 = (long)200;两种: NarrowingConversion(缩小)-编译器会警告,要求强迫转换。主要是信息可能丢失。Widening Conversion (放大)编译器可以自动转换 。中断(break)和继续(continue):public class BreakAndContinue public static void main(String args) for(int i =0;i100;i +) if(i=74)break;/out of for loop if(i%9!=0)continue; /Next iterator; System.out.println(i); int i = 0; /an infinite loop while(true) i+; int j = i*27; if(j=1269)break;/out of loop if(i%10 != 0)continue;/top of loop System.out.println(i); 规则:1、简单的一个continue会退回内层循环的开头,并继续执行。2、带有标签的continue会到达标签的位置,并重新进入接在那个标签后面的循环。3、break会中断当前循环,并移离当前标签的末尾。4、带标签的break会中断当前循环,并移离由那个标签指示的循环末尾。在Java中唯一用的标签的地方就是拥有套嵌的循环。开关(switch)Switch有时也被划为一种”选择语句”. Switch语句可以从一系列代码中选出一断去执行.Switch(integral-selector) Caae integral-value1 : atatement; break; Caae integral-value2 : atatement; break; Caae integral-value3 : atatement; break; Caae integral-value4 : atatement; break; Caae integral-value5 : atatement; break; default : atatement;第四章初始化和清除构造函数负责初始化,分配空间。构建器,无返回值,可重载overloading方法重载overloading方法重载是让类以统一的方式处理不同类型数据的一种手段。Java的方法重载,就是在类中可以创建多个方法,它们具有相同的名字,但具有不同的参数和不同的定义。调用方法时通过传递给它们的不同个数和类型的参数来决定具体使用哪个方法, 这就是多态性。根据参数不同或返回值不同而区分相同名字的方法。注意,Java的方法重载要求同名的方法必须有不同的参数表,仅有返回类型不同是不足以区分两个重载的方法。主类型的重载: 若我们的数据类型小于方法中的自变量,就会向上cast,转换。 如果是大于的话,需要强制转换(信息可能丢失)默认构造函数:创建一个空对象。如果定义一个构建函数,那么就不会使用默认的构建函数。“this”关键字表示调用它的对象的句柄。当前对象的句柄在构建函数中调用构建函数。使用“this”关键字。例如:public class Moop int lit; int pak; public Moop(int x) lit = x; public Moop(int x,int y) this(x); /在构建器中调用了构建函数。this表示当前对象句柄。 pak = y; “static”关键字,static定义的方法没有this句柄注意:我们不可以从一个static方法内部发出对非static方法的调用,除非将以个句柄传到static方法内部。清除收尾和垃圾收集 垃圾收集器只知道释放new分配的内存。当需要释放一些特殊内存的时候,Java提供了一个名为finalize ()的方法。可以在我们的类中定义它。 finalize()工作原理:当垃圾收集器准备好释放对象空间,它首先调用finalize()方法,并且需要在下一次垃圾收集的过程中才真正回收对象内存。三个重点: 1、垃圾收集并不等于“破坏”(释放)Java对象并非肯定最为对象被收集。2、我们的对象可能不会当作垃圾被收集掉。3、垃圾收集只和内存有关。什么时候用finalize()呢?答案是最好不用。似乎finalize()没有多少用途,只是在一些特殊的地方。非Java对象调用。成员初始化:若程序员没有初始化,那编译器会为他们赋一个值:Data Type Inital valueboolean falsechar (Null,不显示)byte 0short 0 int 0long 0float 0.0double 0.0规定初始化:在定义同时赋初值(C+ 中不能这样做)可以用new,方法(带返回值)来初始化构建函数初始化:在用此初始化之前定义的数据成员已经被编译器赋给默认值,所以在构建器中没有强迫我们初始化。静态数据的初始化:static的初始化只有在必要的时候才会进行。初始化时首先是static对象的创建过程:以名为Dog的类为例1.类型为Dog的一个对象首次创建时,或Dog类的static方法/static字段首次访问时,Java解释器必须找到Dog.class(在环境变量中设置搜索路径) 2.找到Dog.class后(它会创建一个class对象) 它的所有static初始化模块都会运行.因此,static初始化仅发生一次,即在class对象首次装载时。 3.创建一个new Dog()时,Dog对象分配足够的内存存储空间。 4.这种存储空间会清为零,将Dog中所有基本类型设为他们的默认值。 5.进行字段定义时发生的初始化都会执行。 6.执行构建函数。明确进行静态初始化 例: class Spoon static int i; static /静态初始化开始 i = 47; 数组初始化Java中的数组大小在编译的时候才决定,在运行的时候才创建。在编译的时候进行边界检查。牺牲性能换来安全。 int a1 = 1,2,3,4,5; int a2 ; a2 = a1; /复制一个句柄。 对于非基本数据类型的数组初始化:使用new Integer a = new Integer /java1.1以后版本支持 new Integer(1); new Integer(2); ; Integer a = /java 1.0 版本支持(唯一) new Integer(1); new Integer(2); 未知参数数量大小,及类型:变参表/:VarArgs.java /Using the Java1.1 array syntax to create /varivale argument lists class Aint i; public class VarArgs static void f(Object x) for(int i = 0 ; i x.length ; i+) System.out.println(xi); /每一个Object都有一个toString(),自动转换 public static void main(String args) f(new Object/不同的类型 new Integer(47),new VarArgs(), new Float(3.14),new Double(11.11); f(new Objectone,two,three); f(new Objectnew A(),new A(),new A(); 多维数组初始化: int a1 = 1,2,3, 4,5,6, ; Integer a2 = new Integer(1),new Integer(2), new Integer(3),new Integer(4), new Integer(5),new Integer(6), int a3 = new intpRand(7); /pRand(int)是一个随机方法 for(int i = 0; i a3.length;i+) a3i = new intpRand5); for(int j = 0 ;ja3i.length;j+) a3ij = new intpRand(5); 第五章封装 库单元我们用 import 关键字导入一个完整的库时,就会获得一个”封装”(Package)例如: import java.util.*;如果想将所有这些组件(在它们各自独立的.java 和.class 文件里)都归纳到一起,那么 package 关键字就可以发挥作用 package mypackage;取得对某成员的访问权的唯一途径是:1.使该成员成为public。于是,无论是谁,无论在哪里,都可以访问该成员。2.通过不加访问权限修饰词并将其他类放置于同一个包内的方式给成员赋予包访问权。于是包内的其他类也就可以访问该成员了。3.继承技术中可以看到继承而来的类可以与访问public成员一样地访问protected成员(但访问private成员却不行)。4.提供访问器(accessor)和变异器(mutator)方法(也称作“get/set方法”),以读取和改变数值。一些额外的限制:1.每个编译单元(文件)都只能有一个public类。这表示每个编译单元都有一个单一的公共接口,用public类来表现。2.public类的名称必须完全与含有该编译单元的文件名相匹配,包括大小写。3.虽然不是很常用,但编译单元内完全不带public类也是可能的。组合技术通常用于你想要在新类中使用现有类的功能而非它的接口的情形。即,你在新类中嵌入某个对象,借其实现你所需要的功能,但新类的用户看到的只是你为新类所定义的接口,而非嵌入对象的接口。为取得此效果,你需要在新类中嵌入一个private的现有类的对象。向上转型:由于向上转型是从一个较专用类型向通用类型转,所以总是很安全的。也就是说,导出类是基类的一个超集(superset)。它可能比基类含有更多的方法,但它必须至少具备基类中所含有的方法。在向上转型的过程中,对于类接口唯一有可能发生的事情是丢失方法,而不是获取它们。这就是为什么编译器在“未曾明确表示转型”或“未曾指定特殊标记”的情况下,仍然允许向上转型的原因。使用final方法第一个原因是把方法锁定,以预防任何继承类修改它的意义。第二个原因是效率。如果你将一个方法指明为final,就是同意编译器将针对该方法的所有调用都转为内嵌(inline)调用。当编译器发现一个final方法调用命令时,它会根据自己的谨慎判断,跳出插入程序代码的正常方法而执行方法调用机制(将参数压入栈,跳至方法代码处并执行,然后跳回并清除栈中的参数,处理返回值。),并且以方法体中的实际代码的复本来替代方法调用。这将消除方法调用的开销。第六章 复用类组合(composition)在新的类中产生现有类的对象(只是复用了现有程序代码的功能,而非它的形式)编译器并不是简单地为每一个引用都创建缺省对象,这一点是很有意义的,因为真要是那样做的话,就会在许多情况下增加不必要的负担。如果你想初始化这些引用,可以在代码中的下列位置进行:1、在定义对象的地方。这意味着它们总是能够在构造器被调用之前初始化。2、在类的构造器中。3、就在你确定需要使用这些对象之前。这种方式被称为“惰性初始化”。每一个非基本类型的对象都有一个toString(),而且编译器需要一个string而你却只有一个对象时,该方法就会被调用。继承(inheritance)按照现有类的类型来创建新类,无需改变旧有的类的形式,仅只是采用它的形式并在其中添加新代码。class 子类 extends 基类 子类自动得到基类中所有的数据成员和成员方法。当你创建一个导出类的对象时,该对象包含了一个基类的子对象。这个子对象与你用基类直接创建的对象一样的。二者的区别在于,后者来自外部,而基类的子对象被包装在导出类对象内部。对基类子对象的正确初始化至关重要:Java会自动在导出类的构造器中插入对基类构造器的调用。构造过程是从基类“向外”扩散的,所以基类在导出类构造器可以访问它之前,就已经完成了初始化。带参数的构造器如果你的类没有缺省的参数,或者是你想调用一个带参数的基类构造器,你就必须用关键字super显示的编写调用基类构造器的语句,并且配以适当的参数列表。结合使用组合和继承确保正确清除名称屏蔽:如果Java的基类拥有某个已被多次重载的方法名称,那么载导出类中重新定义该方法名称,并不会屏蔽其在基类中的任何版本。组合与继承之间选择:组合技术通常用于你想要在新类中使用现有类的功能而非它的接口的情形,继承使用某个现有类,并开发一个它的特殊版本。受保护的(protected):对于任何继承于此类的导出类或其它任何位于同一个包内的类来说,可以进行访问。增量开发引入新代码而不会在现有代码中引发Bug。向上转型(upcasting):“为新的类提供方法”并不是继承技术中最重要的一个方面。其最重要的方面是它被用来表现新类和基类之间的关系。这种关系可以用“新类是现有类的一种类型”来加以概括。将子类的引用转换为父类的引用的动作称为“向上转型”。为什么要使用“向上转型”:由于向上转型是从一个较专用类型向较通用类型,所以总是安全的。再次探究组合于继承一个用以判断你到底是该用组合还是继承的最清晰的办法,就是问一问你自己是否需要从新类向基类向上转型。如果你必须向上转型,则继承是必要的,但如果你不需要,则你应该好好考虑是否需要继承。关键字final “这是无法改变的”。Final数据:一个即是static又是 final的域只占有一份不能改变的存储空间。对对象引用,final使引用恒定不变。空白final是指被声明为final但又未给定初值的数据成员使用前必须初始化。 Final方法(原因1把方法锁定,以预防任何继承类修改它的意义原因2是效率)Final类:不能有子类初始化及类的加载:知道类的第一个对象被构造时才发生加载,所有的 static 对象和代码都会在加载时依程序中的顺序依次初始化,只会初始化一次。继承与初始化:加载类时,有基类则不管你是否打算产生该基类的对象,都会加载基类。如果基类还有其自身的基类,那么第二个基类就会被加载,依次类推。第七章多态将一个方法调用同一个方法主体关联起来被称作“绑定(binding)”。若在程序执行前进行绑定(如果有的话,由编译器和链接程序实现),叫做“前期绑定(early binding)”。后期绑定也叫做“动态绑定(dynamic binding)”或“运行时绑定(run-time binding)”。如果一种语言想实现后期绑定,就必须具有某些机制,以便在运行时能判断对象的类型,以调用前当的方法。也就是说,编译器仍不知道对象类型,但是方法调用机制能找到正确的方法体,并加以调用。向上转型可以像下面这条语句这么简单:Shape s = new Circle();这里,创建了一个Circle对象,并把得到的引用立即赋值给Shape,这样做看似错误(将一种类型赋值给另一个类型);但实际上是没有问题的,因为通过继承,Circle就是一种Shape。因此,编译器认可这条语句,也就不会产生错误信息。假设我们调用某个基类方法(已被导出类所重载):s.draw();同样的,我们会认为调用的是shape的draw(),因为这毕竟是一个shape引用,那么编译器是怎么知道去做其他的事情呢?由于后期绑定(多态),程序还是正确调用了Circle.draw()方法。抽象类:当我们想通过这个通用接口操纵一系列类时,就需创建一个抽象类。与任何基类所声明的签名相符的导出类方法,都会通过动态绑定机制来调用。(然而,如果方法名与基类中的相同,但是参数不同,就会出现重载,这或许不是我们想要的)如果只有一个像Instrument这样的抽象类,那么该类的对象几乎没有任何意义。也就是说,Instrument只是表示了一个接口,没有具体的实现内容;因此,创建一个Instrument对象没有什么意义,并且我们可能还想阻止使用者这样做。通过在Instrument的所有方法中打印出错误信息,就可以实现这个目的。但是这样做会将错误信息延迟到运行期才可获得,并且需要在客户端进行可靠、详尽的测试。所以最好是在编译期间捕获这些问题。为此,java提供一个叫做“abstract method抽象方法”的机制。这种方法是不完整的;仅有声明而没有方法体。包含抽象方法的类叫做“抽象类”。如果一个类包含一个或多个抽象方法,该类必须被限制为抽象的。否则,编译器就会报错。构造器和多态:尽管构造器并不具有多态性(它们实际上是static方法,只不过该static声明是隐式的)。构造器的调用顺序:基类的构造器总是在导出类的构造器过程中被调用,而且按照继承层次逐渐向上链接,以使每个基类的构造器都能得到调用。这样做是有意义的,因为构造器具有一项特殊任务:检查对象是否被正确地构造。导出类只能访问它自己的成员,不能访问基类中的成员(基类成员通常是private类型)。只有基类的构造器才具有恰当的知识和权限对自己的元素进行初始化。因此,必须令所以后构造器都得到调用,否则所有对象就不可能被正确构造。这正是编译器为什么要强制每个导出类部分都必须调用构造器的原因。构造器不能多态就是因为调用顺序。用继承进行设计:一条通用的规则:用继承表达行为间的差异,并用属性表达状态上的变化。abstract修饰符用来修饰类和成员方法 1:用abstract修饰的类表示抽象类,抽象类位于继承树的抽象层,抽象类不能被实例化。 2:用abstract修饰的方法表示抽象方法,抽象方法没有方法体。抽象方法用来描述系统具有什么功能,但不提供具体的实现。 abstract 规则:1:抽象类可以没有抽象方法,但是有抽象方法的类必须定义为抽象类,如果一个子类继承一个抽象类,子类没有实现父类的所有抽象方法,那么子类也要定义为抽象类,否则的话编译会出错的。 2:抽象类没有构造方法,也没有抽象静态方法。但是可以有非抽象的构造方法 3:抽象类不能被实例化,但是可以创建一个引用变量,类型是一个抽象类,并让它引用非抽象类的子类的一个实例 4:不能用final 修饰符修饰为了满足常规编程的需要,我们要求能在任何时候、任何地点创建任意数量的对象。所以不可依赖一个已命名的句柄来容纳自己的每一个对象第八章interface关键字interface关键字允许类的创建者为一个类建立其形式:有方法名、参数列表和返回类型,但是没有任何方法体。接口也可以包含有数据成员,但是它们隐含都是static和final的,它们不能是“空final”,但是可以被非常量表达式初始化。接口中的方法因为需要多态,所以不能是final和static的(final不能继承,而static无法多态,唯一一个static空间不能指向new的多个堆)接口只提供了形式,而未提供任何具体实现。接口可以嵌套在类或其他接口中。一个接口表示:“所有实现了该特定接口的类看起来都像它”。因此,任何使用某特定接口的代码都知道可能会调用该接口的那些方法,而且仅需知道这些。因此,接口被用来建立类于类之间的“协议(protocol)”。使用接口的核心原因:为了能够向上转型为不止一个的基类型。然而,使用接口的第二个原因却是与使用抽象基类相同:防止客户端程序员创建该类的对象,并确保这仅仅是建立一个接口。在类中嵌套接口在类中嵌套接口的语法是相当显而易见的,就像非嵌套接口一样,可以拥有public和包内访问来年各种可视性。你可以看到,public和包内访问的嵌套接口都可以被实现为public、包内访问以及private的嵌套类。当你实现某个接口时,并不需要实现嵌套在其内部的任何接口。而且private接口不能在定义它的类之外被实现。内部类如果你想从外部类的非静态方法之外的任意位置创建某个内部类的对象,那么你必须像main()方法中那样,具体地指明这个对象的类型:OuterClassName.InnerClassName.内部类的第一个好处就体现出来了 隐藏你不想让别人知道的操作,也即封装性。 同时,我们也发现了在外部类作用范围之外得到内部类对象的第一个方法,那就是利用其外部类的方法创建并返回。内部类的第二个好处一个内部类对象可以访问创建它的外部类对象的内容,甚至包括私有变量!这是一个非常有用的特性,为我们在设计时提供了更多的思路和捷径。要想实现这个功能,内部类对象就必须有指向外部类对象的引用。Java编译器在创建内部类对象时,隐式的把其外部类对象的引用也传了进去并一直保存着。这样就使得内部类对象始终可以访问其外部类对象,同时这也是为什么在外部类作用范围之外向要创建内部类对象必须先创建其外部类对象的原因。如果内部类里的一个成员变量与外部类的一个成员变量同名,也即外部类的同名成员变量被屏蔽了,怎么办?没事,Java里用如下格式表达外部类的引用: 外部类.this 有了它,我们就不怕这种屏蔽的情况了静态内部类 和普通的类一样,内部类也可以有静态的。不过和非静态内部类相比,区别就在于静态内部类没有了指向外部的引用。除此之外,在任何非静态内部类中,都不能有静态数据,静态方法或者又一个静态内部类(内部类的嵌套可以不止一层)。不过静态内部类中却可以拥有这一切。这也算是两者的第二个区别吧。局部内部类 Java内部类也可以是局部的,它可以定义在一个方法甚至一个代码块之内。 public class Goods1 public Destination dest(String s) class GDestination implements Destination private String label;private GDestination(String whereTo) label = whereTo;public String readLabel() return label; return new GDestination(s); public static void main(String args) Goods1 g= new Goods1();Destination d = g.dest(Beijing); 上面就是这样一个例子。在方法dest中我们定义了一个内部类,最后由这个方法返回这个内部类的对象。如果我们在用一个内部类的时候仅需要创建它的一个对象并创给外部,就可以这样做。当然,定义在方法中的内部类可以使设计多样化,用途绝不仅仅在这一点。匿名内部类java的匿名内部类的语法规则看上去有些古怪,不过如同匿名数组一样,当你只需要创建一个类的对象而且用不上它的名字时,使用内部类可以使代码看上去简洁清楚。它的语法规则是这样的: new interfacename().; 或 new superclassname().; 下面接着前面继续举例子: public class Goods3 public Contents cont()return new Contents()private int i = 11;publi
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 木材销售协议书模板
- 新车买卖协议书样本
- 水利水电工程师考务培训试题及答案
- 2026-2031年中国弱视治疗仪行业市场发展现状及投资前景预测报告
- 食品生产计划考试题及答案
- 老年公寓老人生活监护人培训试题及答案
- 教育扶贫共建协议书
- 2026-2031年中国生态修复行业前景研究与市场需求预测报告
- 文章刊登协议书模板
- 人民银行考试题库及答案
- 中国建筑史-绘图题
- GB/T 9442-2010铸造用硅砂
- 溶胶-凝胶法:高均一性、高比表面积催化剂制备
- FZ/T 73009-2021山羊绒针织品
- 纤维化学与物理-第三章蛋白质纤维-蚕丝课件
- 医务处的管理职责课件
- 中医妇科学课件-妊娠病胎漏胎动不安
- 甾体及其苷类-2011课件
- 大健康数据课件
- 新北师大版七年级上册生物 第2单元 生物体的结构 教学课件
- 非物质文化遗产概论:第二章-非遗分类-第七节传统节日类遗产课件
评论
0/150
提交评论