接口与数据结构北京理工大学计算机系 金旭亮第七讲
2009-7-29 北京理工大学计算机系 (共 38页) 2
本讲内容接口与内部类基本数据结构第一部分 接口与内部类
2009-7-29 北京理工大学计算机系 (共 38页) 4
什么是接口(一)
引例:
鸭子是一种鸟,又是一种食物,如何在面向对象的程序中表达这种关系?
2009-7-29 北京理工大学计算机系 (共 38页) 5
什么是接口?(二)
public interface IFood {
public void Cook(Object o);
}
Public class Duck implements IFood{
public void Cook(Object o) {
……
}
……
}
2009-7-29 北京理工大学计算机系 (共 38页) 6
使用接口
IFood f=new Duck();
格式:
接口类型的变量=
new 实现了接口的子类类型();
2009-7-29 北京理工大学计算机系 (共 38页) 7
接口的含义
“所有实现本接口的 classes,看起来都应该象这样 ……”
定义一个接口,采用关键字 interface,实现一个接口,采用关键字 implements
2009-7-29 北京理工大学计算机系 (共 38页) 8
接口的要点接口的成员函数自动成为 public的,数据成员自动成为 static和 final的。
如果接口不声明为 public的,则自动变为
friendly,仅包内组件可以使用。
2009-7-29 北京理工大学计算机系 (共 38页) 9
接口的特性接口是一种抽象类,它的所有方法都是抽象方法;
接口的定义:用 interface取代 Class
接口的实现,实现接口的类不从该接口的定义中继承任何行为,在实现该接口的类的任何对象中都能够调用它这个接口中定义的方法,在实现的过程中,这个类还可以同时实现其他接口。
2009-7-29 北京理工大学计算机系 (共 38页) 10
接口多态使用接口名称作为一个引用变量的类型,
该引用变量可以用来指向任何实现了该接口的类的实例。使用时将根据动态连接的原则,视该变量所指向的具体实例进行操作。
这是多态特性的一个体现。(举例说明)
接口的使用是 Java OOP的重要核心之一,
要好好理解和掌握。
2009-7-29 北京理工大学计算机系 (共 38页) 11
接口的扩充可以通过继承接口来扩充已有接口,并形成一个新的接口。
interface OneInterface {
void f1();
}
interface TwoInterface extends OneInterface {
void f2();
}
2009-7-29 北京理工大学计算机系 (共 38页) 12
利用接口定义常量
public interface ArrayBound {
public static final int LOWBOUND=1;
public static final int UPBOUND=100;
}
只要一个类声明实现了这个接口,就可以直接使用这些常量名注意:这些常量必须被初始化。(为什么?)
2009-7-29 北京理工大学计算机系 (共 38页) 13
接口与抽象类的区别抽象类是一个不完全的类,需要进一步专业化。接口只是一个行为的规范或规定。
接口基本上不具备继承的任何具体特点,
它仅仅承诺了能够调用的方法。
一个类一次可以实现若干个接口,但一个类只能扩展一个父类。
接口的应用
2009-7-29 北京理工大学计算机系 (共 38页) 15
编程技巧:回调原理什么叫回调?( CallBack)
事件驱动系统的面向对象原理循环测试 vs 事件驱动
.net示例展示(多个窗体同时响应主窗体)
2009-7-29 北京理工大学计算机系 (共 38页) 16
用接口实现回调( 1)
1.定义一个接口,其中承诺的方法为 run():
public interface Runable {
public void run();
}
2.某个类中现在可以提供一个方法 useIntefaceArgu,接收一个 Runnable接口类型的参数:
void useIntefaceArgu(Runnable r){
r.run();
}
//注意:此类并不需要实现 Runable接口
2009-7-29 北京理工大学计算机系 (共 38页) 17
用接口实现回调( 2)
3,创建一个类实现 Runnable接口:
class myCode implements Runnable {
public void run() {
//一些代码
}
}
//此方法就是给其它人调用的,相当于:“我提供了一个 run方法,你在需要时就可以用,我不知道你什么时候用,但你用时我总有”,
2009-7-29 北京理工大学计算机系 (共 38页) 18
用接口实现回调( 3)
4.把 myCode对象传递给 useIntefaceArgu ()
方法:
myCode myobj=new myCode();
vitalSystemThing(myobj);
//可以把任何一个实现了 Runnable 接口的对象作为参数传入。
2009-7-29 北京理工大学计算机系 (共 38页) 19
回调实例,定时调用类的方法
TimerTest.java
java.swing.Timer类构造函数
Timer( int interval,ActionListener listener)
ActionListener接口,要求实现以下方法:
public void actionPerformed(ActionEvent
event)
2009-7-29 北京理工大学计算机系 (共 38页) 20
对象的比较,Comparable接口
Public interface Comparable
{
int compareTo(Object other)
}
两对象相等,返回 0,X小于 Y,返回负数
X大于 Y,返回正数现场编程展示
2009-7-29 北京理工大学计算机系 (共 38页) 21
泛型化的 Comparable接口
public inteface Comparable<T>
{
int compareTo(T other);
}
编程实例,EmployeeSortTest.java
2009-7-29 北京理工大学计算机系 (共 38页) 22
对象的复制,Cloneable接口对象复制的含义
Cloneable接口没有任何成员,是一个标记接口。
思索:为什么 Java要引入标记接口?
Object类提供了一个 protected clone()方法,
子类必须重新将其定义为 public的。
2009-7-29 北京理工大学计算机系 (共 38页) 23
对象复制实例
CloneTest.java
内部类(内嵌类)
2009-7-29 北京理工大学计算机系 (共 38页) 25
内嵌类的定义(一)
嵌套静态类:一个声明为 static的嵌套类。
这不是一个内部类,其作用如同顶级类:
class Top {
static class MyNested {...}
}
2009-7-29 北京理工大学计算机系 (共 38页) 26
内嵌类的使用嵌套静态类:不能访问其外嵌类的对象的实例数据。
代码实例,innerclass1.java
可运行实例,StaticInnerClassTest.java
2009-7-29 北京理工大学计算机系 (共 38页) 27
内嵌类的定义(二)
成员类,实际上是声明为类的成员。
class Top {
class MyNested {...}
}
2009-7-29 北京理工大学计算机系 (共 38页) 28
内嵌类的使用成员类:不带有 static关键字。可以引用父类中的任何成员。在能够调用内部类的方法,以及为其数据字段赋值之前,父类必须首先声明内部类的实例,
代码实例,innerclass2.java
可运行实例,InnerClassTest.java
2009-7-29 北京理工大学计算机系 (共 38页) 29
内嵌类的定义(三)
本地类:在一个方法中声明
void foo() {
class Mylocal {...}
}
2009-7-29 北京理工大学计算机系 (共 38页) 30
内嵌类的使用本地类:在方法中声明。
实例,innerclass3.java
2009-7-29 北京理工大学计算机系 (共 38页) 31
内嵌类的定义(四)
匿名类:在表达式中声明,没有类变量。
void foo() {
JFrame jf=new JFrame();
jf.addKeyListener(
new KeyAdapter {
public void keyPressed(keyEvent k) {...}
}
);
}
2009-7-29 北京理工大学计算机系 (共 38页) 32
内嵌类的使用匿名类:在表达式中定义;
代码实例,innerclass4.java
可运行实例:
AnonymousInnerClassTest.java
2009-7-29 北京理工大学计算机系 (共 38页) 33
内嵌类的好处一旦建立一个 inner class,其对象便拥有了对其外围数据的访问权。
2009-7-29 北京理工大学计算机系 (共 38页) 34
古怪的对象创建
public class Parcell {
class Contents {...}
public static void main(String[ ])
{
Parcell p=new Parcell();
Parcell.Contents c=p.new Contents();
}
} NOTE:这种语法其它 OO语言是没有的,尽量避免使用这种语法。
2009-7-29 北京理工大学计算机系 (共 38页) 35
内部类编译以后 …
每个 inner class都会产生一个,class文件。
内部类编译之后的文件名规范:
外部类名 $内部类名,class
2009-7-29 北京理工大学计算机系 (共 38页) 36
内部类的应用使用内部类实现键盘和鼠标事件驱动第二部分 数据结构
2009-7-29 北京理工大学计算机系 (共 38页) 38
Self-Referential Classes
Self-referential class(自引用类)
– 包含一个指向本类对象的数据成员
class Node {
private int data;
private Node nextNode;
// constructors and methods,..
}
2009-7-29 北京理工大学计算机系 (共 38页) 39
链表( Linked Lists)
实例:
List.java EmptyListException.java
ListTest.java
2009-7-29 北京理工大学计算机系 (共 38页) 40
堆栈( Stacks)
后进先出实例:
( 1) StackInheritance.java
StackInheritanceTest.java
( 2) StackComposition.java
StackCompositionTest.java
2009-7-29 北京理工大学计算机系 (共 38页) 41
从堆栈实例中得到 ……
OOP的两种基本思路之一:组合。
2009-7-29 北京理工大学计算机系 (共 38页) 42
OOP的两种基本思路之一:继承从堆栈实例中得到 ……
2009-7-29 北京理工大学计算机系 (共 38页) 43
队列( Queues)
先进先出实例:
QueueInheritance.java
QueueInheritanceTest.java
作业:
分析以上实例,绘出 UML图。
队列能否用组合来实现?请试一试。
2009-7-29 北京理工大学计算机系 (共 38页) 44
树的知识二叉排序树的特点:左子树,右子树,根节点树的遍历
– Inorder traversal(中序)
Traverse left subtree,obtain node value,traverse right
subtree
– Preorder traversal(前序)
Obtain node value,traverse left subtree,traverse right
subtree
– Postorder traversal(后序)
Traverse left subtree,traverse right subtree,obtain node
value
2009-7-29 北京理工大学计算机系 (共 38页) 45
用自引用类对象实现树
Class Tree
{
private Object data;
private Tree left;
private Tree right;

}
2009-7-29 北京理工大学计算机系 (共 38页) 46
课外作业用 Java编写树的三种遍历方式,并在屏幕上输出。
Java提供了一种动态数组类,Vector,请同学们自学此类,并尝试自己用它来编写一个树。
2009-7-29 北京理工大学计算机系 (共 38页) 47
程序阅读实践阅读 Java实例,DrawingShapes