当前位置:文档之家› 包、接口和事件

包、接口和事件

包、接口和事件
包、接口和事件

包、接口和事件

【课前思考】

1.什么是包?如何创建和使用包?

2.什么是接口?如何声明和实现接口?

2.在Java中如何处理事件?JDK1.0和JDK2.0处理事件有什么不同?

【学习目标】

掌握如何创建和使用包,了解接口的概念,掌握接口的声明及其实现,理解在Java中如何处理事件,掌握AWT各个组件所采用的事件处理接口。

【学习指南】

理解概念,多实践,勤思考,举一反三。

【难重点】

重点:

接口的用法。

难点:

组件所采用的事件处理接口。

9.1 包

利用面向对象技术开发一个实际的系统时,通常需要定义许多类共同工作,为了更好地管理这些类,Java中引入了包的概念。就像文件夹(目录)把各种文件组织在一起,使硬盘更清晰、有条理一样,Java中的包把各种类组织在一起,使得程序功能清楚、结构分明。特别地,使用包可以有利于实现不同程序间类的复用。

包是一种松散的类的集合。一般不要求处于同一个包中的类有明确的相互关系,如包含、继承等,但是由于同一包中的类在缺省情况下可以互相访问,所以为了方便编程和管理,通常把需要在一起工作的类放在一个包里。

Java系统中包括io、lang、applet、awt、math、net、rmi、security、text、sql、util、beans 等包。

9.1.1创建包

在缺省情况下,系统会为每一个.java源文件创建一个无名包,该.java文件中定义的所有类都隶属于这个无名包,它们之间可以相互引用非private的属性或方法。但是由于这个无名包是没有名字的,所以它不能被其他包所引用,即无名包中的类不能被其他包中的类所引用和复用。为了解决这个问题,可以创建有名字的包。

创建包的语句需要使用关键字package,而且应该是整个.java文件的第一个语句。

package 包名;

利用这个语句就可以创建一个具有指定名字的包,当前 .java文件中的所有类都被放在这个包中。例如下面的语句是合法的创建包的语句:

package StudentClass;

package StudentClass.SubClass;

实际上,创建包就是在当前文件夹下创建一个子文件夹,以便存放这个包中包含的所有类的 .class文件。上面的第二个创建包的语句中的符号“.”代表了目录分隔符,即这个语句创建了两个文件夹。第一个是当前文件夹下的子文件夹StudentClass;第二个是StudentClass下的子文件夹SubClass,当前包中的所有类就存放在这个文件夹里。

【例9-1】

package com.StudentClass;

public class specialStudent{

public static void main(String args[]){

System.out.println("Hello package");

}

}

运行过程:(假设文件存放在D:\Code中)

D:\code> javac –d . specialStudent.java(备注:运行此命令后在code文件夹中生成了code\com\StudentClass\specialStudent.class)

D:\code> java –cp . com.StudentClass.specialStudent

运行结果:Hello package

9.1.2包的引用

将类组织成包的目的是为了更好地利用包中的类。通常一个类只能引用与它在同一个包中的类。如果需要使用其他包中的public类,则可以使用如下的几种方法。

1. 使用包名、类名前缀

一个类要引用其他的类,无非是继承这个类或创建这个类的对象并使用它的属性、调用它的方法。对于同一包中的其他类,只需在要使用的属性或方法名前加上类名作为前缀即可;对于其他包中的类,则需要在类名前缀的前面再加上包名前缀。例如:

【例9-2】

/* Students.java*/

package StudentClass;

public class Students{

private int StudentNo;

public Students(int i){

setStudentNo(i);

}

protected void setStudentNo(int i){

StudentNo=i;

}

public int getStudentNo(){

return StudentNo;

}

}

/* UsingStudentClass.java*/

public class UsingStudentClass{

public static void main(String[] args){

StudentClass.Students MyObj=new StudentClass.Students(2);

System.out.println("Using Students "+MyObj.getStudentNo());

}

}

运行过程:(假设文件存放在D:\Code中)

D:\code> javac –d . Students.java(备注:运行此命令后在code文件夹中生成了code\ StudentClass\Students.class)

D:\code> javac UsingStudentClass.java

D:\code> java UsingStudentClass

运行结果:Using Students 2

2. 加载需要使用的类

如果使用上面的方法,每当类名出现时都必须附加一个包名的前缀,编程中使用起来非常麻烦。一个解决的方法是在程序文件的开始部分利用import语句将需要使用的整个类加载到当前程序中,这样在程序中需要引用这个类的地方就不需要再使用包名作为前缀。例如上面的程序,在程序开始处增加了:

【例9-3】

/* UsingStudentClass.java*/

import StudentClass.Students;

public class UsingStudentClass{

public static void main(String[] args){

Students MyObj=new Students(2);

System.out.println("Using Students "+MyObj.getStudentNo());

}

}

运行过程:(假设文件存放在D:\Code中)

D:\code> del Students.java (备注:必须删除目录下的Students.java,即确保没有类库的.JAVA文件)

D:\code> javac UsingStudentClass.java

D:\code> java UsingStudentClass

运行结果:Using Students 2

3. 加载整个包

上面的方法利用import语句加载了其他包中的一个类。有些情况下可以直接利用import语句引入整个包,此时这个包中的所有类都会被加载到当前程序中。加载整个包的import语句可以写为:

import StudentClass.*;

import java.awt.*;

上面的第二个语句在前面的例子中已多次使用,它的作用是把Java系统有关抽象窗口工具的包(系统类库)加载到当前程序中。与加载单个类相同,加载整个包后,凡是用这个包中的类,都不需要再使用包名前缀。

【例9-3】

//:myVector.java

package https://www.doczj.com/doc/7615455321.html,1.simple;

public class myVector{

public myVector() {

System.out.println("https://www.doczj.com/doc/7615455321.html,1.simple.myVector");

}

}

//:myList.java

package https://www.doczj.com/doc/7615455321.html,2.simple;

public class myList{

public myList() {

System.out.println("https://www.doczj.com/doc/7615455321.html,2.simple.myList");

}

}

//:LibTest.java

import https://www.doczj.com/doc/7615455321.html,1.simple.*;

import https://www.doczj.com/doc/7615455321.html,2.simple.*;

public class LibTest{

public static void main(String[] args) {

myVector v = new myVector();

myList l = new myList();

}

}

运行过程:(假设文件存放在D:\Code中)

D:\code> javac –d . myVector.java(备注:运行此命令后在code文件夹中生成了code\

com\name1\simple\myVector.class)

D:\code> javac –d . myList.java(备注:运行此命令后在code文件夹中生成了code\ com\name2\simple\myList.class)

D:\code> del myVector.java (备注:必须删除目录下的myVector.java,即确保没有类库的.JAVA文件)

D:\code> del myList.java (备注:必须删除目录下的myVector.java,即确保没有类库的.JAVA文件)

D:\code> javac LibTest.java

D:\code> java LibTest

运行结果:

https://www.doczj.com/doc/7615455321.html,1.simple.myVector

https://www.doczj.com/doc/7615455321.html,2.simple.myList

引用方法比较:

(1)使用包名做前缀的方法使得程序清晰,很容易看出所使用的类所于哪个包中。(2)使用包引入的方法会给名字带来冲突,如A包中有类k.class,B包中也有类k.class,因为程序无法知道所要使用的究竟是哪个k.class,会引起编译错误,而使用包名做前缀的方法不会存在这样的问题。

(3)使用包名做前缀的方法书写程序的时候非常麻烦,特别是在大量使用其它包中类的时候,而使用import语句引入包则使得程序书写简单化。

【例9-4】

//:k.java

package com.A;

public class k{

public k() {

System.out.println("Hello A.K");

}

}

//:k.java

package com.B;

public class k{

public k() {

System.out.println("Hello B.K");

}

}

//:Test.java

import com.A.*;

import com.B.*;

public class Test{

public static void main(String[] args) {

k test1= new k();

}

}

D:\code> javac –d . k.java(备注:运行此命令后在code文件夹中生成了code\

com\A\k.class)

D:\code> javac –d . k.java(备注:运行此命令后在code文件夹中生成了code\ com\B\k.class)

D:\code> del k.java (备注:必须删除目录下的k.java,即确保没有类库的.JAVA文件)D:\code> javac Test.java(备注:出错,系统提示对 k 的引用不明确)

//:Test.java

