接口优先于抽象类

接口和抽象类是用来定义多个实现的类型的两种机制。相比较而言接口更加灵活、实用。理由如下:

现有的类很容易更新,以实现新的接口。但是对抽象类则不行。

接口是定义混合类型的理想选择。

接口允许我们构造非层次结构的类型框架。非结构类型的组织。

抽象类演变比接口的演变要容易的多。后续版本可以在抽象类中添加方法,并且有默认的实现。而接口则不行。接口一旦被公开,并且被广泛实现,再想改变几乎是不可能的。所以设计接口的时候必须非常谨慎。

转载于:https://www.cnblogs.com/macula7/archive/2009/09/16/1960761.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
基本数据型的包装 •八大数据型的包装分别为:Byte、Short、Integer、Long、Character、 Float、Double、Boolean。 把基本数据型变量包装实例是通过对应包装的构造器来实现的,不仅如此,8个包装中除了 Character之外,还可以通过传入一个字符串参数来构建包装对象。 •如果希望获得包装对象中包装的基本型变量,则可以使用包装提供的XxxValue()实例方法。 自动装箱与自动拆箱 •JDk还提供了自动装箱和自动拆箱。自动装箱就是把一个基本型的变量直接赋给对应的包装变量,自动拆箱 则与之相反。 •包装还可以实现基本型变量和字符串之间的转换,除了Character之外的所有包装都提供了一个 parseXxx(String s)静态方法。 •如果将基本型转换为这符串,只需在后面加+ “”进行连接运算。 Java 7对包装的增强 •Java 7为所有包装增加一个新方法: compare(x , y)的方法。该方法用于比较两个包装实例,当x>y, 返回大于0的数;当x==y,返回0;否则返回小于0的数。 对象的方法 •打印对象和toString方法:toString方法是系统将会输出该对象的“自我描述”信息,用以告诉外界对象具有的状 态信息。 •Object 提供的toString方法总是返回该对象实现名 + @ +hashCode值。 •==和equals比较运算符:==要求两个引用变量指向同一个对象才会返回true。equals方法则允许用户提供自 定义的相等规则。 •Object提供的equals方法判断两个对象相等的标准与==完全相同。因此开发者通常需要重写equals方法。 成员 •在java里只能包含Field,方法,构造器,初始化块,内部接口、枚举)等5种成员。 用static修饰的成员属 于成员,Field既可通过来访问,也可以通过的对象来访问。当通过对象来访问属性时,系统会在底 层转换为通过该来访问 属性。 成员规则 •成员并不是属于实例,它是属于本身的。只要存在,成员就存在。 •即使通过null对象来访问成员,程序也不会引发NullPointerException。   成员不能访问实例成员。 单例 •如果一个始终只能创建一个对象,称为单例。须符合以下几个条件:   –1.我们把该的构造器使用Private修饰,从而把该 的所有构造器隐藏起来。   –2.则需要提供一个public方法作为该的访问点,用于创建该的对象,且必须使用static修饰   –3.该还必须缓存已经创建的对象,必须用static修饰 final变量 •final修饰变量时,表示该变量一旦获得 初始值之后就不可被改变。 •final既可修饰成员变量,也可以修饰局部变量。 final修饰成员变量 •成员变量是随的初始化或对象初始化而初始化的。final修饰的成员变量必须由程序员指定初始值。 •对于属性而言,要么在静态初始化中初始化,要么在声明该属性时初始化。 •对于实例属性,要么在普通初始化块中指定初始值。要么在定义时、或构造器中指定初始值。 final修饰局部变量 •使用final修饰局部变量时既可以在定义时指定默认值,也可以不指定默认值。 •给局部变量赋初始值,只能一次,不能重复。 final修饰基本型和引用型 •当使用final修饰基本数据型时,不能对其重新赋值,不能被改变。 •但对引用型的变量而言,它仅仅保存的是一个引用,final只能保证他的地址不变,但不能保证对象,所以引用 型完全可以改变他的对象。 可执行“宏替换”的final变量 •对一个final变量来说,不管它是变量、实例变量,还是局部变量,只要该变量满足3个条件,这个final变量就 不再是一个变量,而是相当于一个直接量。   –使用final修饰符修饰;   –在定义该final变量时指定了初始值;   –该初始值可以在编译时就被确定下来。 final方法 •final方法 •final 修饰的方法不可以被重写。 •final 修饰的方法仅仅是不能重写,但它完全可以被重载。 •final 修饰的不可以被继承 不可变的 •不可变的要满足以下几个条件:   –1.使用private和final修饰符来修饰该的属性   –2.提供带参数的构造器,用于根据传入参数来初始化里的属性   –3.仅为该的属性提供getter方法,不要为该的属性提供setter方法,因为普通方法无法修改final修饰的 属性   –4.如有必要,重写Object中hashCode 和equals •缓存实例的不可变:如果程序经常需要使用不可变的实例,则可对实例进行缓存。 抽象方法和抽象类 •抽象方法和都必须使用abstract来修饰,有抽象方法的只能定义成抽象类,抽象里也可以没有抽象方法。 • 抽象类不能被实例化,可以通过其子给他赋值,普通里有的抽象里也有,定义抽象方法只需在普通方法上增 加abstract修饰符,并把普通方法的方法体(也就是方法后花括号括起来的部分)全部去掉,并在方法后增加分号 即可。 抽象类的特征 •抽象类的特征:有得有失,得到了新能力,可以拥有抽象方法;失去了创建对象的能力。 抽象类的作用 •抽象类代表了一种未完成的设计,它体现的是一种模板。 •抽象类与模板模式。 接口的概念 •接口定义的是多个共同的行为规范,这些行为是与外部交流的通道,这就意味着接口里通常是定义一组公用的 方法。 •接口体现了规范与实现分离的设计。 接口的定义 •和定义不同,定义接口不再用class关键字,而是使用interface关键字。语法如下: •[修饰符] interface接口名 extends 父接口1,父接口2 ... •{ • 零个到多个常量定义... • 零个到多个抽象方法定义... • 零个到多个内部接口、枚举定义... • 零个到多个默认方法或方法定义... •} 接口里的成分 •在定义接口时,接口里可以包含成员变量(只能是常量),方法(只能是抽象实例方法、方法或默认方法),内 部(包括内部接口、枚举   –常量都是:public static final修饰   –方法都是:public abstract 修饰   –内部的:public static 接口的继承 •接口的继承和继承不一样,接口完全支持多继承,子接口扩展某个父接口将会获得父接口的所有抽象方法,常 量属性,内部和枚举定义。 使用接口接口可以用于声明引用型的变量,但接口不能用于创建实例。 •当使用接口来声明引用型的变量时,这个引用型的变量必须引用到其实现的对象。 •一个可以实现一个或多个接口,继承使用extends关键字,实现接口则使用implements关键字。 实现接口 •一个实现了一个或多个接口之后,这个必须完全实现这些接口里所定义的全部抽象方法(也就是重写这些抽 象方法); •否则,该将保留从父接口那里继承到的抽象方法,该也必须定义成抽象类接口抽象类的相似性 •接口抽象类都不能被实例化,它们都位于继承树的顶端,用于被其他实现和继承。 •接口抽象类都可以包含抽象方法,实现接口或继承抽象类的普通子都必须实现这些抽象方法。 接口抽象类的区别 •接口里只能包含抽象方法,不同包含已经提供实现的方法;抽象类则完全可以包含普通方法。 •接口里不能定义静态方法;抽象类里可以定义静态方法。 •接口里只能定义静态常量属性,不能定义普通属性;抽象类里则既可以定义普通属性,也可以定义静态常量属 性。 •接口不包含构造器;抽象类里可以包含构造器,抽象类里的构造器并不是用于创建对象,而让其子调用这些构 造器来完成属于抽象类的初始化操作。 •接口里不能包含初始化块,但抽象类则完全可以包含初始化块。 •一个最多只能有一个直接父,包括抽象类;但一个可以直接实现多个接口,通过实现多个接口可以弥补 Java单继承的不足。 面向接口编程 •接口体现了规范与实现分离的原则。充分利用接口可以很好地提高系统的可扩展性和可维护性。 •接口与简单工厂模式、命令模式等。 内部 •我们把一个放在另一个的内部定义,这个定义在其他内部的就被称为内部,有的也叫嵌套,包含内   部也被称为外部有的也叫宿住。 •内部提供了更好的封装,内部成员可以直接访问外部的私有数据,因为内部被当成其他外部成员。 •匿名内部适合用于创建那些仅需要一次使用的。 非静态内部 •定义内部非常简单,只要把一个放在另一个内部定义即可。 •当在非静态内部的方法内访问某个变量时,系统优先在该方法内查找是否存在该名字的局部变量,如果存在该 名字的局部变量,就使用该变量,如果不存在,则到该方法所在的内部中查找是否存在该名字的属性,如果存在 则使用该属性。 •总之,第一步先找局部变量,第二步,内部的属性,第三步。外部的属性。 本文原创作者:pipi-changing 本文原创出处:http://www.cnblogs.com/pipi-changing/ 静态内部 •如果用static修饰一个内部,称为静态内部。 •静态内部可以包含静态成员,也可以包含非静态成员。所以静态内部不能访问外部的实例成员,只能访问   外部成员。 •静态内部的对象寄存在外部里,非静态内部的对象寄存在外部实例里 使用内部 •1.在外部内部使用内部-不要在外部的静态成员中使用非静态内部,因为静态成员不能访问非静态成 员。 • 2.在外部以外使用非静态内部。   –private 修饰的内部只能在外部内部使用。   –在外部以外的地方使用内部,内部完整的名应该OuterClass.InnerClass.   –在外部以外的地方使用非静态内部创建对象的语法如下:OuterInstance.new InnerConstructor()   –在外部以外的地方使用静态内部创建对象的语法如下:new OuterClass.InnerConstructer(); 局部内部 •如果把一个内部放在方法里定义,这就是局部内部,仅仅在这个方法里有效。 •局部内部不能在外部以外的地方使用,那么局部内部也不能使用访问控制符和static修饰 匿名内部 •匿名内部适合创建那种只需要一次使用的,定义匿名内部的语法格式如下: •new 父构造器(实例列表) |实现接口) •{ • //匿名内部体部分 •} •匿名内部不能是抽象类,匿名内部不能定义构造器。 Lambda表达式入门 •Lambda表达式主要作用就是代替匿名内部的繁琐语法。它由三部分组成:   –形参列表。形参列表允许省略形参型。如果形参列表中只有一个参数,甚至连形参列表的圆括号也可以省略。   –箭头(->),必须通过英文等号和大于符号组成。   –代码块。如果代码块只有包含一条语句,Lambda表达式允许省略代码块的花括号,如果省略了代码块的花括 号,这条语句不要用花括号表示语句结束。Lambda代码块只有一条return语句,甚至可以省略return关键字。 Lambda表达式需要返回值,而它的代码块中仅有一条省略了return的语句,Lambda表达式会自动返回这条语句的 值。 Lambda表达式与函数式接口 •如果采用匿名内部语法来创建函数式接口的实例,只要实现一个抽象方法即可,在这种情况下即可采用 Lambda表达式来创建对象,该表达式创建出来的对象的目标型就是这个函数式接口。 •Lambda表达式有如下两个限制:   –Lambda表达式的目标型必须是明确的函数式接口。   –Lambda表达式只能为函数式接口创建对象。Lambda表达式只能实现一个方法,因此它只能为只有一个抽 象方法的接口(函数式接口)创建对象。 •为了保证Lambda表达式的目标型是一个明确的函数式接口,可以有如下三种常见方式:   –将Lambda表达式赋值给函数式接口型的变量。   –将Lambda表达式作为函数式接口型的参数传给某个方法。   –使用函数式接口对Lambda表达式进行强制型转换。 方法引用与构造器引用 种 示例 说明 对应的Lambda表达式 引用方法 名::方法 函数式接口中被实现方法的全部参数传给该方法作为参数。 (a,b,...) -> 名.方法(a,b, ...) 引用特定对象的实例方法 特定对象::实例方法 函数式接口中被实现方法的全部参数传给该方法作为参数。 (a,b, ...) -> 特定对象.实例方法(a,b, ...) 引用某对象的实例方法 名::实例方法 函数式接口中被实现方法的第一个参数作为调用者,后面的参数全部传给该方法作为参数。 (a,b, ...) ->a.实例方法(b, ...) 引用构造器 名::new 函数式接口中被实现方法的全部参数传给该构造器作为参数。 (a,b, ...) ->new 名(a,b, ...) Lambda表达式与匿名内部 •Lambda表达式与匿名内部存在如下相同点:   –Lambda表达式与匿名内部一样,都可以直接访问“effectively final”的局部变量,以及外部的成员变 量(包括实例变量和变量)。   –Lambda表达式创建的对象与匿名内部生成的对象一样, 都可以直接调用从接口继承得到的默认方法。 •Lambda表达式与匿名内部主要存在如下区别:   –匿名内部可以为任意接口创建实例——不管接口包含多少个抽象方法,只要匿名内部实现所有的抽象方 法即可。但Lambda表达式只能为函数式接口创建实例。   –匿名内部可以为抽象类、甚至普通创建实例,但Lambda表达式只能为函数式接口创建实例。   –匿名内部实现的抽象方法的方法体允许调用接口中定义的默认方法;但Lambda表达式的代码块不允许调 用接口中定义的默认方法。 手动实现枚举 •可以采用如下设计方式:   –通过private将构造器隐藏起来。   –把这个的所有可能实例都使用public static final属性来保存。   –如果有必要,可以提供一些静态方法,允许其他程序根据特定参数来获取与之匹配实例。 JDK 5新增的枚举支持 •J2SE1.5新增了一个enum关键字,用以定义枚举。正如前面看到,枚举是一种特殊的,它一样可以有自 己的方法和属性,可以实现一个或者多个接口,也可以定义自己的构造器。一个Java源文件中最多只能定义一个 public访问权限的枚举,且该Java源文件也必须和该枚举名相同。 枚举 •枚举可以实现一个或多个接口,使用enum定义的枚举默认继承了java.lang.Enum,而不是继承Object 。其中java.lang.Enum实现了java.lang.Serializable和java.lang. Comparable两个接口。 •枚举的构造器只能使用private访问控制符,如果省略了其构造器的访问控制符,则默认使用private修饰;如 果强制指定访问控制符,则只能指定private修饰符。 •枚举的所有实例必须在枚举中显式列出,否则这个枚举将永远都不能产生实例。列出这些实例时系统会自 动添加public static final修饰,无需程序员显式添加。 •所有枚举都提供了一个values方法,该方法可以很方便地遍历所有的枚举值。 枚举的属性、方法和构造器 •枚举也是一种,只是它是一种比较特殊的,因此它一样可以使用属性和方法。 •枚举通常应该设计成不可变,也就说它的属性值不应该允许改变,这样会更安全,而且代码更加简洁。为 此,我们应该将枚举的属性都使用private final 修饰。 •一旦为枚举显式定义了带参数的构造器,则列出枚举值时也必须对应地传入参数。 实现接口的枚举 •枚举也可以实现一个或多个接口。与普通实现一个或多个接口完全一样,枚举实现一个或多个接口时,也 需要实现该接口所包含的方法。 •如果需要每个枚举值在调用同一个方法时呈现出不同的行为方式,则可以让每个枚举值分别来实现该方法,每个 枚举值提供不同的实现方式,从而让不同枚举值调用同一个方法时具有不同的行为方式。 包含抽象方法的枚举 •可以在枚举里定义一个抽象方法,然后把这个抽象方法交给各枚举值去实现即可。 •枚举里定义抽象方法时无需显式使用abstract关键字将枚举定义成抽象类,但因为枚举需要显式创建枚举 值,而不是作为父,所以定义每个枚举值时必须为抽象方法提供实现,否则将出现编译错误。 垃圾回收机制 •垃圾回收机制只负责回收堆内存中对象,不会回收任何任何物理资源(例如数据库连接,网络IO等资源)。 •程序无法精确控制垃圾回收的运行,垃圾回收会在合适时候进行垃圾回收。当对象永久性地失去引用后,系统就 会在合适时候回收它所占的内存。 •垃圾回收机制回收任何对象之前,总会先调用它的finalize方法,该方法可能使该对象重新复活(让一个引用变量 重新引用该对象),从而导致垃圾回收机制取消回收 对象在内存中的状态 •激活状态:当一个对象被创建后,有一个以上的引用变量引用它。则这个对象在程序中处于激活状态,程序可通 过引用变量来调用该对象的属性和方法。 •去活状态:如果程序中某个对象不再有任何引用变量引用它,它就进入了去活状态。在这个状态下,系统的垃圾 回收机制准备回收该对象所占用的内存,在回收该对象之前,系统会调用所有去活状态对象的finalize方法进行资 源清理,如果系统在调用finalize方法重新让一个引用变量引用该对象,则这个对象会再次变为激活状态;否则该 对象将进入死亡状态。 •死亡状态:当对象与所有引用变量的关联都被切断,且系统会调用所有对象的finalize方法依然没有使该对象变成 激活状态,那这个对象将永久性地失去引用,最后变成死亡状态。只有当一个对象处于死亡状态时,系统才会真正 回收该对象所占有的资源。 强制垃圾回收 •强制系统垃圾回收有如下两个方法:   –调用System的gc()静态方法:System.gc()   –调用Runtime对象的gc()实例方法:Runtime.getRuntime().gc() finalize方法 •finalize方法有如下四个特点:   –永远不要主动调用某个对象的finalize方法,该方法应交给垃圾回收机制调用。   –finalize方法的何时被调用,是否被调用具有不确定性。不要把finalize方法当成一定会被执行的方法。   –当JVM执行去活对象的finalize方法时,可能使该对象,或系统中其他对象重新变成激活状态。   –当JVM执行finalize方法时出现了异常,垃圾回收机制不会报告异常,程序继续执行。 对象的软、弱和虚引用 •强引用(StrongReference) •软引用-软引用需要通过SoftReference来实现,当一个对象只具有软引用时,它有可能被垃圾回收机制回 收。 •弱引用-弱引用通过WeakReference实现,弱引用和软引用很像,但弱引用的引用级别更低。对于只有弱引 用的对象而言,当系统垃圾回收机制运行时,不管系统内存是否足够,总会回收该对象所占用的内存。 •虚引用-虚引用通过PhantomReference实现,虚应用完全似于没有引用。虚引用对对象本身没有太大影 响,对象甚至感觉不到虚引用的存在。 修饰符的适用范围 顶层/接口 成员属性 方法 构造器 初始化块 成员内部 局部成员 public √ √ √ √ √ protected √ √ √ √ 包访问控制符 √ √ √ √ ○ √ ○ private √ √ √ √ abstract √ √ √ final √ √ √ √ √ static √ √ √ √ strictfp √ √ √ synchronized √ native √ transient √ volatile √ 使用JAR文件的好处 •1.安全 •2.加快下载速度 •3.压缩 •4.包封装 •5.可移植性 jar命令详解 •-c 创建新文档,-t 列出存档内容的列表, -x 展开存档中的命名文件 •-u 更新已存在的存档,-v生成详细输出到标准输出上 •-f 指定存档文件名,-m 包含 来自标文件的标明信息 •-o 只存储方式:未用ZIP压缩格式 •-m 不产生所有项的清单文件,- I 为指定的jar文件产生索引信息 •-c 改变到指定的目录, 创建可执行的JAR包 •1.使用平台相关的编译器将整个应用编译成平台相关的可执行性文件 •2.为整个应用编辑一个批处理文件 关于JAR包的技巧 •相当于一个压缩文件。 •可使用WinRAR来压缩JAR包。 •也可使用WinRAR来查看JAR包。 现在贴出代码: AutoBoxingUnboxing Primitive2String UnsignedTest WrapperClassCompare EqualTest Person OverrideEqualsRight PrintObject StringCompareTest ToStringTest NullAccessStatic Singleton Address CacheImmutaleTest FinalErrorTest FinalLocalTest FinalLocalVariableTest FinalMethodTest FinalReferenceTest FinalReplaceTest FinalVariableTest ImmutableStringTest IntegerCacheTest Person Sub extends PrivateFinalMethodTest StringJoinTest CarSpeedMeter Circle extends Shape abstract class Shape SpeedMeter Triangle 复制代码 public class AddCommand implements Command { public void process(int[] target) { int sum = 0; for (int tmp : target) { sum += tmp; } System.out.println("数组元素的总和是:" + sum); } } **************************************************** public class BetterPrinter implements Output { private String[] printData = new String[MAX_CACHE_LINE * 2]; // 用以记录当前需打印的作业数 private int dataNum = 0; public void out() { // 只要还有作业,继续打印 while (dataNum > 0) { System.out.println("高速打印机正在打印:" + printData[0]); // 把作业队列整体前移一位,并将剩下的作业数减1 System.arraycopy(printData, 1, printData, 0, --dataNum); } } public void getData(String msg) { if (dataNum >= MAX_CACHE_LINE * 2) { System.out.println("输出队列已满,添加失败"); } else { // 把打印数据添加到队列里,已保存数据的数量加1。 printData[dataNum++] = msg; } } } ************************************************ public interface Command { // 接口里定义的process()方法用于封装“处理行为” void process(int[] target); } ********************************************** public class CommandTest { public static void main(String[] args) { ProcessArray pa = new ProcessArray(); int[] target = { 3, -4, 6, 4 }; // 第一次处理数组,具体处理行为取决于PrintCommand pa.process(target, new PrintCommand()); System.out.println("------------------"); // 第二次处理数组,具体处理行为取决于AddCommand pa.process(target, new AddCommand()); } } ************************************************* public class Computer { private Output out; public Computer(Output out) { this.out = out; } // 定义一个模拟获取字符串输入的方法 public void keyIn(String msg) { out.getData(msg); } // 定义一个模拟打印的方法 public void print() { out.out(); } } ********************************************** interface interfaceA { int PROP_A = 5; void testA(); } interface interfaceB { int PROP_B = 6; void testB(); } interface interfaceC extends interfaceA, interfaceB { int PROP_C = 7; void testC(); } public class InterfaceExtendsTest { public static void main(String[] args) { System.out.println(interfaceC.PROP_A); System.out.println(interfaceC.PROP_B); System.out.println(interfaceC.PROP_C); } } ************************************************** public interface Output { // 接口里定义的成员变量只能是常量 int MAX_CACHE_LINE = 50; // 接口里定义的普通方法只能是public的抽象方法 void out(); void getData(String msg); // 在接口中定义默认方法,需要使用default修饰 default void print(String... msgs) { for (String msg : msgs) { System.out.println(msg); } } // 在接口中定义默认方法,需要使用default修饰 default void test() { System.out.println("默认的test()方法"); } // 在接口中定义方法,需要使用static修饰 static String staticTest() { return "接口里的方法"; } } ********************************************** public class OutputFactory { public Output getOutput() { // return new Printer(); return new BetterPrinter(); } public static void main(String[] args) { OutputFactory of = new OutputFactory(); Computer c = new Computer(of.getOutput()); c.keyIn("轻量级Java EE企业应用实战"); c.keyIn("疯狂Java讲义"); c.print(); } } *********************************************** public class OutputFieldTest { public static void main(String[] args) { // 访问另一个包中的Output接口的MAX_CACHE_LINE System.out.println(lee.Output.MAX_CACHE_LINE); // 下面语句将引起"为final变量赋值"的编译异常 // lee.Output.MAX_CACHE_LINE = 20; // 使用接口来调用方法 System.out.println(lee.Output.staticTest()); } } ************************************************ public class PrintCommand implements Command { public void process(int[] target) { for (int tmp : target) { System.out.println("迭代输出目标数组的元素:" + tmp); } } } *********************************************** // 定义一个Product接口 interface Product { int getProduceTime(); } // 让Printer实现Output和Product接口 public class Printer implements Output, Product { private String[] printData = new String[MAX_CACHE_LINE]; // 用以记录当前需打印的作业数 private int dataNum = 0; public void out() { // 只要还有作业,继续打印 while (dataNum > 0) { System.out.println("打印机打印:" + printData[0]); // 把作业队列整体前移一位,并将剩下的作业数减1 System.arraycopy(printData, 1, printData, 0, --dataNum); } } public void getData(String msg) { if (dataNum >= MAX_CACHE_LINE) { System.out.println("输出队列已满,添加失败"); } else { // 把打印数据添加到队列里,已保存数据的数量加1。 printData[dataNum++] = msg; } } public int getProduceTime() { return 45; } public static void main(String[] args) { // 创建一个Printer对象,当成Output使用 Output o = new Printer(); o.getData("轻量级Java EE企业应用实战"); o.getData("疯狂Java讲义"); o.out(); o.getData("疯狂Android讲义"); o.getData("疯狂Ajax讲义"); o.out(); // 调用Output接口中定义的默认方法 o.print("孙悟空", "猪八戒", "白骨精"); o.test(); // 创建一个Printer对象,当成Product使用 Product p = new Printer(); System.out.println(p.getProduceTime()); // 所有接口型的引用变量都可直接赋给Object型的变量 Object obj = p; } } ************************************************* public class ProcessArray { public void process(int[] target, Command cmd) { cmd.process(target); } } 复制代码 。。。。。。。。。。。。。。。。
这本经典、畅销的数据结构教材详细介绍了数据抽象的基础知识,强调作为面向对象方法基础原理的规范和实施之间的区别。书中使用的软件工程原则和概念以及UML图便于增强学生的理解。 ◆ 详细介绍了数据抽象,强调规范和实现之间的区别 ◆ 广泛介绍了各种面向对象的编程技术 ◆ 重点是核心的数据结构,而不是非必要的C++语言语法 ◆ 说明了和ADT在问题解决过程中的作用 ◆ 诠释了ADT的主要应用,如查找航班图、事件驱动的模拟和八皇后问题 ◆ 大部分章节中的例子都使用了标准模板库(STL) ◆ 介绍了递归 ◆ 附录中提供了基本的C++语法,以帮助学生从其他语言转换为C++ 第1章 数据抽象:墙 1 1.1 面向对象的概念 2 1.1.1 面向对象分析与设计 2 1.1.2 面向对象解决方案的特征 3 1.2 获得更好的解决方案 4 1.2.1 内聚 5 1.2.2 耦合 5 1.3 规范 6 1.3.1 操作契约 7 1.3.2 特殊情况 8 1.3.3 抽象 9 1.3.4 信息隐藏 10 1.3.5 最小且完整的接口 11 1.4 抽象数据型 12 1.4.1 设计ADT 14 1.4.2 涉及其他ADT的ADT 17 1.5 ADT包 18 1.5.1 确定行为 18 1.5.2 指定数据和操作 19 1.5.3 ADT的模板接口 22 1.5.4 使用ADT包 24 C++片段1 C++ 29 C1.1 待解决的问题 30 C1.1.1 私有数据字段 31 C1.1.2 构造函数和析构函数 32 C1.1.3 方法 32 C1.1.4 防止编译错误 33 C1.2 实现解决方案 34 C1.3 模板 35 C1.4 继承 37 C1.4.1 基和派生 38 C1.4.2 重写基方法 40 C1.5 虚方法和抽象类 42 C1.5.1 虚方法 42 C1.5.2 抽象类 43 第2章 递归:镜子 45 2.1 递归解决方案 46 2.2 返回值的递归 48 2.2.1 递归值函数:n的阶乘 49 2.2.2 箱式跟踪 52 2.3 执行动作的递归 55 2.4 递归与数组 62 2.4.1 逆置数组项 63 2.4.2 折半查找 64 2.4.3 查找数组中的最大值 68 2.4.4 查找数组中第k个最小值 69 2.5 组织数据 71 2.6 更多示例 75 2.6.1 Fibonacci数列(兔子繁殖) 75 2.6.2 组织游行队伍 78 2.6.3 从n个事物中选出k个 79 2.7 递归和效率 81 第3章 基于数组的实现 91 3.1 办法 92 3.1.1 核心方法 93 3.1.2 使用大小固定的数组 93 3.2 ADT包的基于数组的实现 94 3.2.1 头文件 95 3.2.2 定义核心方法 96 3.2.3 测试核心方法 98 3.2.4 实现更多方法 101 3.2.5 删除项的方法 103 3.2.6 测试 106 3.3 在实现中使用递归 107 3.3.1 getIndexOf方法 107 3.3.2 getFrequencyOf方法 108 C++片段2 指针、多态和内存分配 113 C2.1 变量的内存分配和方法的前期绑定 114 C2.2 需要解决的问题 115 C2.3 指针与程序的自由存储 116 C2.3.1 释放内存 118 C2.3.2 避免内存泄漏 119 C2.3.3 避免悬挂指针 122 C2.4 虚方法和多态 124 C2.5 数组的动态分配 126 第4章 基于链表的实现 129 4.1 预备知识 130 4.2 ADT包的基于链表的实现 133 4.2.1 头文件 134 4.2.2 定义核心方法 135 4.2.3 实现更多方法 138 4.3 在基于链表的实现中使用递归 143 4.4 测试多个ADT实现 145 4.5 比较基于数组的实现和基于链表的实现 148 第5章 作为问题求解技术的递归 155 5.1 定义语言 156 5.1.1 语法知识基础 156 5.1.2 两种简单的语言 158 5.2 代数表达式 160 5.2.1 代数表达式的型 160 5.2.2 前缀表达式 162 5.2.3 后缀表达式 166 5.2.4 完全括号化表达式 168 5.3 回溯 168 5.3.1 查找航线 168 5.3.2 八皇后问题 173 5.4 递归和数学归纳法的关系 179 5.4.1 递归阶乘函数的正确性 179 5.4.2 Hanoi塔的工作量 180 第6章 栈 189 6.1 ADT栈 190 6.1.1 在设计解决方案期间开发ADT 190 6.1.2 ADT栈的规范 192 6.2 栈的简单应用 197 6.2.1 检查括号匹配 197 6.2.2 识别语言中的字符串 199 6.3 栈在代数表达式中的应用 200 6.3.1 计算后缀表达式 201 6.3.2 中缀表达式与后缀表达式的等价转换 202 6.4 使用栈查找航班图 205 6.5 栈和递归的关系 212 C++片段3 异常 221 C3.1 背景知识 222 C3.2 断言 223 C3.3 抛出异常 224 C3.4 处理异常 227 C3.4.1 多个catch块 228 C3.4.2 未捕获的异常 229 C3.5 程序员定义的异常 232 第7章 实现ADT栈 235 7.1 基于数组的实现 236 7.2 基于链表的实现 239 7.3 在实现中使用异常 243 第8章 列表 247 8.1 指定ADT列表 248 8.2 使用列表操作 252 8.3 ADT列表的模板接口 255 第9章 实现列表 259 9.1 基于数组的ADT列表实现 260 9.1.1 头文件 261 9.1.2 实现文件 262 9.2 基于链表的ADT列表实现 266 9.2.1 头文件 266 9.2.2 实现文件 268 9.2.3 在LinkedList的方法中使用递归 275 9.3 两种实现的比较 279 第10章 算法的效率 283 10.1 什么是好的解决方案 284 10.2 测量算法的效率 285 10.2.1 算法的执行时间 286 10.2.2 算法增长率 287 10.2.3 分析与大O表示法 288 10.2.4 正确分析问题 291 10.2.5 查找算法的效率 293 第11章 排序算法及其效率 299 11.1 基本排序算法 300 11.1.1 选择排序 300 11.1.2 起泡排序 303 11.1.3 插入排序 305 11.2 较快排序算法 307 11.2.1 归并排序 307 11.2.2 快速排序 312 11.2.3 基数排序 319 11.3 各种排序算法的比较 321 C++片段4 关系和重用 325 C4.1 回顾继承 326 C4.1.1 的公有、私有和受保护部分 331 C4.1.2 公有、私有和受保护继承 332 C4.1.3 is-a和as-a关系 333 C4.2 包含:has-a关系 334 C4.3 回顾抽象基 335 第12章 有序表及其实现 339 12.1 指定ADT有序表 340 12.1.1 ADT有序表的模板接口 342 12.1.2 使用有序表的操作 343 12.2 基于链表的实现 344 12.2.1 头文件 344 12.2.2 实现文件 345 12.2.3 基于链表的实现的效率 348 12.3 使用ADT列表的实现 348 12.3.1 包含 349 12.3.2 公有继承 352 12.3.3 私有继承 356 第13章 队列和优先队列 363 13.1 ADT队列 364 13.2 ADT队列的简单应用 367 13.2.1 读取字符串 367 13.2.2 识别回文 368 13.3 ADT优先队列 369 13.4 应用:模拟 371 13.5 面向位置和面向值的ADT 379 第14章 队列和优先队列的实现 387 14.1 ADT队列的实现 388 14.1.1 使用ADT列表的实现 388 14.1.2 基于链表的实现 390 14.1.3 基于数组的实现 394 14.1.4 比较实现 399 14.2 ADT优先队列的实现 400 C++片段5 运算符重载和友元访问 405 C5.1 重载运算符 406 C5.1.1 重载=进行赋值 408 C5.1.2 重载+进行连接 410 C5.2 友元访问和<<的重载 411 第15章 树 415 15.1 术语 416 15.1.1 树的型 417 15.1.2 树的高度 419 15.1.3 满二叉树、完全二叉树和平衡二叉树 421 15.1.4 二叉树的最大和最小高度 422 15.2 ADT二叉树 425 15.2.1 二叉树的遍历 425 15.2.2 二叉树的操作 428 15.2.3 ADT二叉树的模板接口 430 15.3 ADT二叉查找树 432 15.3.1 二叉查找树的操作 433 15.3.2 查找二叉查找树 434 15.3.3 创建二叉查找树 435 15.3.4 遍历二叉查找树 437 15.3.5 二叉查找树操作的效率 437 第16章 树的实现 443 16.1 二叉树中的节点 444 16.1.1 基于数组的表示 444 16.1.2 基于链表的表示 446 16.2 ADT二叉树基于链表的实现 447 16.2.1 头文件 447 16.2.2 实现 450 16.3 ADT二叉查找树基于链表的实现 458 16.3.1 ADT二叉查找树操作的算法 458 16.3.2 BinarySearchTree 469 16.4 在文件中保存二叉查找树 471 16.5 树排序 474 16.6 一般树 474 C++片段6 迭代器 479 C6.1 迭代器 480 C6.1.1 常见的迭代器操作 481 C6.1.2 使用迭代器操作 482 C6.1.3 实现迭代器 483 C6.2 迭代器的高级功能 485 第17章 堆 489 17.1 ADT堆 490 17.2 堆的基于数组的实现 493 17.2.1 基于数组的堆操作的算法 494 17.2.2 实现 498 17.3 ADT优先队列的堆实现 502 17.4 堆排序 504 第18章 字典及其实现 511 18.1 ADT字典 512 18.2 可能的实现 517 18.2.1 ADT字典的基于数组的有序实现 519 18.2.2 ADT字典的二叉查找树实现 521 18.3 选择实现 523 18.4 散列 529 18.4.1 散列函数 532 18.4.2 解决冲突 534 18.4.3 散列的效率 539 18.4.4 如何确立散列函数 542 18.4.5 字典遍历:散列的低效操作 543 18.4.6 使用散列和分离链实现ADT字典 544 第19章 平衡查找树 551 19.1 平衡查找树 552 19.2 2-3树 553 19.2.1 遍历2-3树 555 19.2.2 查找2-3树 556 19.2.3 在2-3树中插入数据 558 19.2.4 从2-3树中删除数据 562 19.3 2-3-4树 567 19.3.1 查找和遍历2-3-4树 569 19.3.2 在2-3-4树中插入数据 569 19.3.3 从2-3-4树中删除数据 572 19.4 红-黑树 573 19.4.1 查找和遍历红-黑树 575 19.4.2 红-黑树的插入和删除 575 19.5 AVL树 577 第20章 图 583 20.1 术语 584 20.2 将图作为ADT 587 20.3 图的遍历 591 20.3.1 深度优先查找 592 20.3.2 广度优先查找 593 20.4 图的应用 595 20.4.1 拓扑排序 595 20.4.2 生成树 598 20.4.3 最小生成树 600 20.4.4 最短路径 603 20.4.5 回路 606 20.4.6 一些复杂问题 608 第21章 外部存储中的数据处理 615 21.1 了解外部存储 616 21.2 排序外部文件的数据 618 21.3 外部字典 624 21.3.1 确定外部文件的索引 626 21.3.2 外部散列 629 21.3.3 B-树 632 21.3.4 遍历 639 21.3.5 多索引 640 C++片段7 标准模板库 647 C7.1 STL容器 648 C7.1.1 STL容器适配器 649 C7.1.2 顺序容器 650 C7.1.3 关联容器 654 C7.2 STL算法 657 附录A 回顾C++基础 659 附录B 编程中的重要主题 697 附录C 统一建模语言 719 附录D 软件生命周期 727 附录E 数学归纳法 733 附录F 算法验证 737 附录G C++文件基础 741 附录H C++头文件和标准函数 751 附录I C++文档系统 755 附录J ASCII字符代码 757 附录K 针对Java编程人员的C++知识 759 附录L 针对Python编程人员的C++知识 767

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值