返回
第 4章 Java程序结构
Java语言是一种纯面向对象的程
序设计语言, 它的核心概念是类和
对象, 它的程序是基于类和对象建
造的, 程序中类的结构决定了程序
的结构 。 这一章较深入系统地介绍
Java程序的结构, 介绍组成 Java程序
的类之间的关系 。
Java程序结构
类层次结构
对象的使用与对象间通信
多态性
接口与包
访问控制与修饰符
类层次结构
继承的概念
继承的描述
类的继承规则
变量的隐藏
继承的概念
在日常生活中,我们常用“是一
种( is-a)”关系来组织与表达
知识,从而将知识组织成一种有
层次、可分类的结构。面向对象
程序设计方法将 is-a关系引入到
程序设计领域,用于描述类与类
之间的关系,称之为 继承 。
多态性
同一运算或方法(如,+”)对不同类型的
对象(如整型数,或字符串)有不同的语
义解释。这种在程序中同一方法对不同类
型的对象有不同解释的现象称为 多态性
多态性与继承是密不可分的。通常,两类
对象都有共同的父类,在父类中定义的方
法在这两个子类中分别有不同的实现
超类与子类
我们在声明类 A时,指明类 A继承了
类 B(类 B是一个已定义了的类),
则类 A 通常就拥有了类 B的成员变量
和方法。此时,类 B称为类 A的直接
超类 ( superclass),超类也称为父
类或基类;类 A称为类 B的直接 子类
( subclass),子类也称为派生类
继承的描述
Java语言中,声明类首部的格式
如下,
[类的修饰符 ] class 类名 [extends 超类名 ][implement 接口名表 ]
其中,extends 超类名,部分就是用
来描述继承的,这里 超类 名指明所
声明类的直接超类
继承描述的演示
class Car // 声明 Car类
{
int car_number;
void set_number(int car_num)
{
car_number = car_num;
}
void show_number( )
{
System.out.println("我的车号是,"+car_number);
}
}
class TrashCar extends Car // 声明 TrashCar类,它继承 Car类
{
int capacipy;
void set_capacity(int trash_car_capacipy)
{
capacipy = trash_car_capacipy;
}
void show_capacity( )
{
System.out.println("我的容量是,"+capacipy+" ");
}
}
类的继承规则
直接子类继承那些被声明为 public 或 protected的直
接超类成员(包括成员变量和成员方法,下同)
直接子类继承那些未被存取权限修饰符修饰的直接
超类成员,只要该子类与该超类在同一个包中
如果直接子类声明了一个与直接超类中的成员同名
的成员,则该子类不继承该超类中的该同名成员
直接子类不继承被修饰为 private的直接超类的成员
变量的隐藏
直接子类声明了一个与其直接超类的成
员变量同名的成员变量,则称该超类的
该成员变量在该直接子类中被 隐藏,关键字 this 和 super分别用来指明直接子类
和其直接超类中同名的成员变量
当超类的成员变量、子类的成员变量和
类中方法使用的局部变量三者同名,或其中的两者同名时,可以使用关键字 this
和 super来指定所要使用的变量
this和 super区别同名变量的演示
class A
{
int x; // 类 A中声明了成员变量 x
┇
}
class B extends A // 类 B继承类 A,也继承了类 A的成员变量 x
{
int x; // 类 B中又声明了成员变量 x
┇
void m( )
{
int x; // 方法 m声明了自己的局部变量 x
┇
super.x = 2; // super.x是其所在类的父类即类 A的 x
this.x = 1; // this.x 是其所在类即类 B的 x
x = 100; // x是方法本身的局部变量 x
┇
}
}
对象的使用与对象间通信
对象的创建
对象的使用
对象间的通信(消息)与实例方
法的调用
对象的创建
Java中,类是某一类对象的共同特征
(属性、行为)的描述,即类中含
有某一类对象具有 哪些属性, 哪些
行为 的信息。而由类创建的多个对
象都具有类所定义的那些属性和行
为。但是,由同一个类所创建的不
同对象的同一个属性的值可能不同
对象的生命周期
对象和现实生活中的事物一样,
有它的产生、发展和消亡的过程,
在 Java中分别称之为对象的创建、
使用和释放,这一过程称为 对象
的生命周期
定义一个学生类
class Student // Student是学生类名
{ // 定义成员变量
private int sNumber; // 学号
private String sName; // 姓名
private String sClass; // 班号。以下是 定义成员方法
void setSNumber(int xNumber) // 成员方法 setSNumber
{ sNumber = xNumber;
}
int getSNumber( ) // 成员方法 getSNumber
{ return sNumber;
}
void setSName(String xName) // 成员方法 setSName
{ sName = xName;
}
String getSName( ) // 成员方法 getSName
{ return sName;
}
void setSClass(String xClass) // 成员方法 setSClass
{ sClass = xClass;
}
String getSClass( ); // 成员方法 getSClass
{ return sClass;
}
}
创建对象过程
对象的声明
对象的实例化
对象的初始化
对象的声明
对象声明的语法形式为,
类名 对象名 ;
该语句从指定的类创建对象。
对象的实例化和初始化
必须给一个对象分配相应的存储空
间,才能使用它。在声明一个对象
时,并没有为该对象分配存储空间。
对象的实例化完成对象的空间分配,
对象实例化是通过 new操作完成。构
造方法的调用则确定了对象的初始
状态,这一过程就是初始化
对象创建过程的演示
class Course // Course是课程类名
{ // 定义成员变量
private int cNumber; // 课程编号
private String cName;// 课程名
private int cUnit; // 学分数
// 定义成员方法
void setCNumber(int xNumber) // 成员方法 setCNumber
{
cNumber = xNumber;
}
int getCNumber( ) // 成员方法 getCNumber
{
return cNumber;
}
void setCName(String xName) // 成员方法 setCName
{
cName = xName;
}
String getCName( ) // 成员方法 getCName
{
return cName;
}
void setCUnit(int xUnit) // 成员方法 setCUnit
{
cUnit = xUnit;
}
int getCUnit( ) // 成员方法 getCUnit
{
return cUnit;
}
public class InitialDemo1
{
public static void main(String[ ] args)
{
Course cs1 = new Course( ); //声明一个 Course对象 cs1
System.out.println(cs1.getCNumber( ));//输出初始值 cNumber
System.out.println(cs1.getCName( )); //输出初始值 cName
System.out.println(cs1.getCUnit( )); //输出初始值 cUnit
}
}
演示对象的初始化
class Course // Course是类名
{ // 定义成员变量
int cNumber = 1; // 课程编号
String cName = ‖Wang‖; // 课程名
int cUnit = 2; // 学分数
}
public class InitialDemo2
{
public static void main(String[ ] args)
{
Course cs1 = new Course( ); //声明一个 Course对象 cs1
System.out.println(cs1.cNumber); //输出初始值 cNumber
System.out.println(cs1.cName); //输出初始值 cName
System.out.println(cs1.cUnit); //输出初始值 cUnit
}
}
演示使用构造方法进行初始化
class Course // Course是类名
{ // 定义成员变量
int cNumber = 1;
String cName;
int cUnit = 2;
//构造方法
Course( String Name,int Unit )
{
cName = Name;
cUnit = Unit;
}
}
public class InitialDemo3
{
public static void main(String[ ] args)
{
Course cs1 = new Course(―Zhang‖,6); //使用类中声明的构造方法
//声明一个 Course对象 cs1
System.out.println(cs1.cNumber);
System.out.println(cs1.cName);
System.out.println(cs1.cUnit);
}
}
演示由子类创建对象的过程
class A
{
int x = 1;
int y = 1;
A(int x1,int y1)
{
x = x1;
y = y1;
}
}
class B extends A
{
int x = 2;
float z;
B(int xx,int yy)
{
super(0,0);//子类的构造方法中先调用超类的构造方法,否则 Java调用默认的构造方法 A( )
this.x = xx; this.y = yy;
}
}
public class EtndsDemo
{
public static void main(String[ ] args)
{
B b1 = new B(1,2);
System.out.println(b1.x);
System.out.println(b1.y);
System.out.println(b1.z);
}
}
对象的使用
引用对象的成员变量
调用对象的成员方法
对象作数组元素
对象作类的成员变量
引用对象的成员变量
引用对象成员变量的语法形式为,
对象名,成员变量名 ;
例,Rectangle类的声明
class Rectangle
{
int width;
int height;
Rectangle( ) // Rectangle类的构造方法
{
width = 20; height = 30;
}
}
静态变量和实例变量
类 myclass
int Var1 ;
static int Var2 ;
对象 myobject1
Var1
Var2
对象 myobject2
Var1
Var2
myobject1.Var2
myobject2.Var2
myobject1.Var1
myobject2.Var1
静态变量
实例变量
调用对象的成员方法
如前所述,调用对象成员方法的语法形
式为,
对象名, 成员方法名 ( [实际参数表 ]);
其中,
⑴ 对象名 指定所使用的对象;
⑵ 成员方法名 指定所要调用的成员方法;
⑶ 实际参数表 由 0个或多个表达式构成,
表达式之间用逗号“,”分隔
调用对象方法参数传递过程演示
class MethodDemo1
{ //实现两个形式参数 x,y的相加,其和以方法返回值的形式传回
float add(float x,float y)
{
float z;
z = x + y;
return z;
}
}
public class CallMethodDemo1
{
public static void main(String[ ] args)
{
float result;
methodDemo1 addCall = new methodDemo1( );
result = addCall.add (3,5); //调用对象 addCall的 add方法,计算 3+5
System.out.println(result);//result的值为 3+5
}
}
说明实例
本例中类 MethodDemo1给出一个实
现两 float型数相加的方法。方法的参
数 x,y是参与加法的操作数,相加
的结果存于局部变量 z中,return语句
指明 z的值即是方法的返回值。类
CallMethodDemo1的 add对象调用了
类 MethodDemo1的方法 add,实参为
整型 3和 5
演示方法的一种用法
class Fact
{
float fact( int n) //定义计算 n!的方法
{
int i;
float x = 1;
for(i = 1;i<n;i++)
x = x*i;
return x;
}
}
public class MethodCallDemo2
{
public static void main (String args[ ])
{
Fact x = new Fact( );
System.out.println(x.fact(10));//计算 10!
System.out.println(x.fact(15));//计算 15!
}
}
演示静态方法的用法
class Fact
{
static float fact( int n) //将方法 fact声名为静态方法
{
int i;
float x = 1;
for(i = 1;i<n;i++)
x = x*i;
return x;
}
}
public class MethodCallDemo5
{
public static void main (String args[ ])
{
System.out.println(Fact.fact(10));//直接用类名,方法名调用静态方法
System.out.println(Fact.fact(15));
}
}
演示数组作为方法的参数 Java中
数组是作为对象来处理的
class methodDemo5
{
float findMax(float arr[ ] )//形式参数 arr[ ]是数组
{
int i;
float temp;
temp = arr[0];
for(i = 1; i<arr.length; i++)
if( arr[i]>temp) temp = arr[i];
return temp;
}
}
public class MethodCallDemo6
{
public static void main (String args[ ])
{
float max;
float x[ ] = {1,2,3,4,5};
methodDemo5 y = new methodDemo5( );
max = y.findMax(x);//实参 x是数组,数组调用的返回值为 5.0
System.out.println(max);
}
}
对象作数组元素
对象也可以作数组元素,当对象
作数组元素时,其数组称为对象
的数组。创建对象的数组时,首
先对数组初始化,然后对数组的
每个元素初始化
对象作数组元素用法的演示
class node
{
private int data;
private node next;
void setData(int x)
{ data = x;
}
int getData( )
{ return data;
}
node getNext( )
{ return next;
}
void setNext(node x)
{ next = x;
}
}
public class ObjAsArrayElementDemo
{
public static void main (String args[ ])
{ //创建 3个结点
node x[ ] = new node[3]; //创建元素为 node型对象的数组并初始化数组
int i;
for(i = 0;i<x.length;i++)//初始化数组元素 ——对象
x[i] = new node( ); //给结点的 data赋值,并组成链表
for(i = 0;i<x.length;i++)
{
x[i].setData(i);
if(i<x.length-1) x[i].setNext(x[i+1]);
} //利用 start依次输出链表各结点的值
node start = new node( );
start = x[0]; //指向链表的第 1个结点
System.out.println(start.getData( )); //输出 x[0].data
while(start.getNext( )! = null)
{
start = start.getNext( ); //指向下一结点
System.out.println(start.getData( )); //输出 x[i].data
}
}
}
对象作类的成员变量
class date
{
String yy;//年
String mm; //月
String dd; //日
date(String xyy,String xmm,String xdd) // date构造方法
{
yy = xyy; mm = xmm; dd = xdd;
}
}
class Student{
private int idNumber,height; //学号、身高
private char sex; //性别
date birthday; //出生日期 birthday是对象
// Student构造方法
Student(int id,int h,char s,String xyy,String xmm,String xdd){
idNumber = id;
height = h;
sex = s; //调用 date构造方法
birthday = new date(xyy,xmm,xdd);
}
int getHeight( ){ return height; }
int getSex( ){ return sex; }
void show( ){ //输出学号,身高,性别,出生年份
System.out.println( );
System.out.print("/t"+idNumber);
System.out.print ("/t"+height);
System.out.print ("/t"+sex);
System.out.println("/t"+birthday.yy);
}
}
public class UseStudent{
public static void main(String[ ] args)throws java.io.IOException{
int sum = 0;
double ave;
Student [ ] a = new Student [3];//创建对象的数组,数组元素初始化
a[0] = new Student(100001,169,'女 ',"1976","06","12");
a[1] = new Student(100002,155,'女 ',"1976","02","03");
a[2] = new Student(100003,175,'男 ',"1976","05","25"); //求平均身高
for (int i = 0; i<a.length; i++) {
sum = sum+a [i].getHeight( );
}
ave = sum/3.0; //输出超过平均身高的女生学号与身高
System.out.println("超过平均身高的女生学号与身高为 ");
for (int i = 0; i < a.length; i++)
if ((a[i].getHeight( ) > = ave) &(a [i].getSex( ) = = '女 '))
a [i].show( );
}
}
对象间的通信(消息)与实例方
法的调用
消息是一个对象发送给另一对象的信息,
用来驱动接受这一消息的对象的某个行为。
消息由三部分组成:接受消息的对象、
对象中描述某一行为的方法以及这一方
法所需要的参数。
这些问题包括对象作方法的参数、作方
法的返回值、作数组元素以及作类的成
员变量。
对象作方法的参数
当方法的参数时类类型时,方法的
实参就是一个对象,这就是对象作
方法的参数的情形。与基本数据类
型的变量作方法参数的情形不同,
在基本数据类型的变量作方法参数
的情形下,进行方法调用时的语义
动作,是将实参的值传递给相应的
形参。
对象作方法参数的演示
class objPara //定义对象作为参数的类
{ float temp; //用成员变量 temp传递参数值
}
class methodDemo4
{
void add(float x,float y,objPara z) //对象 z作为方法 add的参数
{ z.temp = x+y; //方法体对对象 z进行操作,可以改变 z的值
}
void callAdd2(float m,float n)
{
objPara k = new objPara( );
add( m,n,k); //向方法 add发消息,将参数 m,n的值分别传递给 x,y,并将 k的
//存储地址值传送给 z,然后执行方法 add的方法体,计算 x+y,
//计算结果通过 k传回 callAdd方法
System.out.print(m+"+"+n+" = "+k.temp);// k.temp的值即为 m+n
}
}
public class MethodCallDemo7
{
public static void main (String args[ ])
{
objPara x = new objPara( );
methodDemo4 y = new methodDemo4( );
System.out.println(x.temp);//x.temp值为 0.0
y.add(1,2,x); //调用对象 y的 add方法,计算结果存于对象 x的 temp变量中
System.out.println(x.temp); //x.temp值为 3.0
y.callAdd2(1,2);//输出 1+2的结果
}
}
对象作方法的返回值
class node
{
private int data;
private node next; //成员变量 next是 node类型,而 node是正在声明的类类型
void setData(int x)
{
data = x;
}
int getData( )
{
return data;
}
node getNext( )//此方法的返回值类型是类类型
{
return next;
}
void setNext(node x)
{
next = x;
}
}
public class ObjAsRetValDemo
{
public static void main (String args[ ])
{ //创建 3个结点
node x1 = new node( );
node x2 = new node( );
node x3 = new node( ); //给结点的 data赋值
x1.setData(1);
x2.setData(2);
x3.setData(3); //把 3个结点组成链表
x1.setNext(x2); x2.setNext(x3); //利用 start依次输出链表各结点的值
node start = new node( );
start = x1;//指向结点 x1
System.out.println(start.getData( )); //输出 x1.data
start = start.getNext( );//指向下一结点 x2
System.out.println(start.getData( )); //输出 x2.data
start = start.getNext( );//指向下一结点 x3
System.out.println(start.getData( )); //输出 x3.data
}
}
多态性
方法的重构与重载
方法的动态调用
抽象类
多态性
多态性,就是程序中同一操作在
不同的环境中有不同语义解释的
现象。和继承机制一样,多态性
是面向对象方法的一大特色,它
提供了使同一程序有很强的适应
不同环境的能力的描述机制。
方法的重构与重载
在直接子类中定义的某个方法与其直接
超类的某个方法有相同的名称和参数,
则称该子类 重构 ( Overriding)了该超类
的该方法,重构也称为覆盖
在同一个类中定义了多个同名的方法,
它们或有不同的形参个数或有不同的形
参类型,则称该方法被 重载
( Overloading)
方法重构的演示
class Father
{
void speak( ) // 超类定义的 speak方法
{
System.out.println("I am Father! ");
}
}
class Son extends Father
{
void speak( ) // 子类重构的 speak方法
{
System.out.println("I am Son! ");
}
}
方法重构的演示
class Father
{
void speak( ) // 超类定义的 speak方法
{
System.out.println("I am Father! ");
}
}
class DemoThisSuper extends Father
{
void speak( ) // 子类重构的 speak方法
{
System.out.println("I am Son! ");
}
void demThisSuper( )
{
super.speak( );//调用超类 Father的 speak方法
this.speak( ); //调用子类 DemoThisSuper重构的 speak方法
}
}
class MethodCallDemo4
{
public static void main (String args[ ])
{
Father x = new Father( );
DemoThisSuper y = new DemoThisSuper( );
x.speak( );
//执行方法体 System.out.println("I am Father! ");
y,speak( );
//执行方法体 System.out.println("I am Son! ");
y,demThisSuper( );
//super.speak( )执行方法体 System.out.println("I am Father! ");
//this.speak( )执行方法体 System.out.println("I am Son! ");
}
}
演示方法的重载
class Demoverload
{ int add(int x,int y)
{ return x+y;
}
double add(double x,double y)
{ return x+y;
}
}
class MethodCallDemo3
{ public static void main (String args[ ])
{ Demoverload x = new Demoverload( );
int im = 1,in = 2;
double fm = 1.0,fn = 2.0;
System.out.println(x.add(im,in));//调用时,匹配整型加方法 int
add(int x,int y)
System.out.println(x.add(fm,fn)); //调用时,匹配单精度型加
方法
//double add(double x,double y)
}
}
方法重构的规定
子类重构父类方法时,子类方法的返回类型应当与
被重构方法的相同
子类不能重构父类的 final和 private方法
子类不能用实例方法去重构父类的 static方法。子类
的 static方法可重构父类的 static方法,但不能重构父
类的实例方法
子类方法重构父类方法时,子类方法的访问权限修
饰词不能严于父类方法的访问权限修饰词
子类若要引用父类中的被重构方法,应使用
,super,方法名,的方式
方法的动态调用
class Location{//位置类
int x,y;//位置的坐标
Location(int locX,int locY){ x = locX; y = locY; }
void show( ){ System.out.print("("+x+","+y+")"); }
}
class Point extends Location{ //点类
boolean visible; //可见性
Point(int pointX,int pointY,boolean trueOrFalse){
super(pointX,pointY);//调用超类的构造方法
visible = trueOrFalse;
}
void moveTo(int newX,int newY){//方法 ----移动到新位置
x = newX; y = newY;
}
}
class Circle extends Point{ //圆类
int r ; //r存放半径
Circle(int centX,int centY,int radius,boolean tureOrFalse){
super(centX,centY,tureOrFalse);
r = radius;
}
void expand(int delta){ r = r+delta; } //方法 ----扩展
void contract(int delta){ r = r–delta; }//方法 ----收缩
void show( ){
System.out.print("\t圆心位于 ");
super.show( );
System.out.print("\t半径为 "+r);
if (visible) System.out.println("\t此圆发亮 ");
else System.out.println("\t此圆不发亮 ");
}
}
class TestPointCircle{
public static void main(String[ ] args){
Point p = new Point(200,200,false);
System.out.print("\t点 p的位置是 ");
p.show( ); //调用超类 Location的 show方法
System.out.println( );
Circle c = new Circle(100,100,20,true);
c.show( ); //调用 Circle类的 show方法
c.moveTo(300,400);
c.expand(40);
c.show( );
}
}
说明
子类对象的引用可以赋给超类对象的引
用;方法形参为某类对象时,可用其子
类对象作实参。当子类对象引用赋给父
类对象引用后,父类对象引用引用的是
子类实例,用这个父类引用来引用子类
实例成员(变量与方法)时只能引用与
父类成员同名的那些成员。若成员变量
出现隐藏,引用的是父类变量,若成员
方法出现重构,引用的是子类的方法。
方法动态调用的演示
class TwoDimension{
void show( ){ }
}
class Point extends TwoDimension{
private int x,y;
Point(int px,int py){ x = px; y = py; }
void show( ){//重构了超类的 show方法,输出点的位置
System.out.println("点的位置是 ("+x+","+y+")");
}
}
class Line extends TwoDimension{
private int x1,y1,x2,y2;
Line(int px,int py,int qx,int qy){
x1 = px; y1 = py; x2 = qx; y2 = qy;
}
void show( ){//重构了超类的方法,输出线段两端位置,方法体语句略
}
}
class Circle extends TwoDimension{
private int cX,cY,radius;
Circle(int x,int y,int r){
cX = x; cY = y; radius = r;
}
void show( ){//重构了超类的方法,输出圆心坐标及半径,方法体语句略
}
}
class UseTwoDimension{
static void showParameter(TwoDimension plc){
plc.show( );
}
public static void main(String[ ] args){
Point p = new Point(10,10);
Line l = new Line(0,20,100,20);
Circle c = new Circle(100,100,50);
//p,l,c均是 TwoDimension类的子类类型,充当 showParameter方法的实参
//将子类对象引用赋给超类对象引用
showParameter( p ); //执行 p.show( )
showParameter( l ); //执行 l.show( )
showParameter( c ); //执行 c.show( )
}
}
抽象类
使用修饰符 abstract对类加以修饰,
这个类就是 抽象类 ( abstract class),
抽象类不能被实例化。通常,抽象
类中含有抽象方法,抽象方法是指
只给出方法声明但没有方法体的方
法。子类在继承抽象类时,必须 重
构其父类的抽象方法,给出具体的
定义。
演示抽象类及其用法
abstract class Figure // 声明抽象类 Figure
{
double x,y;
void set_size(double size1,double size2)
{ x = size1;
y = size2;
} // 声明抽象方法 get_area,它没有方法体
abstract double get_area( );
}
class Triangle extends Figure // Triangle 继承抽象类 Figure
{ double get_area( ) // 重构其超类的抽象方法 get_area( )
{ return(x*y/2); //三角形面积 = 底 *高 /2
}
}
class Rectangle extends Figure // Rectangle 继承抽象类 Figure
{ double get_area( ) //重构其超类的抽象方法 get_area( )
{
return(x*y); //矩形面积 = 长 *宽
}
}
接口与包
接口
包
接口
接口 ( interface)是一个协定,它定义了一组
行为的界面,但没有定义行为的具体实现过程。
任何一个类都可以实现一个接口。
所谓一个类实现一个接口,是指这个类给出这
个接口的 所有 行为的具体实现过程。
从语法上看,接口由接口首部和接口体组成。
接口首部给出接口名,如果存在接口的继承关
系,也要在接口首部中给出。接口体主要是一
组方法首部的说明,接口体中也可以声明一些
常量。
接口声明、实现和使用的演示
// 声明接口 Figure
interface Figure //接口首部,interface是关键字,Figure是接口名
//接口体
{ void set_size(double size1,double size2);//方法首部给出行为的界面
double get_area( );
}//接口声明结束
class Triangle implements Figure // Triangle 实现接口 Figure,implements是关键字
{ double x,y;
//实现接口的方法,给出所实现接口的所有方法首部的方法体
public void set_size(double size1,double size2)
{ x = size1;
y = size2;
}
public double get_area( )
{ return(x*y/2); //三角形面积 = 底 *高 /2
}
}
class Rectangle implements Figure // Rectangle 实现接口 Figure
{ double x,y;
public void set_size(double size1,double size2)
{ x = size1;
y = size2;
}
public double get_area( )
{ return(x*y); //矩形面积 = 长 *宽
}
}
class output // output类使用接口 Figure
{ static void put(Figure q) //此方法的参数是接口类型
{ System.out.println(q.get_area( ));
}
}
public class TestInterface{
public static void main(String[ ] args){
Figure ft = new Triangle( );//创建接口对象,其方法的具体实现过程
//由 Triangle类给出
Figure fr = new Rectangle( );//创建接口对象,其方法的具体实现过程
//由 Rectangle类给出
Rectangle r = new Rectangle( );r.set_size(2,2);
ft.set_size(2,2); fr.set_size(2,2);
output.put(ft);//实参是接口对象,输出三角形面积,2
output.put(fr);//实参是接口对象,输出矩形面积,4
output.put(r);// 实参是实现接口的类的对象,输出矩形面积,4
}
}
接口与抽象类的主要区别
接口不能实现任何方法(即不能
给出方法的具体实现过程),而
抽象类却可以
一个类可以实现多个接口,但只能有一个直接超类
接口不是任何类的继承层次的组
成部分,无关的几个类可以实现同一个接口
包
包的概念
包的创建
包中成员的使用
包的概念
包 ( package)是一组相关类和接口的集合,它
提供了访问权限和命名的管理机制。
Java中的包主要有三个作用,
1)使得功能相关的类易于查找和使用 ----同一
包中的类和接口通常是功能相关的;
2)避免了命名的冲突 ----不同包中的不同类可
以同名;
3)提供一种访问权限的控制机制
包的创建
创建一个包,只需在定义了类和
接口的源文件的第一行使用
package语句
package语句的作用域是包含该
语句的整个源文件
包中成员的使用
三种方法使用包中的成员。如果要
使用包 A中的成员 x,我们可以,
⑴ 用长名 A.x引用成员 x;
⑵ import A.x语句装入包的成员 x;
⑶ import A语句装入整个包 A。
访问控制与修饰符
类成员的访问权限
类的修饰符
类成员的访问权限
private,protected和 public是类成
员(包括成员变量和成员方法)
的访问权限修饰符。
类成员的访问权限
被本类访
问 被子类访问
被同一包中的
其它类访问 被所有类访问
private 允许 不允许 不允许 不允许
protected 允许 允许 允许 不允许
public 允许 允许 允许 允许
friendly 允许 不允许 允许 不允许
private
由 private修饰的成员成为私有成
员,它们只允许由声明它的类中
的成员方法使用,即只允许在定
义这些方法时使用这些私有成员
的名字。
演示 private成员的修饰和使用
class Alpha
{ private int iamprivate;
private void privateMethod( )
{
System.out.println(―privateMethod‖);
}
void usePrivate( )
{ iamprivate = 10;//合法
privateMethod( );//合法
}
}
class Beta
{ void accessMethod( )
{ Alpha a = new Alpha( );
a.iamprivate = 10; // 非法
a.privateMethod( ); // 非法
}
}
protected
由 protected修饰的成员(也称受
保护成员)允许被声明它的类本
身、声明它的类的子类(必须在
同一个包中)及与它在同一个包
中的其它类使用
演示 protected成员的修饰和使用
package A;
class Alpha
{ protected int iam;
protected void aMethod( )
{ System.out.println(―aMethod‖);
}
}
class Gamma
{ void accessMethod( )
{ Alpha a = new Alpha( );
a.iam = 10; //合法
a.aMethod( );//合法
}
}
package B;
class Gamma
{ void accessMethod( )
{ Alpha a = new Alpha( );
a.iamp = 10; //非法
a.aMethod( );//非法
}
}
public
由 public修饰的成员(也称公共
成员)允许被任何包中的任何类
使用
演示 public成员的修饰和访问
package Greek;
class Alpha
{ //成员变量 iam和成员方法 aMethod都被修饰为公共成员 public int iam;
public void aMethod( )
{ System.out.println(―aMethod‖);
}
}
import Greek.* ;
package Roman ;
class Beta
{ void accessMethod( )
{ Alpha a = new Alpha( );
a.iam = 10; // 合法
a.aMethod( ); // 合法
}
}
friendly
package A;
class Alpha
{
//声明 friendly成员
int iam;
void aMethod( )
{
System.out.println(―aMethod‖);
}
}
class Beta
{
void accessMethod( )
{
Alpha a = new Alpha( );
a.iam = 10; // 合法
a.aMethod( ); // 合法
}
}
class Gamma extends Alpha
{
void accessMethod( )
{
Alpha a = new Alpha( );
a.iam = 10; // 非法
a.aMethod( ); // 非法
}
}
package B;
class Beta
{
void accessMethod( )
{
Alpha a = new Alpha( );
a.iam = 10; //非法
a.aMethod( ); //非法
}
}
类的修饰符
修 饰 符 作 用
private,public 说明类访问权限
Abstract 说明抽象类
Final 说明最终类
习题
第 4章 Java程序结构
Java语言是一种纯面向对象的程
序设计语言, 它的核心概念是类和
对象, 它的程序是基于类和对象建
造的, 程序中类的结构决定了程序
的结构 。 这一章较深入系统地介绍
Java程序的结构, 介绍组成 Java程序
的类之间的关系 。
Java程序结构
类层次结构
对象的使用与对象间通信
多态性
接口与包
访问控制与修饰符
类层次结构
继承的概念
继承的描述
类的继承规则
变量的隐藏
继承的概念
在日常生活中,我们常用“是一
种( is-a)”关系来组织与表达
知识,从而将知识组织成一种有
层次、可分类的结构。面向对象
程序设计方法将 is-a关系引入到
程序设计领域,用于描述类与类
之间的关系,称之为 继承 。
多态性
同一运算或方法(如,+”)对不同类型的
对象(如整型数,或字符串)有不同的语
义解释。这种在程序中同一方法对不同类
型的对象有不同解释的现象称为 多态性
多态性与继承是密不可分的。通常,两类
对象都有共同的父类,在父类中定义的方
法在这两个子类中分别有不同的实现
超类与子类
我们在声明类 A时,指明类 A继承了
类 B(类 B是一个已定义了的类),
则类 A 通常就拥有了类 B的成员变量
和方法。此时,类 B称为类 A的直接
超类 ( superclass),超类也称为父
类或基类;类 A称为类 B的直接 子类
( subclass),子类也称为派生类
继承的描述
Java语言中,声明类首部的格式
如下,
[类的修饰符 ] class 类名 [extends 超类名 ][implement 接口名表 ]
其中,extends 超类名,部分就是用
来描述继承的,这里 超类 名指明所
声明类的直接超类
继承描述的演示
class Car // 声明 Car类
{
int car_number;
void set_number(int car_num)
{
car_number = car_num;
}
void show_number( )
{
System.out.println("我的车号是,"+car_number);
}
}
class TrashCar extends Car // 声明 TrashCar类,它继承 Car类
{
int capacipy;
void set_capacity(int trash_car_capacipy)
{
capacipy = trash_car_capacipy;
}
void show_capacity( )
{
System.out.println("我的容量是,"+capacipy+" ");
}
}
类的继承规则
直接子类继承那些被声明为 public 或 protected的直
接超类成员(包括成员变量和成员方法,下同)
直接子类继承那些未被存取权限修饰符修饰的直接
超类成员,只要该子类与该超类在同一个包中
如果直接子类声明了一个与直接超类中的成员同名
的成员,则该子类不继承该超类中的该同名成员
直接子类不继承被修饰为 private的直接超类的成员
变量的隐藏
直接子类声明了一个与其直接超类的成
员变量同名的成员变量,则称该超类的
该成员变量在该直接子类中被 隐藏,关键字 this 和 super分别用来指明直接子类
和其直接超类中同名的成员变量
当超类的成员变量、子类的成员变量和
类中方法使用的局部变量三者同名,或其中的两者同名时,可以使用关键字 this
和 super来指定所要使用的变量
this和 super区别同名变量的演示
class A
{
int x; // 类 A中声明了成员变量 x
┇
}
class B extends A // 类 B继承类 A,也继承了类 A的成员变量 x
{
int x; // 类 B中又声明了成员变量 x
┇
void m( )
{
int x; // 方法 m声明了自己的局部变量 x
┇
super.x = 2; // super.x是其所在类的父类即类 A的 x
this.x = 1; // this.x 是其所在类即类 B的 x
x = 100; // x是方法本身的局部变量 x
┇
}
}
对象的使用与对象间通信
对象的创建
对象的使用
对象间的通信(消息)与实例方
法的调用
对象的创建
Java中,类是某一类对象的共同特征
(属性、行为)的描述,即类中含
有某一类对象具有 哪些属性, 哪些
行为 的信息。而由类创建的多个对
象都具有类所定义的那些属性和行
为。但是,由同一个类所创建的不
同对象的同一个属性的值可能不同
对象的生命周期
对象和现实生活中的事物一样,
有它的产生、发展和消亡的过程,
在 Java中分别称之为对象的创建、
使用和释放,这一过程称为 对象
的生命周期
定义一个学生类
class Student // Student是学生类名
{ // 定义成员变量
private int sNumber; // 学号
private String sName; // 姓名
private String sClass; // 班号。以下是 定义成员方法
void setSNumber(int xNumber) // 成员方法 setSNumber
{ sNumber = xNumber;
}
int getSNumber( ) // 成员方法 getSNumber
{ return sNumber;
}
void setSName(String xName) // 成员方法 setSName
{ sName = xName;
}
String getSName( ) // 成员方法 getSName
{ return sName;
}
void setSClass(String xClass) // 成员方法 setSClass
{ sClass = xClass;
}
String getSClass( ); // 成员方法 getSClass
{ return sClass;
}
}
创建对象过程
对象的声明
对象的实例化
对象的初始化
对象的声明
对象声明的语法形式为,
类名 对象名 ;
该语句从指定的类创建对象。
对象的实例化和初始化
必须给一个对象分配相应的存储空
间,才能使用它。在声明一个对象
时,并没有为该对象分配存储空间。
对象的实例化完成对象的空间分配,
对象实例化是通过 new操作完成。构
造方法的调用则确定了对象的初始
状态,这一过程就是初始化
对象创建过程的演示
class Course // Course是课程类名
{ // 定义成员变量
private int cNumber; // 课程编号
private String cName;// 课程名
private int cUnit; // 学分数
// 定义成员方法
void setCNumber(int xNumber) // 成员方法 setCNumber
{
cNumber = xNumber;
}
int getCNumber( ) // 成员方法 getCNumber
{
return cNumber;
}
void setCName(String xName) // 成员方法 setCName
{
cName = xName;
}
String getCName( ) // 成员方法 getCName
{
return cName;
}
void setCUnit(int xUnit) // 成员方法 setCUnit
{
cUnit = xUnit;
}
int getCUnit( ) // 成员方法 getCUnit
{
return cUnit;
}
public class InitialDemo1
{
public static void main(String[ ] args)
{
Course cs1 = new Course( ); //声明一个 Course对象 cs1
System.out.println(cs1.getCNumber( ));//输出初始值 cNumber
System.out.println(cs1.getCName( )); //输出初始值 cName
System.out.println(cs1.getCUnit( )); //输出初始值 cUnit
}
}
演示对象的初始化
class Course // Course是类名
{ // 定义成员变量
int cNumber = 1; // 课程编号
String cName = ‖Wang‖; // 课程名
int cUnit = 2; // 学分数
}
public class InitialDemo2
{
public static void main(String[ ] args)
{
Course cs1 = new Course( ); //声明一个 Course对象 cs1
System.out.println(cs1.cNumber); //输出初始值 cNumber
System.out.println(cs1.cName); //输出初始值 cName
System.out.println(cs1.cUnit); //输出初始值 cUnit
}
}
演示使用构造方法进行初始化
class Course // Course是类名
{ // 定义成员变量
int cNumber = 1;
String cName;
int cUnit = 2;
//构造方法
Course( String Name,int Unit )
{
cName = Name;
cUnit = Unit;
}
}
public class InitialDemo3
{
public static void main(String[ ] args)
{
Course cs1 = new Course(―Zhang‖,6); //使用类中声明的构造方法
//声明一个 Course对象 cs1
System.out.println(cs1.cNumber);
System.out.println(cs1.cName);
System.out.println(cs1.cUnit);
}
}
演示由子类创建对象的过程
class A
{
int x = 1;
int y = 1;
A(int x1,int y1)
{
x = x1;
y = y1;
}
}
class B extends A
{
int x = 2;
float z;
B(int xx,int yy)
{
super(0,0);//子类的构造方法中先调用超类的构造方法,否则 Java调用默认的构造方法 A( )
this.x = xx; this.y = yy;
}
}
public class EtndsDemo
{
public static void main(String[ ] args)
{
B b1 = new B(1,2);
System.out.println(b1.x);
System.out.println(b1.y);
System.out.println(b1.z);
}
}
对象的使用
引用对象的成员变量
调用对象的成员方法
对象作数组元素
对象作类的成员变量
引用对象的成员变量
引用对象成员变量的语法形式为,
对象名,成员变量名 ;
例,Rectangle类的声明
class Rectangle
{
int width;
int height;
Rectangle( ) // Rectangle类的构造方法
{
width = 20; height = 30;
}
}
静态变量和实例变量
类 myclass
int Var1 ;
static int Var2 ;
对象 myobject1
Var1
Var2
对象 myobject2
Var1
Var2
myobject1.Var2
myobject2.Var2
myobject1.Var1
myobject2.Var1
静态变量
实例变量
调用对象的成员方法
如前所述,调用对象成员方法的语法形
式为,
对象名, 成员方法名 ( [实际参数表 ]);
其中,
⑴ 对象名 指定所使用的对象;
⑵ 成员方法名 指定所要调用的成员方法;
⑶ 实际参数表 由 0个或多个表达式构成,
表达式之间用逗号“,”分隔
调用对象方法参数传递过程演示
class MethodDemo1
{ //实现两个形式参数 x,y的相加,其和以方法返回值的形式传回
float add(float x,float y)
{
float z;
z = x + y;
return z;
}
}
public class CallMethodDemo1
{
public static void main(String[ ] args)
{
float result;
methodDemo1 addCall = new methodDemo1( );
result = addCall.add (3,5); //调用对象 addCall的 add方法,计算 3+5
System.out.println(result);//result的值为 3+5
}
}
说明实例
本例中类 MethodDemo1给出一个实
现两 float型数相加的方法。方法的参
数 x,y是参与加法的操作数,相加
的结果存于局部变量 z中,return语句
指明 z的值即是方法的返回值。类
CallMethodDemo1的 add对象调用了
类 MethodDemo1的方法 add,实参为
整型 3和 5
演示方法的一种用法
class Fact
{
float fact( int n) //定义计算 n!的方法
{
int i;
float x = 1;
for(i = 1;i<n;i++)
x = x*i;
return x;
}
}
public class MethodCallDemo2
{
public static void main (String args[ ])
{
Fact x = new Fact( );
System.out.println(x.fact(10));//计算 10!
System.out.println(x.fact(15));//计算 15!
}
}
演示静态方法的用法
class Fact
{
static float fact( int n) //将方法 fact声名为静态方法
{
int i;
float x = 1;
for(i = 1;i<n;i++)
x = x*i;
return x;
}
}
public class MethodCallDemo5
{
public static void main (String args[ ])
{
System.out.println(Fact.fact(10));//直接用类名,方法名调用静态方法
System.out.println(Fact.fact(15));
}
}
演示数组作为方法的参数 Java中
数组是作为对象来处理的
class methodDemo5
{
float findMax(float arr[ ] )//形式参数 arr[ ]是数组
{
int i;
float temp;
temp = arr[0];
for(i = 1; i<arr.length; i++)
if( arr[i]>temp) temp = arr[i];
return temp;
}
}
public class MethodCallDemo6
{
public static void main (String args[ ])
{
float max;
float x[ ] = {1,2,3,4,5};
methodDemo5 y = new methodDemo5( );
max = y.findMax(x);//实参 x是数组,数组调用的返回值为 5.0
System.out.println(max);
}
}
对象作数组元素
对象也可以作数组元素,当对象
作数组元素时,其数组称为对象
的数组。创建对象的数组时,首
先对数组初始化,然后对数组的
每个元素初始化
对象作数组元素用法的演示
class node
{
private int data;
private node next;
void setData(int x)
{ data = x;
}
int getData( )
{ return data;
}
node getNext( )
{ return next;
}
void setNext(node x)
{ next = x;
}
}
public class ObjAsArrayElementDemo
{
public static void main (String args[ ])
{ //创建 3个结点
node x[ ] = new node[3]; //创建元素为 node型对象的数组并初始化数组
int i;
for(i = 0;i<x.length;i++)//初始化数组元素 ——对象
x[i] = new node( ); //给结点的 data赋值,并组成链表
for(i = 0;i<x.length;i++)
{
x[i].setData(i);
if(i<x.length-1) x[i].setNext(x[i+1]);
} //利用 start依次输出链表各结点的值
node start = new node( );
start = x[0]; //指向链表的第 1个结点
System.out.println(start.getData( )); //输出 x[0].data
while(start.getNext( )! = null)
{
start = start.getNext( ); //指向下一结点
System.out.println(start.getData( )); //输出 x[i].data
}
}
}
对象作类的成员变量
class date
{
String yy;//年
String mm; //月
String dd; //日
date(String xyy,String xmm,String xdd) // date构造方法
{
yy = xyy; mm = xmm; dd = xdd;
}
}
class Student{
private int idNumber,height; //学号、身高
private char sex; //性别
date birthday; //出生日期 birthday是对象
// Student构造方法
Student(int id,int h,char s,String xyy,String xmm,String xdd){
idNumber = id;
height = h;
sex = s; //调用 date构造方法
birthday = new date(xyy,xmm,xdd);
}
int getHeight( ){ return height; }
int getSex( ){ return sex; }
void show( ){ //输出学号,身高,性别,出生年份
System.out.println( );
System.out.print("/t"+idNumber);
System.out.print ("/t"+height);
System.out.print ("/t"+sex);
System.out.println("/t"+birthday.yy);
}
}
public class UseStudent{
public static void main(String[ ] args)throws java.io.IOException{
int sum = 0;
double ave;
Student [ ] a = new Student [3];//创建对象的数组,数组元素初始化
a[0] = new Student(100001,169,'女 ',"1976","06","12");
a[1] = new Student(100002,155,'女 ',"1976","02","03");
a[2] = new Student(100003,175,'男 ',"1976","05","25"); //求平均身高
for (int i = 0; i<a.length; i++) {
sum = sum+a [i].getHeight( );
}
ave = sum/3.0; //输出超过平均身高的女生学号与身高
System.out.println("超过平均身高的女生学号与身高为 ");
for (int i = 0; i < a.length; i++)
if ((a[i].getHeight( ) > = ave) &(a [i].getSex( ) = = '女 '))
a [i].show( );
}
}
对象间的通信(消息)与实例方
法的调用
消息是一个对象发送给另一对象的信息,
用来驱动接受这一消息的对象的某个行为。
消息由三部分组成:接受消息的对象、
对象中描述某一行为的方法以及这一方
法所需要的参数。
这些问题包括对象作方法的参数、作方
法的返回值、作数组元素以及作类的成
员变量。
对象作方法的参数
当方法的参数时类类型时,方法的
实参就是一个对象,这就是对象作
方法的参数的情形。与基本数据类
型的变量作方法参数的情形不同,
在基本数据类型的变量作方法参数
的情形下,进行方法调用时的语义
动作,是将实参的值传递给相应的
形参。
对象作方法参数的演示
class objPara //定义对象作为参数的类
{ float temp; //用成员变量 temp传递参数值
}
class methodDemo4
{
void add(float x,float y,objPara z) //对象 z作为方法 add的参数
{ z.temp = x+y; //方法体对对象 z进行操作,可以改变 z的值
}
void callAdd2(float m,float n)
{
objPara k = new objPara( );
add( m,n,k); //向方法 add发消息,将参数 m,n的值分别传递给 x,y,并将 k的
//存储地址值传送给 z,然后执行方法 add的方法体,计算 x+y,
//计算结果通过 k传回 callAdd方法
System.out.print(m+"+"+n+" = "+k.temp);// k.temp的值即为 m+n
}
}
public class MethodCallDemo7
{
public static void main (String args[ ])
{
objPara x = new objPara( );
methodDemo4 y = new methodDemo4( );
System.out.println(x.temp);//x.temp值为 0.0
y.add(1,2,x); //调用对象 y的 add方法,计算结果存于对象 x的 temp变量中
System.out.println(x.temp); //x.temp值为 3.0
y.callAdd2(1,2);//输出 1+2的结果
}
}
对象作方法的返回值
class node
{
private int data;
private node next; //成员变量 next是 node类型,而 node是正在声明的类类型
void setData(int x)
{
data = x;
}
int getData( )
{
return data;
}
node getNext( )//此方法的返回值类型是类类型
{
return next;
}
void setNext(node x)
{
next = x;
}
}
public class ObjAsRetValDemo
{
public static void main (String args[ ])
{ //创建 3个结点
node x1 = new node( );
node x2 = new node( );
node x3 = new node( ); //给结点的 data赋值
x1.setData(1);
x2.setData(2);
x3.setData(3); //把 3个结点组成链表
x1.setNext(x2); x2.setNext(x3); //利用 start依次输出链表各结点的值
node start = new node( );
start = x1;//指向结点 x1
System.out.println(start.getData( )); //输出 x1.data
start = start.getNext( );//指向下一结点 x2
System.out.println(start.getData( )); //输出 x2.data
start = start.getNext( );//指向下一结点 x3
System.out.println(start.getData( )); //输出 x3.data
}
}
多态性
方法的重构与重载
方法的动态调用
抽象类
多态性
多态性,就是程序中同一操作在
不同的环境中有不同语义解释的
现象。和继承机制一样,多态性
是面向对象方法的一大特色,它
提供了使同一程序有很强的适应
不同环境的能力的描述机制。
方法的重构与重载
在直接子类中定义的某个方法与其直接
超类的某个方法有相同的名称和参数,
则称该子类 重构 ( Overriding)了该超类
的该方法,重构也称为覆盖
在同一个类中定义了多个同名的方法,
它们或有不同的形参个数或有不同的形
参类型,则称该方法被 重载
( Overloading)
方法重构的演示
class Father
{
void speak( ) // 超类定义的 speak方法
{
System.out.println("I am Father! ");
}
}
class Son extends Father
{
void speak( ) // 子类重构的 speak方法
{
System.out.println("I am Son! ");
}
}
方法重构的演示
class Father
{
void speak( ) // 超类定义的 speak方法
{
System.out.println("I am Father! ");
}
}
class DemoThisSuper extends Father
{
void speak( ) // 子类重构的 speak方法
{
System.out.println("I am Son! ");
}
void demThisSuper( )
{
super.speak( );//调用超类 Father的 speak方法
this.speak( ); //调用子类 DemoThisSuper重构的 speak方法
}
}
class MethodCallDemo4
{
public static void main (String args[ ])
{
Father x = new Father( );
DemoThisSuper y = new DemoThisSuper( );
x.speak( );
//执行方法体 System.out.println("I am Father! ");
y,speak( );
//执行方法体 System.out.println("I am Son! ");
y,demThisSuper( );
//super.speak( )执行方法体 System.out.println("I am Father! ");
//this.speak( )执行方法体 System.out.println("I am Son! ");
}
}
演示方法的重载
class Demoverload
{ int add(int x,int y)
{ return x+y;
}
double add(double x,double y)
{ return x+y;
}
}
class MethodCallDemo3
{ public static void main (String args[ ])
{ Demoverload x = new Demoverload( );
int im = 1,in = 2;
double fm = 1.0,fn = 2.0;
System.out.println(x.add(im,in));//调用时,匹配整型加方法 int
add(int x,int y)
System.out.println(x.add(fm,fn)); //调用时,匹配单精度型加
方法
//double add(double x,double y)
}
}
方法重构的规定
子类重构父类方法时,子类方法的返回类型应当与
被重构方法的相同
子类不能重构父类的 final和 private方法
子类不能用实例方法去重构父类的 static方法。子类
的 static方法可重构父类的 static方法,但不能重构父
类的实例方法
子类方法重构父类方法时,子类方法的访问权限修
饰词不能严于父类方法的访问权限修饰词
子类若要引用父类中的被重构方法,应使用
,super,方法名,的方式
方法的动态调用
class Location{//位置类
int x,y;//位置的坐标
Location(int locX,int locY){ x = locX; y = locY; }
void show( ){ System.out.print("("+x+","+y+")"); }
}
class Point extends Location{ //点类
boolean visible; //可见性
Point(int pointX,int pointY,boolean trueOrFalse){
super(pointX,pointY);//调用超类的构造方法
visible = trueOrFalse;
}
void moveTo(int newX,int newY){//方法 ----移动到新位置
x = newX; y = newY;
}
}
class Circle extends Point{ //圆类
int r ; //r存放半径
Circle(int centX,int centY,int radius,boolean tureOrFalse){
super(centX,centY,tureOrFalse);
r = radius;
}
void expand(int delta){ r = r+delta; } //方法 ----扩展
void contract(int delta){ r = r–delta; }//方法 ----收缩
void show( ){
System.out.print("\t圆心位于 ");
super.show( );
System.out.print("\t半径为 "+r);
if (visible) System.out.println("\t此圆发亮 ");
else System.out.println("\t此圆不发亮 ");
}
}
class TestPointCircle{
public static void main(String[ ] args){
Point p = new Point(200,200,false);
System.out.print("\t点 p的位置是 ");
p.show( ); //调用超类 Location的 show方法
System.out.println( );
Circle c = new Circle(100,100,20,true);
c.show( ); //调用 Circle类的 show方法
c.moveTo(300,400);
c.expand(40);
c.show( );
}
}
说明
子类对象的引用可以赋给超类对象的引
用;方法形参为某类对象时,可用其子
类对象作实参。当子类对象引用赋给父
类对象引用后,父类对象引用引用的是
子类实例,用这个父类引用来引用子类
实例成员(变量与方法)时只能引用与
父类成员同名的那些成员。若成员变量
出现隐藏,引用的是父类变量,若成员
方法出现重构,引用的是子类的方法。
方法动态调用的演示
class TwoDimension{
void show( ){ }
}
class Point extends TwoDimension{
private int x,y;
Point(int px,int py){ x = px; y = py; }
void show( ){//重构了超类的 show方法,输出点的位置
System.out.println("点的位置是 ("+x+","+y+")");
}
}
class Line extends TwoDimension{
private int x1,y1,x2,y2;
Line(int px,int py,int qx,int qy){
x1 = px; y1 = py; x2 = qx; y2 = qy;
}
void show( ){//重构了超类的方法,输出线段两端位置,方法体语句略
}
}
class Circle extends TwoDimension{
private int cX,cY,radius;
Circle(int x,int y,int r){
cX = x; cY = y; radius = r;
}
void show( ){//重构了超类的方法,输出圆心坐标及半径,方法体语句略
}
}
class UseTwoDimension{
static void showParameter(TwoDimension plc){
plc.show( );
}
public static void main(String[ ] args){
Point p = new Point(10,10);
Line l = new Line(0,20,100,20);
Circle c = new Circle(100,100,50);
//p,l,c均是 TwoDimension类的子类类型,充当 showParameter方法的实参
//将子类对象引用赋给超类对象引用
showParameter( p ); //执行 p.show( )
showParameter( l ); //执行 l.show( )
showParameter( c ); //执行 c.show( )
}
}
抽象类
使用修饰符 abstract对类加以修饰,
这个类就是 抽象类 ( abstract class),
抽象类不能被实例化。通常,抽象
类中含有抽象方法,抽象方法是指
只给出方法声明但没有方法体的方
法。子类在继承抽象类时,必须 重
构其父类的抽象方法,给出具体的
定义。
演示抽象类及其用法
abstract class Figure // 声明抽象类 Figure
{
double x,y;
void set_size(double size1,double size2)
{ x = size1;
y = size2;
} // 声明抽象方法 get_area,它没有方法体
abstract double get_area( );
}
class Triangle extends Figure // Triangle 继承抽象类 Figure
{ double get_area( ) // 重构其超类的抽象方法 get_area( )
{ return(x*y/2); //三角形面积 = 底 *高 /2
}
}
class Rectangle extends Figure // Rectangle 继承抽象类 Figure
{ double get_area( ) //重构其超类的抽象方法 get_area( )
{
return(x*y); //矩形面积 = 长 *宽
}
}
接口与包
接口
包
接口
接口 ( interface)是一个协定,它定义了一组
行为的界面,但没有定义行为的具体实现过程。
任何一个类都可以实现一个接口。
所谓一个类实现一个接口,是指这个类给出这
个接口的 所有 行为的具体实现过程。
从语法上看,接口由接口首部和接口体组成。
接口首部给出接口名,如果存在接口的继承关
系,也要在接口首部中给出。接口体主要是一
组方法首部的说明,接口体中也可以声明一些
常量。
接口声明、实现和使用的演示
// 声明接口 Figure
interface Figure //接口首部,interface是关键字,Figure是接口名
//接口体
{ void set_size(double size1,double size2);//方法首部给出行为的界面
double get_area( );
}//接口声明结束
class Triangle implements Figure // Triangle 实现接口 Figure,implements是关键字
{ double x,y;
//实现接口的方法,给出所实现接口的所有方法首部的方法体
public void set_size(double size1,double size2)
{ x = size1;
y = size2;
}
public double get_area( )
{ return(x*y/2); //三角形面积 = 底 *高 /2
}
}
class Rectangle implements Figure // Rectangle 实现接口 Figure
{ double x,y;
public void set_size(double size1,double size2)
{ x = size1;
y = size2;
}
public double get_area( )
{ return(x*y); //矩形面积 = 长 *宽
}
}
class output // output类使用接口 Figure
{ static void put(Figure q) //此方法的参数是接口类型
{ System.out.println(q.get_area( ));
}
}
public class TestInterface{
public static void main(String[ ] args){
Figure ft = new Triangle( );//创建接口对象,其方法的具体实现过程
//由 Triangle类给出
Figure fr = new Rectangle( );//创建接口对象,其方法的具体实现过程
//由 Rectangle类给出
Rectangle r = new Rectangle( );r.set_size(2,2);
ft.set_size(2,2); fr.set_size(2,2);
output.put(ft);//实参是接口对象,输出三角形面积,2
output.put(fr);//实参是接口对象,输出矩形面积,4
output.put(r);// 实参是实现接口的类的对象,输出矩形面积,4
}
}
接口与抽象类的主要区别
接口不能实现任何方法(即不能
给出方法的具体实现过程),而
抽象类却可以
一个类可以实现多个接口,但只能有一个直接超类
接口不是任何类的继承层次的组
成部分,无关的几个类可以实现同一个接口
包
包的概念
包的创建
包中成员的使用
包的概念
包 ( package)是一组相关类和接口的集合,它
提供了访问权限和命名的管理机制。
Java中的包主要有三个作用,
1)使得功能相关的类易于查找和使用 ----同一
包中的类和接口通常是功能相关的;
2)避免了命名的冲突 ----不同包中的不同类可
以同名;
3)提供一种访问权限的控制机制
包的创建
创建一个包,只需在定义了类和
接口的源文件的第一行使用
package语句
package语句的作用域是包含该
语句的整个源文件
包中成员的使用
三种方法使用包中的成员。如果要
使用包 A中的成员 x,我们可以,
⑴ 用长名 A.x引用成员 x;
⑵ import A.x语句装入包的成员 x;
⑶ import A语句装入整个包 A。
访问控制与修饰符
类成员的访问权限
类的修饰符
类成员的访问权限
private,protected和 public是类成
员(包括成员变量和成员方法)
的访问权限修饰符。
类成员的访问权限
被本类访
问 被子类访问
被同一包中的
其它类访问 被所有类访问
private 允许 不允许 不允许 不允许
protected 允许 允许 允许 不允许
public 允许 允许 允许 允许
friendly 允许 不允许 允许 不允许
private
由 private修饰的成员成为私有成
员,它们只允许由声明它的类中
的成员方法使用,即只允许在定
义这些方法时使用这些私有成员
的名字。
演示 private成员的修饰和使用
class Alpha
{ private int iamprivate;
private void privateMethod( )
{
System.out.println(―privateMethod‖);
}
void usePrivate( )
{ iamprivate = 10;//合法
privateMethod( );//合法
}
}
class Beta
{ void accessMethod( )
{ Alpha a = new Alpha( );
a.iamprivate = 10; // 非法
a.privateMethod( ); // 非法
}
}
protected
由 protected修饰的成员(也称受
保护成员)允许被声明它的类本
身、声明它的类的子类(必须在
同一个包中)及与它在同一个包
中的其它类使用
演示 protected成员的修饰和使用
package A;
class Alpha
{ protected int iam;
protected void aMethod( )
{ System.out.println(―aMethod‖);
}
}
class Gamma
{ void accessMethod( )
{ Alpha a = new Alpha( );
a.iam = 10; //合法
a.aMethod( );//合法
}
}
package B;
class Gamma
{ void accessMethod( )
{ Alpha a = new Alpha( );
a.iamp = 10; //非法
a.aMethod( );//非法
}
}
public
由 public修饰的成员(也称公共
成员)允许被任何包中的任何类
使用
演示 public成员的修饰和访问
package Greek;
class Alpha
{ //成员变量 iam和成员方法 aMethod都被修饰为公共成员 public int iam;
public void aMethod( )
{ System.out.println(―aMethod‖);
}
}
import Greek.* ;
package Roman ;
class Beta
{ void accessMethod( )
{ Alpha a = new Alpha( );
a.iam = 10; // 合法
a.aMethod( ); // 合法
}
}
friendly
package A;
class Alpha
{
//声明 friendly成员
int iam;
void aMethod( )
{
System.out.println(―aMethod‖);
}
}
class Beta
{
void accessMethod( )
{
Alpha a = new Alpha( );
a.iam = 10; // 合法
a.aMethod( ); // 合法
}
}
class Gamma extends Alpha
{
void accessMethod( )
{
Alpha a = new Alpha( );
a.iam = 10; // 非法
a.aMethod( ); // 非法
}
}
package B;
class Beta
{
void accessMethod( )
{
Alpha a = new Alpha( );
a.iam = 10; //非法
a.aMethod( ); //非法
}
}
类的修饰符
修 饰 符 作 用
private,public 说明类访问权限
Abstract 说明抽象类
Final 说明最终类
习题