public class Test{

public static void main(String[] args) {

com.A.k test1= new com.A.k();

com.B.k test2= new com.B.k();

}

}

运行结果:

Hello A.K

Hello B.K

4. CLASSPATH

包是一种组织代码的有效手段,包名实际上就指出了程序中需要使用的.class文件的所在之处。另一个能指明.class文件目录所在的结构是环境变量CLASSPATH。CLASSPATH类似于DOS操作系统中的PATH,它指明了所有缺省的类字节码文件路径,当一个程序找不到它所需使用的其他类的.class文件时,系统会自动到CLASSPATH环境变量所指明的路径中去寻找。

设置CLASSPATH环境变量可以通过编辑系统的AUTOEXEC.BAT文件,或使用相关的DOS 命令。例如最常见的CLASSPATH设置语句:

SET CLASSPATH= .; c:\jdk1.2\lib\dt.jar;c:\jdk1.2\lib\tools.jar;

9.2 接口

接口(interface)在有些资料上称为界面。Java的接口与包相似,也是用来组织应用中的各类并调节它们的相互关系的一种结构。更准确地说,接口是用来实现类间多重继承功能的结构。

Java中的接口在语法上有些相似于类,它定义了若干个抽象方法和常量,形成一个属性集合,该属性集合通常对应了某一组功能,其主要作用是可以帮助实现类似于类的多重继承的功能。

所谓多重继承,是指一个子类可以有一个以上的直接父类,该子类可以继承它所有直接父类的成员。某些面向对象的语言,如C++,提供多重继承的语法级支持,而在Java中,出于简化程序结构的考虑,不再支持类间的多重继承而只支持单重继承,即一个类至多只能有一个直接父类。然而在解决实际问题的过程中,仅仅依靠单重继承在很多情况下都不能将问题的复杂性表述完整,需要其他的机制作为辅助。

由于Java只支持单重继承,所以Java程序中的类层次结构是树状结构,这种树状结构在处理某些复杂问题时会显得力不从心。同时随着类结构树的生长,越是处在下层的子类,它的间接父类(间接父类是直接父类的父类,即祖先)越多,所继承的方法也会越来越多,造成子类成员的膨胀、庞杂,难以管理和掌握。

为了使Java程序的类层次结构更加合理,更符合实际问题的本质,编程者可以把用于完成特定功能的若干属性组织成相对独立的属性集合;凡是需要实现这种特定功能的类,都可以继承这个属性集合并在类内使用它,这种属性集合就是接口。

需要特别说明的是,Java中一个类获取某一接口定义的功能,并不是通过直接继承这个接口中的属性和方法来实现的。因为接口中的属性都是常量,接口中的方法都是没有方法体的抽象方法。也就是说,接口定义的仅仅是实现某一特定功能的一组功能的对外接口和规范,而并没有真正地实现这个功能,这个功能的真正实现是在“继承”这个接口的各个类中

完成的,要由这些类来具体定义接口中各抽象方法的方法体。因而在Java中,通常把对接口功能的“继承”称为“实现”。

9.2.1声明接口

Java中声明接口的语法如下:

[public] interface 接口名[extends 父接口名列表]

{ // 接口体

// 常量域声明

[public][static][final]属性类型属性名 = 常量值;

// 抽象方法声明

[public][abstract][native]返回值方法名( 参数列表 ) [throw 异常列表];

}

从上面的语法规定可以看出,定义接口与定义类非常相似。实际上完全可以把接口理解成为一种特殊的类,接口是由常量和抽象方法组成的特殊类。一个类只能有一个父类,但是它可以同时实现若干个接口。这种情况下如果把接口理解成特殊的类,那么这个类利用接口实际上就获得了多个父类,即实现了多重继承。

就像class是声明类的关键字一样,interface是接口声明的关键字,它引导着所定义的接口的名字,这个名字应该符合Java对标识符的规定。与类定义相仿,声明接口时也需要给出访问控制符,不同的是接口的访问控制符只有public一个。用public修饰的接口是公共接口,可以被所有的类和接口使用,而没有public修饰符的接口则只能被同一个包中的其他类和接口利用。

与类相仿,接口也具有继承性。定义一个接口时可以通过extends关键字声明该新接口是某个已经存在的父接口的派生接口,它将继承父接口的所有属性和方法。与类的继承不同的是一个接口可以有一个以上的父接口,之间用逗号分隔,形成父接口列表。新接口将继承所有父接口中的属性和方法。

接口体的声明是定义接口的重要部分。接口体由两部分组成:一部分是对接口中属性的声明,另一部分是对接口中方法的声明。正如前面已经指出的,接口中的属性都是用final 修饰的常量,接口中的方法都是用abstract修饰的抽象方法。在接口中只能给出这些抽象方法的方法名、返回值和参数列表,而不能定义方法体,即仅仅规定了一组信息交换、传输和处理的“接口”。定义接口可归纳为如下几点:

①在Java中接口是一种专门的类型。用interface关键字定义接口。

②接口中只能定义抽象方法,不能有方法体,一定是public修饰的。

③接口中可以定义变量,但实际上是static final修饰的常量。

④接口中不能定义静态方法。

9.2.2 实现接口

接口的声明仅仅给出了抽象方法,相当于程序开发早期的一组协议,而具体地实现接口所规定的功能,则需某个类为接口中的抽象方法书写语句并定义实在的方法体,称为实现这个接口。

一个类要实现接口时,请注意以下问题:

(1) 在类的声明部分,用implements关键字声明该类将要实现哪些接口。

(2) 如果实现某接口的类不是abstract的抽象类,则在类的定义部分必须实现指定接口的所有抽象方法,即为所有抽象方法定义方法体,而且方法头部分应该与接口中的定义完全一致,即有完全相同的返回值和参数列表。

(3) 如果实现某接口的类是abstract的抽象类,则它可以不实现该接口所有的方法。但是对于这个抽象类任何一个非抽象的子类而言,它们父类所实现的接口中的所有抽象方法都必须有实在的方法体。这些方法体可以来自抽象的父类,也可以来自子类自身,但是不允许存在未被实现的接口方法。这主要体现了非抽象类中不能存在抽象方法的原则。

(4) 一个类在实现某接口的抽象方法时,必须使用完全相同的方法头。如果所实现的方法与抽象方法有相同的方法名和不同的参数列表,则只是在重载一个新的方法,而不是实现已有的抽象方法。

(5) 接口的抽象方法的访问限制符都已指定为public,所以类在实现方法时,必须显式地使用public修饰符,否则将被系统警告为缩小了接口中定义的方法的访问控制范围。【例9-5】

interface A{

int a=1;

}

interface B{

int b=2;

public abstract void pp();

}

interface MyInterface extends A,B{}//接口的继承

abstract class AbstractInterfaceExam implements A,B {} //抽象类实现接口

public class InterfaceExam implements A,B//一般类实现接口

{

static InterfaceExam obj = new InterfaceExam();//必须定义为静态类型,否则会出现错误无法从静态上下文中引用非静态变量obj

public static void main(String [] args){

System.out.println("继承接口A中的a=" + obj.a);

obj.pp();

}

public void pp()//实现抽象方法pp()

{

System.out.println("继承接口AB中的ab=" + obj.b);

}

}

运行结果:

继承接口A中的a=1

继承接口AB中的ab=2

【例9-6】

interface Sup_InterfaceExam{

public static final int x=1;

int y=2;

public void z();

public abstract int getz();

}

interface Sub_InterfaceExam extends Sup_InterfaceExam{

public static final int a=3;

int b=4;

public void c();

public abstract int getc();

}

public class MyClass implements Sub_InterfaceExam , Sup_InterfaceExam{

static MyClass obj = new MyClass();

public static void main(String [] args){

System.out.println("继承接口Sup_InterfaceExam中的x=" + obj.x);

System.out.println("继承接口Sup_InterfaceExam中的y=" + obj.y);

System.out.println("继承接口Sub_InterfaceExam中的a=" + obj.a);

System.out.println("继承接口Sub_InterfaceExam中的b=" + obj.b);

System.out.println("继承接口Sup_InterfaceExam中的getz() " + obj.getz());

System.out.println("继承接口Sub_InterfaceExam中的getc() " + obj.getc());

}

public void z(){}

public int getz(){

return 1;

}

public void c(){}

public int getc(){

return 5;

}

}

运行结果:

继承接口Sup_InterfaceExam中的x=1

继承接口Sup_InterfaceExam中的y=2

继承接口Sub_InterfaceExam中的a=3

继承接口Sub_InterfaceExam中的b=4

继承接口Sup_InterfaceExam中的getz() 1

继承接口Sub_InterfaceExam中的getc() 5

【例9-7】

为某研究所编写一个通用程序,用来计算每一种交通工具运行1000公里所需的时间,已知每种交通工具的参数都是3个整数A、B、C的表达式。现有两种工具:Car 和Plane,其中Car 的速度运算公式为:A*B/C,Plane 的速度运算公式为:A+B+C。需要编写三类:ComputeTime.java,Plane.java,Car007.java和接口Common.java,要求在未来如果增加第3种交通工具的时候,不必修改以前的任何程序,只需要编写新的交通工具的程序。其运行过程如下,从命令行输入ComputeTime的四个参数,第一个是交通工具的类型,第二、三、四个参数分别时整数A、B、C,举例如下:

计算Plane的时间:"java ComputeTime Plane 20 30 40"

计算Car007的时间:"java ComputeTime Car007 23 34 45"

如果第3种交通工具为Ship,则只需要编写Ship.java,运行时输入:"java ComputeTime Ship 22 33 44"

提示:充分利用接口的概念,接口对象充当参数。

实例化一个对象的另外一种办法:Class.forName(str).newInstance();例如需要实例化一个Plane对象的话,则只要调用Class.forName("Plane").newInstance()便可。

代码如下:

1. ComputTime.java 请确保输入正确,其中没有捕捉NumberFromatException

import https://www.doczj.com/doc/7615455321.html,mon;

import https://www.doczj.com/doc/7615455321.html,ng.*;

public class ComputeTime {

public static void main(String args[]) {

System.out.println("交通工具: "+args[0]);

System.out.println(" 参数A: "+args[1]);

System.out.println(" 参数B: "+args[2]);

System.out.println(" 参数C: "+args[3]);

double A=Double.parseDouble(args[1]);

double B=Double.parseDouble(args[2]);

double C=Double.parseDouble(args[3]);

double v,t;

try {

Common d=(Common) Class.forName("CalTime.vehicle."+args[0]).newInstance();

v=d.runTimer(A,B,C);

t=1000/v;

System.out.println("平均速度: "+v+" km/h");

System.out.println("运行时间:"+t+" 小时");

} catch(Exception e) {

System.out.println("class not found");

}

}

}

2.Plane.java

package CalTime.vehicle;

import https://www.doczj.com/doc/7615455321.html,mon;

public class Plane implements Common {

public double runTimer(double a, double b, double c) {

return (a+ b + c);

}

}

3. Car.java

package CalTime.vehicle;

import https://www.doczj.com/doc/7615455321.html,mon;

public class Car implements Common {

public double runTimer(double a, double b, double c) {

return ( a*b/c );

}

}

https://www.doczj.com/doc/7615455321.html,mon.java

package CalTime.vehicle.all;

public interface Common {

double runTimer(double a, double b, double c);

}

演示了接口的经典使用方法。

9.3 Java的事件处理机制

要能够让图形界面接收用户的操作,就必须给各个组件加上事件处理机制。在事件处理的过程中,主要涉及三类对象:

◇Event-事件,用户对界面操作在java语言上的描述,以类的形式出现,例如键盘操作对应的事件类是KeyEvent。

◇Event Source-事件源,事件发生的场所,通常就是各个组件,例如按钮Button。

◇Event handler-事件处理者,接收事件对象并对其进行处理的对象。

JDK1.0采用的是层次事件模型,而JDK1.1以及更高的版本采用的是委托事件模型9.3.1层次模型(JDK1.0)

层次模型是基于容器的。事件先发送到组件,然后沿容器层次向上传播。没有被组件处理的事件会自动地继续传播到组件的容器

例如,在下图中,Button对象(包含在一个Frame上的Panel中)上的鼠标点击首先向Button发送一个动作事件。如果它没有被Button处理,这个事件会被送往Panel,如果它在那儿仍然没有被处理,这个事件会被送往Frame

优点:简单,而且非常适合面向对象的编程环境。

缺点:事件只能由产生这个事件的组件或包含这个组件的容器处理;为了处理事件,你必须定义接收这个事件的组件的子类,或者在基容器创建handleEvent()方法

9.3.2委托事件模型(JDK1.1)

委托事件模型是在JDK1.1中引入的。在这个模型中,事件被送往产生这个事件的组件

每一个组件注册一个或多个称为监听者的类,这些类包含事件处理器,用来接收和处理这个事件。采用这种方法,事件处理器可以安排在与源组件分离的对象中。监听者就是实现了Listener接口的类.

优点:事件不会被意外地处理。有可能创建并使用适配器(adapter)类对事件动作进行分类。委托模型有利于把工作分布到各个类中。

缺点:不容易将JDK1.0代码移植到JDK1.1上。

引入事件处理机制后的编程基本方法如下:

①对java.awt中组件实现事件处理必须使用java.awt.event包,所以在程序开始应加入import java.awt.event.*语句。

②用如下语句设置事件监听者:事件源.addXXListener(XXListener代表某种事件监听者)。

③事件监听者所对应的类实现事件所对应的接口XXListener,并重写接口中的全部方法。这样就可以处理图形用户界面中的对应事件了。要删除事件监听者可以使用语句:

事件源.removeXXListener;

【例9-8】

import java.awt.*;

import java.applet.*;

import java.awt.event.*;

public class ActionListenerDemo extends Applet implements ActionListener{

Button b=new Button("Press Me");

public void init(){

add(b);

//设置按钮b的监听者

b.addActionListener(this);

}

//实现ActionListener接口所定义的方法actionPerformed

public void actionPerformed(ActionEvent e){

showStatus("Button Clicked"); //改变底部状态栏

}

}

java.util.EventObject类是所有事件对象的基础父类,所有事件都是由它派生出来的。AWT的相关事件继承于java.awt.AWTEvent类,这些AWT事件分为两大类:低级事件和高级事件,低级事件是指基于组件和容器的事件,当一个组件上发生事件,如:鼠标的进入,点击,拖放等,或组件的窗口开关等,触发了组件事件。高级事件是基于语义的事件,它可以不和特定的动作相关联,而依赖于触发此事件的类,如在TextField中按Enter键会触发ActionEvent事件,滑动滚动条会触发AdjustmentEvent事件,或是选中项目列表的某一条就会

触发ItemEvent事件。

◇低级事件

ComponentEvent(组件事件:组件尺寸的变化,移动)

ContainerEvent(容器事件:组件增加,移动)

WindowEvent(窗口事件:关闭窗口,窗口闭合,图标化)

FocusEvent(焦点事件:焦点的获得和丢失)

KeyEvent(键盘事件:键按下、释放)

MouseEvent(鼠标事件:鼠标单击,移动)

◇高级事件(语义事件)

ActionEvent(动作事件:按钮按下,TextField中按Enter键)

AdjustmentEvent(调节事件:在滚动条上移动滑块以调节数值)

ItemEvent(项目事件:选择项目,不选择"项目改变")

TextEvent(文本事件,文本对象改变)

例如,与键盘事件KeyEvent相对应的接口是:

public interface KeyListener extends EventListener {

public void keyPressed(KeyEvent ev);

public void keyReleased(KeyEvent ev);

public void keyTyped(KeyEvent ev);

}

注意到在本接口中有三个方法,那么java运行时系统何时调用哪个方法?其实根据这三个方法的方法名就能够知道应该是什么时候调用哪个方法执行了。当键盘刚按下去时,将调用keyPressed( )方法执行,当键盘抬起来时,将调用keyReleased( )方法执行,当键盘敲击一次时,将调用keyTyped( )方法执行。

又例如窗口事件接口:

public interface WindowListener extends EventListener{

public void windowClosing(WindowEvent e);

//把退出窗口的语句写在本方法中

public void windowOpened(WindowEvent e);

//窗口打开时调用

public void windowIconified(WindowEvent e);

//窗口图标化时调用

public void windowDeiconified(WindowEvent e);

//窗口非图标化时调用

public void windowClosed(WindowEvent e);

//窗口关闭时调用

public void windowActivated(WindowEvent e);

//窗口激活时调用

public void windowDeactivated(WindowEvent e);

//窗口非激活时调用

}

AWT的组件类中提供注册和注销监听器的方法:

◇注册监听器:

public void add (listener);

◇注销监听器:

public void remove (listener);

例如Button类:

public class Button extends Component {

……

public synchronized void addActionListener(ActionListener l);

public synchronized void removeActionListener(ActionListener l);

……}

实现监听接口有以下几种方式:

(1)用容器类实现监听接口

可以使用容器类实现某个监听接口。由于java支持一个类实现多个接口,因此容器可以实现多个监听接口。容器中的组件将容器实例本身注册为监听器。

例子见第七章【例7-4】

(2)事件适配器--EventAdapter

下例中采用了鼠标适配器:

import java.awt.*;

import java.awt.event.*;

public class MouseClickHandler extends MouseAdaper{

public void mouseClicked(MouseEvent e) //只实现需要的方法

{ ……}

}

java.awt.event包中定义的事件适配器类包括以下几个:

1.ComponentAdapter( 组件适配器)

2.ContainerAdapter( 容器适配器)

3.FocusAdapter( 焦点适配器)

4.KeyAdapter( 键盘适配器)

5.MouseAdapter( 鼠标适配器)

6.MouseMotionAdapter( 鼠标运动适配器)

7.WindowAdapter( 窗口适配器)

【例9-9】

import java.awt.*;

import java.awt.event.*;

public class windowAdapterDemo extends Frame{

class closeWindow extends WindowAdapter{

public void windowClosing(WindowEvent e){

System.exit(0);

}

}

public windowAdapterDemo(){

setSize(200,300);

addWindowListener(new closeWindow());

show();

}

public static void main(String args[]){

windowAdapterDemo f=new windowAdapterDemo();

}

}

(3)匿名类(Anonymous Class)

当一个内部类的类声名只是在创建此类对象时用了一次,而且要产生的新类需继承于一个已有的父类或实现一个接口,才能考虑用匿名类,由于匿名类本身无名,因此它也就不存在构造方法,它需要显示地调用一个无参的父类的构造方法,并且重写父类的方法。所谓的匿名就是该类连名字都没有,只是显示地调用一个无参的父类的构造方法。

【例9-10】

import java.awt.*;

import java.awt.event.*;

public class AnonymousClass{

private Frame f;

private TextField tf;

public AnonymousClass(){

f=new Frame("Inner classes example");

tf=new TextField(30);

}

public void launchFrame(){

Label label=new Label("Click and drag the mouse");

f.add(label,BorderLayout.NORTH);

f.add(tf,BorderLayout.SOUTH);

f.addMouseMotionListener(new MouseMotionAdapter(){ //匿名类开始

public void mouseDragged(MouseEvent e){

String s="Mouse dragging: x="+e.getX()+"Y="+e.getY();

tf.setText(s);

}

} ); //匿名类结束

f.setSize(300,200);

f.setVisible(true);

}

public static void main(String args[]) {

AnonymousClass obj=new AnonymousClass();

https://www.doczj.com/doc/7615455321.html,unchFrame();

}

}

运行结果:

(4)用内部类实现监听接口

内部类(inner class)是被定义于另一个类中的类,使用内部类的主要原因是由于:◇一个内部类的对象可访问外部类的成员方法和变量,包括私有的成员。

◇实现事件监听器时,采用内部类、匿名类编程非常容易实现其功能。

◇编写事件驱动程序,内部类很方便。

因此内部类所能够应用的地方往往是在AWT的事件处理机制中。

【例9-11】

import java.awt.* ;

import java.awt.event.*;

public class InnerClass{

private Frame f;

private TextField tf;

public InnerClass(){

f=new Frame("Inner classes example");

tf=new TextField(30);

}

public void launchFrame(){

Label label=new Label("Click and drag the mouse");

f.add(label,BorderLayout.NORTH);

f.add(tf,BorderLayout.SOUTH);

f.addMouseMotionListener(new MyMouseMotionListener());/*参数为内部类对象*/

f.setSize(300,200);

f.setVisible(true);

}

class MyMouseMotionListener extends MouseMotionAdapter{ /*内部类开始*/ public void mouseDragged(MouseEvent e) {

String s="Mouse dragging: x="+e.getX()+"Y="+e.getY();

tf.setText(s);

}

}//内部类结束

public static void main(String args[]) {

InnerClass obj=new InnerClass();

https://www.doczj.com/doc/7615455321.html,unchFrame();

}

}

运行结果同上。

其实大家仔细分析一下,例9-10和9-11实现的都是完全一样的功能,只不过采取的方式不同。9-11中的事件处理类是一个内部类,而9-10的事件处理类是匿名类,可以说从类的关系来说是越来越不清楚,但是程序也越来越简练。熟悉这两种方式也十分有助于大家编写图形界面的程序。

组件与监听器的对应关系

备注:

Act=ActionListener Adj=AdjustmentListener Cmp=ComponentListener Cnt=ConatainerListener Foc=FocusListener Itm=ItemListener

Key=KeyListener Mou=MouseListener MM=MouseMotionListener Text=TextListener Win=WindowListener

06接口与内部类

1.给出如下层次图和程序片段,下列哪个命题是正确的?【选择一项】 Animal Mammal Dog Cat Raccoon Elephant (implements) (implements) ( Washer ) ( Washer ) 1. Cat sunflower; 2. Washer wawa; 3. Elephant pogo; 4. 5. sunflower = new Cat(); 6. wawa = sunflower; 7. pogo = (Elephant)wawa; A第6行导致程序编译失败。 B第7行导致程序编译失败。 C编译通过但是第7行会抛出异常。 D D.以上结果均不是。 2.下列那些命题是不正确的?【选择两项】 A JAVA程序通过接口实现多重继承。 B JAVA里面所有的异常、接口或者其他类,都从Object类扩展而来。C构造方法可以用private修饰,并且可以抛出异常。 D装箱类一共有六个。 3.下列哪些命题为假?【选择三项】 A静态方法只能被类调用,不能被实例调用。 B所有数据类型都可以用==判断恒等。 C equals()方法成立的地方,==也一定成立。 D包含抽象方法的类一定是抽象类。 4.试图编译、运行下列程序,结果是什么?【选择一项】 //Foo.java interface Foo { int k = 0; } //Test.java public class Test implements Foo {

public static void main(String[] args) { int i; Test test = new Test(); i = test.k; i = Test.k; i = Foo.k; } } A编译失败。 B编译成功。 C运行异常。 D以上结果均不是。 5.下列修饰符不能用于顶层类的是哪个【选择一项】。 A public B private C abstract D final 6.哪些命题为真?【选择两项】 A在Java中,implement用于实现接口。 B非抽象类的子类可以声明为abstract。 C超类的所有成员都将由子类继承。 D final类不可以是抽象的。 E如果类中的所有成员都声明为private,则该类不能声明为public。 7.哪些关于接口的命题为真?【选择两项】 A接口允许多重实现接口。 B接口可以被任意数目的其他接口扩展。 C接口可以扩展任意数目的其他接口。 D接口的成员变量从来不会是static。 E接口的方法总会被声明为static。 8.给出下面的程序: 1. interface Base { 2. boolean m1 (); 3. byte m2(short s); 4. } 下面哪两段代码将编译通过? 【选择两项】 A interface Base2 implements Base {} B abstract class Class2 extends Base {

类与接口的关系理解

(类是对所有事物公共的概念进行抽象的描述。)类描述了一系列在概念上有相同含义的对象,并为这些对象统一定义了编程语言上的属性和方法。对象就是一个类的实例(是某一类的具体化实例),每一个类都是具有某些共同特征的对象的抽象。 public class Car { public int number; //编号 public string color; //颜色 private string brand; //厂家 } 析构函数(前面加一个~符号): class Program { ~Program() //析?构1函?¥数oy { Console.WriteLine("析?构1函?¥数oy自á?动?¥调ì??用??"); //输o?出?一°?个?字á?符¤?串?? } static void Main(string[] args) { Program program = new Program(); //实o|ì例¤y化?¥Program对?象¨?} 接口是一种用来定义程序的协议,它描述可属于任何类或结构的一组相关行为。接口可由方法、属性、事件和索引器或这4种成员类型的任何组合构成,但不能包含字段。 C#中的类只支持单继承,但基于多继承给程序员带来的诸多方便与好处,所以通过接口可以实现多继承的功能。(以I开头命名接口名称) 一个接口实现多个类: 一个派生子类可以实现多个接口(多个接口用,隔开): class Program : IPeople, ITeacher, IStudent//多¨¤接¨?口¨2继¨?承D { string name = ""; string sex = ""; ///

///姓?名? /// public string Name { get { return name; }

java内部类练习题

内部类练习题 一、按要求填空 1.请在以下代码的基础上完成下面几个小题 (1)在①和②的位置标注出内部类和外部类 (2)在③的位置定义一个count变量用来存放Circle实例的个数,并在④的位置编写语句用来统计Circle实例的个数。 (3)在⑤和⑥处根据注释语句填写代码 (4)在main()⑦的位置上编写语句调用Draw类中的drawSahpe()。 (5)将修改后的完整代码拷贝在下方: class Circle { //① private double radius = 0; ③ public Circle(double radius) { this.radius = radius; ④ } class Draw { //② public void drawSahpe() { ⑤ //输出radius变量的值 ⑥ //输出count变量的值 } } } public class OuterInnerClass { public static void main(String[] args) { ⑦ //编写语句调用Draw类中的drawSahpe() } } 答案: class Circle { //①外部类 private double radius = 0; static int count=0; public Circle(double radius) { this.radius = radius; count++; } class Draw { //②内部类

public void drawSahpe() { System.out.println(radius); System.out.println(count); } } } public class OuterInnerClass { public static void main(String[] args) { Circle objCircle=new Circle(10); Circle.Draw objDraw=objCircle.new Draw(); objDraw.drawSahpe(); } } 2.程序填空,使程序运行结果为 30 20 10 public class Demo{ public static void main (String[] args) { Outer.Inner obj=new Outer().new Inner(); obj.show(); } } class Outer{ public int number=10; class Inner{ public int number=20; public void show() { int number=30; System.out.print( ); System.out.print( ); System.out.print( ); } } } 答案: public class Demo{ public static void main (String[] args) { Outer.Inner obj=new Outer().new Inner(); obj.show();

第五章 Java类的继承、包及接口

第5章类的继承、包及接口 在前一章的实验中已经了解了类的基本构成、对象的创建及重载方法的应用等。本章实验的任务主要是了解Java中类的继承、类包、内部类、匿名类及接口的基本构成及应用。 5.1 实验一:类的继承 1. 实验目的 1)正确理解Java中类继承基本概念及思想; 2)基本掌握继承类和被继承类(子类和父类)之间的关系,正确地创建继承类。 2. 实验要求 正确地划分类,根据类之间的关系,确定父类和子类,掌握覆盖方法的应用,完成类程序的编写与调试。 3. 实验内容 在上一章的实验中,建立了公司职员信息类,现在需要处理职员的工资信息,建立职员工资类。 实验示例5.1.1 创建职员工资类Payroll类。 实现该示例的方法步骤如下: ⑴首先分析一下该类的构成 工资信息应包括职工的基本信息,因此可以把Employers类作为Payroll类的父类,Payroll类继承了父类所有的成员变量和方法,因此在Payroll类中需要定义的内容是: ①成员变量 对于工资信息项应该包括basicWage(基本工资)、positionWage(职位工资)、extraWage(附加工资)、other(其他补贴)等等。它们均可声明为int (整数类型)。 ②成员方法 常常需要显示或获得全部或某些项工资的信息,因此需要定义如下一些方法: display() 显示工资的全部信息; display(int value) 显示一项工资额; display(int value1, int value2) 显示两项工资额。 ③构造方法 如前所述,一个类能够有多个构造对象方法,视需要而定。对Payroll类来说可以给出两个构造方法: Payroll () 构造无名对象; Payroll(String ID,String name,String sex,String birthday,String home,String address, String number,int basicWage,int positionWage,int extraWage,int other) 构造一般对象。 ⑵根据上边分析和描述,按照类的构成,给出如下类程序代码: public class Payroll extends Employers { int basicWage; //定义基本工资 int positionWage; //定义职位工资 int extraWage; //定义附加工资

匿名内部类

中的匿名内部类总结 匿名内部类也就是没有名字的内部类 正因为没有名字,所以匿名内部类只能使用一次,它通常用来简化代码编写 但使用匿名内部类还有个前提条件:必须继承一个父类或实现一个接口 实例1:不使用匿名内部类来实现抽象方法 abstract class Person { public abstract void eat(); } class Child extends Person { public void eat() { System.out.println("eat something"); } } public class Demo { public static void main(String[] args) { Person p = new Child(); p.eat(); } } 运行结果:eat something 可以看到,我们用Child继承了Person类,然后实现了Child的一个实例,将其向上转型为Person 类的引用 但是,如果此处的Child类只使用一次,那么将其编写为独立的一个类岂不是很麻烦? 这个时候就引入了匿名内部类 实例2:匿名内部类的基本实现 abstract class Person { public abstract void eat(); } public class Demo { public static void main(String[] args) { Person p = new Person() { public void eat() { System.out.println("eat something"); } }; p.eat(); } } 运行结果:eat something 可以看到,我们直接将抽象类Person中的方法在大括号中实现了 这样便可以省略一个类的书写

(2)java练习(类和接口)

1. (分值:0.7 分)Java 语言中创建一个对象使用的关键字为 A: class B: interface C: new D: create 2. (分值:0.7 分)设有对象x 具有属性a 则访问该属性的方法为 A: a.x B: a.x() C: x.a D: x.a() 3. (分值:0.7 分)以public 修饰的类如:public class Car{…} 则Car( ) A: 可被其它程序包中的类使用 B: 仅能被本程序包中的类使用 C: 不能被任意其它类使用 D: 不能被其它类继承 4. (分值:0.7 分)Java 语言中,只限子类或者同一包中的类的方法能访问的访问权限是( ) A: public B: private C: protected D: <无修饰> 5. (分值:0.7 分)有Java 语句如下,则说法正确的是()int []a,b=new int[3]; A: 此语句是错误的 B: a.length 的值为3 C: b.length 的值为3 D: a.length 和b.length 的值都为3 6. (分值:0.7 分)设有数组定义int[][] x={{1,2},{3,4,5},{6},{}};,则x.length 的值为( ) A: 3 B: 4 C: 6 D: 7 7. (分值:0.7 分)在Java 语言的java.util 包中,用于语言符号(单词)分析的类是()A: stringTokenizer B: StringTokenizer C: ToKenizer D: tokenizer 8. (分值:0.7 分)接口的所有变量和方法分别默认为是() A: final static 和public abstract B: final static 和public final C: public static 和public abstract D: public static 和public final 9. (分值:0.7 分)下列有关Java 的叙述错误的是() A: 强类型语言 B: 与平台无关

实验七 抽象类、包与接口

实验七抽象类、接口与包 一、实验目的 1、熟练掌握抽象类abstract的概念。 2、熟练掌握接口interface的概念。 3、熟练包package的概念以及编译运行的方法。 二、实验内容与要求 1.编写求解几何图形(如三角形,矩型,圆,多边型)的周长、面积的应用程序,要求用到继承、多态、抽象类、接口、内部类等面向对象程序设计技术的特点。 2、重写上面的程序,要求三角形,矩型,圆,多边型的类放到不同的包中,用包的技术组织程序的设计。同时要求程序能从键盘上接受数据以便求解不同的几何图形的周长面积。提示:从键盘上输入双精度数的一种方法(程序片段) …… public static void main(String args[]) throws IOException { BufferedReader keyin=new BufferedReader(new InputStreamReader(System.in)); String x; x=keyin.readLine(); double a=Double.parseDouble(x); …… 3.练习https://www.doczj.com/doc/7615455321.html,ng.Class类的使用,通过一个对象返回一个Class对象,如何获取一个类的名称,如何使用class生成一个类的对象。获取类的描述信息。 4.从命令行输入一个正整数,用递归的方法求出每位数字上的累加和 5、编写一个应用程序,实现以下功能: ①声明一个接口(Calculability),接口中包含一个方法area()。 ②声明一个三角形类继承该接口,类名为Triangle,类中包含两个变量、一个带参数年的构造方法和一个计算三角形面积的方法: 三角形的底边长w 三角形的高h 构造方法Triangle(double width,double height)。 计算三角形面积的方法area(),该方法覆盖接口(Calculability)的同名方法,计算三角形的面积(w*h/2)。 ③声明一个锥体类(Taper),包含一个接口对象bottom(锥体的底)和一个变量(锥体的高)height,一个带参数的构造方法,一个换底方法getbottom(),一个锥体体积的计算方法volume()。 ④声明一个主类Exp6_1,在主方法中声明接口和锥体类的对象,输出锥体的底面积和锥体的体积(bottom*height/3)。

第六讲类、对象和接口(二)

第六讲类、对象和接口(二) 1类的继承 继承是类的另一个特性。继承的意义在于:我们重复使用或更改现成的类的方法,也可以加入新的数据成员以及新的方法,以满足新环境的需要。这种技术是所有面向对象的编程语言的一个基本特征。 让我们来看一个例子:前面我们定义了一个Employee类,这只是普通员工,现在我们要定义一个经理类。经理也是员工的一种,所以Employee类中的数据和方法他也应该有;但经理又不同于普通员工,经理有秘书,而且涨工资的时候还要加上分红。怎么办?我们要不要从头开始写一个经理类? 有了继承的技术,我们可以在Employee类的基础上,编写我们的Manager类。程序如下: package teach4; import java.util.Date; class Manager extends Employee { private String secretaryName; public Manager(String n, double s, int d) { super(n, s, d); secretaryName = ""; } public void raiseSalary(double byPercent) { // add 1/2% bonus for every year of service Date today = new Date(2001,1,1); double bonus = 0.5 * (today.getYear()- getHireYear()); super.raiseSalary(byPercent + bonus); } public void setSecretaryName(String n) { secretaryName = n; } public String getSecretaryName() { return secretaryName; } } 我们以这个例子为例,学习继承的用法。 首先,请注意这个类的头部有些不同:class Manager extends Employee;其中,关键字extends是扩展的意思,表明Manager类是从Employee类继承而来。我们把Employee叫做父类或者超类,把Manager叫做子类或者衍生类。一般来说,子类比父类有更多的功能。 Manager的构造方法中有个语句:super(n, s, d),super是一个关键字,意思是调用父

java实验报告 接口、泛型、枚举、内部类与异常

实验报告 课程名称: Java程序设计成绩评定: 实验项目名称:接口、泛型、枚举、内部类与异常指导教师: 学生姓名:学号:专业班级: 实验项目类型:基础实验地点:实验时间: 一、实验目的与要求: 1、理解接口的定义与实现; 2、知道泛型、枚举型与内部类的基本应用; 3、掌握常用异常的抛出与捕获及处理. 二、实验环境:(硬件环境、软件环境) 1.硬件环境:奔ⅣPC。 2.软件环境:Windows XP 操作系统,JDK6.0。 三、实验内容:(原理、操作步骤、程序代码等) 任务: 1、按照要求完成下述接口及实现类的程序 1)定义名称为PCI()的接口,包括启动的方法start和关闭的方法stop; 2)定义名称为NetworkCard 的类表示网卡,实现PCI接口,并且其在实现start 方法时输出“sending data……”,在实现stop方法时输出“network stop.” 3)定义名称为SoundCard 的类表示声卡,实现PCI接口;并且其在实现start 方法时输出“dudu……”,在实现stop方法时输出“sound stop.” 4)定义名称为MainBoard 的类表示主板,包含方法public void usePCICard(PCI p),在方法体内通过p来启动和关闭组件; 5)定义一个包含main方法的Test类,在main方法内创建一个MainBoard 对 象用mb来引用,创建一个NetworkCard对象用nc来引用,创建一个 SoundCard对象用sc来引用,分别通过mb来使用usePCICard(PCI p)启动声 卡和网卡。 2、泛型类程序的调试 调试教材P165的程序8-2,写出程序运行结果,理解泛型类的工作机理及应用。 3、调试运行内部类程序: 在类内部再定义另外一个类,这个另外定义的类就叫内部类。调试教材P171-172程序8-3,写出程序运行结果,理解内部类的定义方法与应用。 4、异常抛出与捕获编程与调试 先调试教材P182、183中的程序9-2和9-3,写出调试结果。然后,自己编写一个能抛出并捕获、处理NullPointerException、NumberFormanException多异常的程序,并调试后写出运行结果。

面向对象--接口与抽象类、对象和接口(通俗讲解)

面向对象--接口与抽象类的恩恩怨怨 接口与抽象类是面向对象编程中两个非常重要的角色,二者各自起着非常重要的作用。但是很多初学的朋友往往会对使用接口还是抽象类存在的很大的迷惑。就我自己的一点心得,发表一下拙见。 面向对象的一些回顾: 面向对象世界中有一个古老的法则:接口隔离原则,指的是不要把多个功能全部都集中在一个接口里面。接口实现的功能要相对单一;衍生开来可以得到另外一个结论:对一组或者称一系列功能的实现,尽量定义相对功能单一的小模块来实现这一组功能。这其实也是解耦和的体现。 那这跟我们的接口和抽象类有什么关系呢?那又得摆出另外一个法则:依赖倒置原则,针对接口编程而不是针对实现编程。 说到这,又会有一个新的问题蹦出来,这是自相矛盾啊,既然要针对接口编程还要抽象类干吗使?我们经常说面向对象,面向对象是来源于生活的。是人们要把对现实世界中的一系列方法论应用到程序设计当中来。从对象这一概念的引入我们就可以揣摩这一点。人类社会中有很多对象的概念,人、车、物体。不幸的是用程序来实现这些对象比在概念上定义对象要难很多。 (如果能达成这一共识,您可以继续往下看,否则就请看官您移步至留言讨论吧) MS给出开发者的建议是,用抽象类来实现接口。子类再继承基类。 实例说明: 为什么要这么建议?OK,我们试着结合实际来说明一下这个问题吧。我们要造车。这个车有个基本的属性就是能移动、还必须有轮子。那我们就设计一个接口 1public interface ICar 2 { 3 string Wheel 4 { 5 get; 6 set; 7 } 8 void Move(); 9 } 10

接下来的事情,就是实现了。造什么车都行,继承一下就行。随着科技的发展,我们的车想要飞了。此时当然不能修改这个接口,因为要遵循开闭原则。为什么要遵循?我们可以想一下,人坐上飞机能飞上天。但是也没见谁认为人有会飞这个特性的。那也好办,不许修改,那我再加一个接口。 1interface IFlyable 2 { 3 void Fly(); 4 } 5 好,我们的飞行汽车最后应该是这样的。 1class FlyCar : ICar,IAerocraft 2 { 3 private string wheel = string.Empty; 4 5 public void Fly() 6 { 7 Console.WriteLine("{0}车飞起来了",this.wheel); 8 } 9 public string Engine 10 { 11 get 12 { 13 return wheel; 14 } 15 set 16 { 17 wheel = value; 18 } 19 } 20 21 public void Move() 22 { 23 Console.WriteLine("{0}轮车在走",this.wheel); 24 } 25 } 26 看起来很不错,车能飞能走了。那它现在他的祖宗到底车还是飞行器呢?我们自己在心里辩论一下吧。估计不是很容易辩清楚。 我们前面说过,面向对象的思想来源于现实生活。如果把这组例子引入到现实中来,造会飞的汽车。肯定是要在原有的汽车上面下功夫。比如你装上喷气动力装置,或者装上翅膀。

接口的定义及使用

1、课程名称:接口的定义及使用 2、知识点 2.1、上次课程的主要知识点 1、抽象类的设计是在普通类之上的抽象类; 2、抽象类关键的问题就是约定了子类必须要覆写的抽象方法; 3、抽象类的使用原则: ·抽象类必须有子类,子类利用extends关键字来继承抽象类,一个子类只能够继承一个父类; ·抽象类的子类(如果不是抽象类),那么必须要覆写抽象类中的全部抽象方法; ·抽象类可以利用对象的向上转型机制,通过子类对象进行实例化操作。 2.2、本次预计讲解的知识点 1、接口的基本定义以及使用形式; 2、与接口有关的设计模式的初步认识; 3、接口与抽象类的区别。

3、具体内容(★★★★★★★★★★★★★★) 接口与抽象类相比,接口的使用几率是最高的,所有的设计几乎都是围绕着接口进行的,但是要想把接口彻底闹明白,需要很长一段时间。 3.1、接口的基本概念 接口是一种特殊的类,但是在接口里面的组成与类不同,比类的组成部分简单,主要由抽象方法和全局常量所组成。而接口使用interface关键字来定义。 范例:定义一个接口 当一个接口定义完成之后,需要遵循如下的步骤进行接口的使用: ·接口一定要定义子类,子类利用implements关键字来实现接口,一个子类可以同时实现多个接口; |- 秒杀抽象类的单继承局限,一个抽象类只能够被一个子类所继承; ·接口的子类(如果不是抽象类)那么必须覆写接口中的全部抽象方法; ·接口的对象利用子类对象的向上转型进行实例化操作。 范例:使用接口

但是这个时候会有这样一种比较神奇的操作。 注意:关于接口的组成描述 接口里面在定义的时候就已经明确的给出了开发要求:抽象方法和全局常量,所以以下两种接口的定义从本质上讲是完全一样的。 如果在定义接口方法的时候没有使用public ,那么本质上也不是default 权限,而默认就是public 。 很多时候为了防止一些开发者概念不清晰,所以以后建议大家在定义接口的时候永远都写上public ,但是一般都不会去写abstract 。 现在程序之中出现有类、抽象类、接口,这几者之间的联系就需要注意好了。 一个普通类如果要实现接口又要求继承抽象类,则一定采用先extends 继承抽象类,再implements 实现接口。格式: 范例:观察子类的多继承

Java中局部内部类可以访问它所在方法中定义的final修饰(精)

public class LocalInnerClassTest{ public static void main(String[] args{ Outer obj=new Outer(; //生成一个外部类对象 SuperInner si=obj.outer(; //调用外部类中的outer(方法,返回一个SuperInner类型对象赋值给si si.m1(; //调用被覆盖的方法m1(,输出:Inner's m1( 20 } } /** *定义一个接口SuperInner,内部定义一个抽象方法m1(,无返回类型 */ interface SuperInner{ public void m1(; } /** *定义一个类Outer,内部只定义一个方法outer(,返回类型为SuperInner */ class Outer{ public SuperInner outer({ int a=10; //方法中定义一个局部变量a,并赋值为10 final int b=20; //再定义一个final局部变量b,初始化为20 class Inner implements SuperInner{ //在outer(方法中定义一个局部内部类Inner,实现接口SuperInner public void m1({ //类中只有一个覆盖接口SuperInner的方法m1(

System.out.println("Inner's m1("+a; //编译报错 System.out.println("Inner's m1( "+b; //编译通过,输出:Inner's m1( 20 } } return new Inner(; } } 我们先从主方法开始看代码的执行顺序,先生成一个Outer类对象obj,obj调用本类中方法outer(;程序开始跳到outer(方法内执行程序语句,先后生成局部变量a和b,再定义一个局部内部类Inner,返回一个SuperInner类型的对象。将返回的SuperInner类型对象地址传给SuperInner类型对象si。si再调用m1(方法,因为已经在局部内部类中覆盖了接口中的m1(方法,所以将调用局部内部类中的m1(方法,程序跳到局部内部类中m1(方法内执行程序语句,先输出一段字符串和a,结果编译报错,先将这条程序语句隐藏,执行下面的语句,你会发现编译通过而且输出Inner's m1( 20! 为什么会这样呢?大家都知道局部变量仅仅在一个范围内有效,在方法调用完就被内存释放,在Outer类对象obj调用outer(方法时,a和b才产生,调用结束后被内存释放,那么b这个值也就不复存在了,为什么还会输出20呢?难道局部变量被final修饰就不会被内存释放而保留? 其实有部分操作对于程序员是透明的,那是JAVA语言开发者的小把戏,在定义a和b 时 JVM(JAVA虚拟机做了程序员看不到的操作,他将b拷贝了一份给局部内部类,也就是说JVM在局部内部类中定义了一个final int b=20;这个操作程序员是不知道的!当调用m1(方法时输出的20并不是原来outer(方法中定义的b,而仅仅是JVM拷贝的一个副本。那么为什么a没被打印出呢?那是因为JVM并没有拷贝它,因为没有final修饰,说明它可以被修改,如果把a 改为a++,此时JVM就不知道拷贝a还是a++了,所以对于无final修饰的局部变量JVM是不会拷贝传给局部内部类的,自然无法打输出!

Java的对象、类、方法和接口

1.1什么叫对象?什么叫方法?什么叫面向对象的程序设计? 面向过程的程序设计语言最重要的特点是按照解决问题的一个一个步骤来设计程序。这种语言是与解决相对比较简单的问题,当程序规模较大时,将显得纷繁复杂。 “对象”原来是描述自然界时使用的一个词语。比如,现在我正在写讲义,桌上的稿纸、手中的笔、案头的参考书、身后的电脑以及窗外的鸟都可以成为对象面向对象,就是将世界看成由许多彼此之间能联络的对象组成。 不少程序设计语言借用了对象这个词语作为一个专用名词,此时,对象也是具有状态和行为两个特征。在程序设计中,对象的状态时相对处于静态的,用变量来描述和表达;而对象的行为时动态的,他们通过“方法”来实现和完成,所以方法一定是实现对象行为的语句块。从功能上讲,方法和子程序、函数很相似。变量和方法是彼此有关、相互依赖的。当然,计算机都是用数据来表示对象的状态的,也是通过对数据的操作和修改来体现某个方法的功能的。 1.2 Java作为面向对象的程序设计语言有什么特点? Java是面向对象的程序设计语言,从面向对象这个角度看,体现了如下三个特点: a:封装性—面向对象的程序设计语言都是把数据和处理数据的操作结合在一起而构成一个整体,这就是对象。对象的使用者只能看到对象的外部特性,比如,其主要功能、如何调用等,而看不到内部如何实现这些功能。作为面向对象的程序设计语言,程序中的数据就是变量,程序对数据作处理则成为方法。变量和方法都被封装在对象中。所以,一个对象就是变量和方法的集合,其中变量表明这个对象的状态,方法实现这个对象所具有的行为,而且在程序中将这些变量和方法进行封装,使它们成为一个模块,再用一个名字来代表这个模块。这样,以后得更高层的程序设计中,就不必关心某个对象的行为到底是怎样实现的。可见,将对象封装就是为了使模块尽可能少地展现其内部细节,而只是以一种界面来面向外部。 对象的封装性减少了程序各部分之间的依赖,使程序的复杂性降低,而可靠性提高,并便于修改。 b:继承性—面向对象的程序设计中,对象是从类创建出来的,这一点即将在下面的解答中说明。在Java中,许多类组成层次化结构。一个类的上一层成为父类,而下一层成为子类。一个类可以继承其父类的变量和方法,而且这种集成具有传递性。就是说,一个类可以继承其上一层和其再上一层的变量和方法。这种可传递的继承性使得下层多个相似的对象可以共享上层类的数据和程序代码,而子类又可以再继承父类的基础上增添新的内容和功能。这种代码共享和代码可增添的继承特性使Java既灵活又方便提高效率。 c:通信相关性—一个对象往往涉及多个行为。体现在程序设计中,一个对象往往包含多个方法,每一个方法对应一个行为。所以,一个对象完成某个动作也就是程序执行相应的方法。于是,就涉及对象之间通过交互来实现复杂的行为,这叫对象之间的通信。 利用通信可以实现一个对象往另一个对象的信息传递。信息传递设计三个要素:一是信息接收对象;二是接收对象中用哪个方法完成指定的动作;三是比方

java练习(类与接口)

1. (分值:分)Java 语言中创建一个对象使用的关键字为 A: class B: interface C: new D: create 2. (分值:分)设有对象x 具有属性a 则访问该属性的方法为 A: B: () C: D: () 3. (分值:分)以public 修饰的类如:public class Car{…} 则Car( ) A: 可被其它程序包中的类使用 B: 仅能被本程序包中的类使用 C: 不能被任意其它类使用 D: 不能被其它类继承 4. (分值:分)Java 语言中,只限子类或者同一包中的类的方法能访问的访问权限是( ) A: public B: private C: protected D: <无修饰> 5. (分值:分)有Java 语句如下,则说法正确的是()int []a,b=new int[3]; A: 此语句是错误的 B: 的值为3 C: 的值为3 D: 和的值都为3 6. (分值:分)设有数组定义int[][] x={{1,2},{3,4,5},{6},{}};,则的 值为( ) A: 3 B: 4 C: 6 D: 7 7. (分值:分)在Java 语言的包中,用于语言符号(单词)分析的类是() A: stringTokenizer B: StringTokenizer C: ToKenizer D: tokenizer 8. (分值:分)接口的所有变量和方法分别默认为是() A: final static 和public abstract B: final static 和public final C: public static 和public abstract D: public static 和public final 9. (分值:分)下列有关Java 的叙述错误的是() A: 强类型语言 B: 与平台无关

内部类详解 1、定义 一个类的定义放在另一个类的内部,这个类就叫做内部类

内部类详解 1、定义 一个类的定义放在另一个类的内部,这个类就叫做内部类。 Java代码 1.public class First { 2.public class Contents{ 3. public void f(){ 4. System.out.println("In Class First's inner Class Contents method f()") ; 5. } 6.} 7. } 像这样的,Contents就叫做内部类 内部类了解外围类,并能与之通信(后面详细讲) 2、链接到外围类 创建了内部类对象时,它会与创造它的外围对象有了某种联系,于是能访问外围类的所有成员,不需任何特殊条件。 Java代码 1. public class First { 2.public class Contents{ 3. public void getStr(){ 4. System.out.println("First.str="+str); 5. } 6.} 7.private String str; 8. } 9. 在内部类Contents中,可以使用外围类First的字段str。 那么,它是如何实现的呢? 是这样的,用外围类创建内部类对象时,此内部类对象会秘密的捕获一个指向外围类的引用,于是,可以通过这个引用来访问外围类的成员。 通常,这些都是编译器来处理,我们看不到,也不用关心这个。 正是因为如此,我们创建内部类对象时,必须与外围类对象相关联。

注:嵌套类(后面会讲到)除外。 3、使用关键字.this与.new 内部类中得到当前外围类对象的引用,可以使用.this关键字,注意与new的区别 Java代码 1. private int num ; 2.public Test2(){ 3. 4.} 5. 6.public Test2(int num){ 7. this.num = num; 8.} 9. 10.private class Inner{ 11. public Test2 getTest2(){ 12. return Test2.this; 13. } 14. 15. public Test2 newTest2(){ 16. return new Test2(); 17. } 18.} 19. 20.public static void main(String [] args){ 21. Test2 test = new Test2(5); 22. Test2.Inner inner = test.new Inner(); 23. Test2 test2 = inner.getTest2(); 24. Test2 test3 = inner.newTest2(); 25. System.out.println(test2.num); 26. System.out.println(test3.num); 27.} 28. 输出结果为5 0 使用.this后,得到时创建该内部类时使用的外围类对象的引用,new则是创建了一个新的引用。 .new关键字

Java实验7抽象类和接口

实验6 抽象类和接口 一、实验目的: 1、学习掌握抽象类的概念和使用方法。 2、学习掌握接口的概念和定义接口的方法。 3、学习使用Cloneable接口和clone方法进行对象内容的复制。 4、理解浅复制和深复制的概念,掌握覆盖clone方法进行对象内容深复制 的技术。 二、实验任务: 1、学习掌握抽象类的概念和使用方法。程序要求: (1)首先创建一个类家族,其中抽象类几何图形类GeometricObject为父类,圆类Circle和矩形类Rectangle为子类。几何图形类 GeometricObject中定义保护型字符串变量color,表示图形的颜色; 该类要具备构造方法和两个抽象方法findArea和findPerimeter,抽 象方法findArea求图形面积,抽象方法findPerimeter求图形周长。 (2)Circle类和Rectangle类是GeometricObject类的子类,其中应实现父类的抽象方法。 (3)程序主方法中创建两个几何对象,一个圆和一个矩形,并用GeometricObject类的引用变量引用它们,调用抽象方法。 2、学习接口的概念和利用接口实现多态的方法。程序要求如下: (1)首先创建圆类Circle和圆柱体类Cylinder,其中Circle类是父类,Cylinder类是子类; (2)创建接口Comparable,其中包含一个抽象方法compareTo,用来比较对象的大小。抽象方法compareTo的形式如下: public int compareTo(Object o); (3)创建类ComparableCircle,该类为Circle类的子类,并实现

java内部类,抽象类,继承,接口,异常的处理等

序 抽象类的特点: 1,抽象方法一定在抽象类中。 2,抽象方法和抽象类都必须被abstract关键字修饰。 3,抽象类不可以用new创建对象。因为调用抽象方法没意义。 4,抽象类中的抽象方法要被使用,必须由子类复写起所有的抽象方法后,建立子类对象调用。 如果子类只覆盖了部分抽象方法,那么该子类还是一个抽象类。 抽象类和一般类没有太大的不同。 抽象类比一般类多个了抽象函数。就是在类中可以定义抽象方法。 抽象类不可以实例化。 特殊:抽象类中可以不定义抽象方法,这样做仅仅是不让该类建立对象。 abstract 关键字,和哪些关键字不能共存。 final:被final修饰的类不能有子类。而被abstract修饰的类一定是一个父类。 private: 抽象类中的私有的抽象方法,不被子类所知,就无法被复写。 而抽象方法出现的就是需要被复写。 static:如果static可以修饰抽象方法,那么连对象都省了,直接类名调用就可以了。 可是抽象方法运行没意义。 抽象类中有构造函数,因为抽象类是一个父类,要给子类提供实例的初始化。 继承: 1,提高了代码的复用性。 2,让类与类之间产生了关系。有了这个关系,才有了多态的特性。 注:不要为了获取其他类的功能,简化代码而继承。 必须是类与类之间有所属关系才可以继承。所属关系 is a。 Java语言中:java只支持单继承,不支持多继承。 因为多继承容易带来安全隐患:当多个父类中定义了相同功能, 当功能内容不同时,子类对象不确定要运行哪一个。 但是java保留这种机制。并用另一种体现形式来完成表示。多实现。 java支持多层继承。也就是一个继承体系

Java接口,抽象类,内部类

最近看到论坛里有个帖子在讨论接口和抽象类的区别和作用,这其实也是很多面试官喜欢问的问题,这里我就说说我的总结,顺便说说内部类的作用,当是给刚入门,或者想学习jav a的同学们能更好的理解它们的用法。 2.抽象类(abstract class),只要类中有一个抽象方法,此类就被标记为抽象类。实际上抽象类 除了被继承之外没有任何意义。 区别 1. 接口是公开(public)的,里面不能有私有的方法或变量,是用于让别人使用的,实现接口的一定 要实现接口里定义的所有方法。 而抽象类是可以有私有方法或私有变量的,实现抽象类可以有选择地重写需要用到的方法, 但是必须实现里面所有的抽象方法。 2. 抽象类在Java 语言中表示的是一种继承关系,一个类只能使用一次继承关系。 但是,一个类却可以实现多个interface(java中实现多重继承的方法之一)。 3. 抽象类中可以有自己的数据成员,也可以有非abstarct的成员方法。 而在接口中,只能够有静态的不能被修改的数据成员(也就是必须是static final的,不过在interface中一般不定义数据成员),而且所有的成员方法都是抽象的。 4. 抽象类和接口所反映出的设计理念不同。 其实abstract class表示的是"is-a"关系,interface表示的是"like-a"关系。(组合是"has a"关 系) 5.

接口中定义的变量默认是public static final 型,且必须给其初值,所以实现类中不能重新 定义,也不能改变其值。 抽象类中的变量默认是friendly 型,其值可以在子类中重新定义,也可以重新赋值。 一般的应用里,最顶级的是接口,然后是抽象类实现接口,最后才到具体类实现。不是很建议具体类直接实现接口的。还有一种设计模式是面向接口编程,而非面向实现编程。 其实接口是抽象类的延伸,可以将它看做是纯粹的抽象类,就是说接口比抽象类还抽象,还有设计接口的目的就是为了实现C++中的多重继承,不过java团队设计的一样更有趣的东西来实现这个功能,那就是内部类(inner class)。 一.定义 放在一个类的内部的类我们就叫内部类。 二.作用 1.内部类可以很好的实现隐藏,也就是封装性。一般的非内部类,是不允许有private 与prot ected权限的,但内部类可以 2.内部类拥有外围类的所有元素的访问权限 3.可是实现多重继承(这个特点非常重要,个人认为它是内部类存在的最大理由之一) 4.可以避免修改接口而实现同一个类中两种同名方法的调用 三.多重继承的实现

相关主题
文本预览
相关文档 最新文档