java中的继承——父类与子类的关系

java中的继承——父类与子类的关系

转载请声明

java中规定一个父类可以有多个子类,但是一个子类只能有一个父类。
子类可以通过extends关键字来继承父类。
做个比较通俗的比喻,就像一个父亲可以有多个孩子,但是每个孩子只能有一个亲生父亲。

定义:

一. 子类引用指向自身对象时

  • 若子类覆盖了某方法,则子类引用调用子类重新定义的新方法
  • 若子类未覆盖某方法,则子类引用调用父类本身的旧方法
  • 若子类覆盖了某属性,则子类引用调用子类重新定义的新属性
  • 若子类未覆盖某属性,则子类引用调用父类本身的旧属性
  • 子类引用可以访问子类新定义的方法

总结:当子类引用自身的对象时:
当子类覆盖了某方法或者某属性则子类调用的是子类重新新定义的新方法或者新属性。

二. 父类引用指向子类对象时

属性不具有多态性
所以若子类覆盖了父类的某属性,但父类引用仍调用父类本身的旧属性

  • 若子类覆盖了某方法,则父类引用调用子类重新定义的新方法
  • 若子类未覆盖某方法,则父类引用调用父类本身的旧方法
  • 若子类覆盖了某属性,但父类引用仍调用父类本身的旧属性
  • 若子类未覆盖某属性,则父类引用调用父类本身的旧属性
  • 父类引用访问子类新定义的方法时需要向下转型

总结一句话:当父类引用自类的对象时:
子类覆盖父类的方法或属性后,只有新方法才能被调用,属性则继续调用父类本身的旧属性。

Dog.java

//Dog作为Animal的子类
//Dogt继承Animal

public class Dog extends Animal{

  //私有的属性
  public Dog(String name, int age, String color, String kind) {
  super();
  this.name = name;
  this.age = age;
  this.color = color;
  this.kind = kind;
 }
 
 //方法的重写
 public void sound(){
  System.out.println(this.name+"在汪汪叫!");
 }
 public void run(){
  System.out.println("小狗在跑!");
 }

Cat.java

//Cat作为Animal的子类
//Cat继承Animal
//私有的东西不能继承
//子类可以继承父类除私有以外的所有东西(方法与属性)
//父类的构造函数不能继承

public class Cat extends Animal{

public Cat(){
  super();
 }
 public Cat(String name, int age, String color, String kind) {
  super();
  this.name = name;
  this.age = age;
  this.color = color;
  this.kind = kind;
 }
}

AnimalMain.java

public class AnimalMain {
	public static void main(String[] args) {
	Animal animal= new Dog("小青",3,"黄色","小金毛");
	animal.sound();
	//如果想调用自己子类的方法时需要向下转型
	Dog dog = (Dog)animal;
	dog.run();
	Animal cat =new Cat("喵喵",1,"白色","加菲猫");
  	cat.sound();
  	}
  }
  	

父类引用子类的方法时需要向下转型
方法的向下转型Dog dog = (Dog)animal;
与字符类型类似

byte向上转型不需要特别标注

byte b=100;
int i=b;

int向下转型为byte需要强制转,转byte型要在i前加一个(byte)

byte b1=(byte)i;

Animal.java

//父类
//父类内可以包含子类公有地属性与方法
public class Animal {

 protected String name;
 protected int age;
 protected String color;
 protected String kind;
 
 public void eat(String food){
  System.out.println(this.name+"吃"+food);
 }
 public void sound(){
  System.out.println(this.name+"欢乐的嘶吼!");
 }
 
 public String getName() {
  return name;
 }
 public void setName(String name) {
  this.name = name;
 }
 public int getAge() {
  return age;
 }
 public void setAge(int age) {
  this.age = age;
 }
 public String getColor() {
  return color;
 }
 public void setColor(String color) {
  this.color = color;
 }
 public String getKind() {
  return kind;
 }
 public void setKind(String kind) {
  this.kind = kind;
 }
}

运行结果

小青在汪汪叫!
小狗在跑!
喵喵欢乐的嘶吼!

  • 怎么判定发生了多态
  • 1.继承 子类要去继承父类
  • 2.方法重写 子类要去重写父类的方法且方法名一定要相同
  • 3.父类的引用指向子类的对象(向上转型)
  • 4.当父类调用父类的方法时,实际执行的时子类的方法(表现出子类 的特征)
  • 5.只能调用父类现有的方法
  • 6.如果父类调用子类自己的方法需要向下转型
  • 20
    点赞
  • 61
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
面向对象编程的基础 要了解面向对象编程(OOP)的基本概念,需要理解 OOP 的三个主要概念,它们撑起 了整个 OOP 的框架。这三个概念是:封装、继承性和多态性。除此以外,还需了解对象、 、消息、接口、及抽象等概念。 2.2.1 对象 现实世界的对象具两个特征:状态和行为。例如:自行车有状态(传动装置、步度、 两个车轮和齿轮的数目等)和行为(刹车、加速、减速和换档等)。 其次,我们再来看看软件对象。软件对象是现实世界对象的模式化产物,他们也有状态 和行为。软件对象把状态用数据表示并存放在变量里,而行为则用方法实现。实际上,软件 对象还包括了数据结构和使用这些数据结构的代码。因此也可以说:软件对象是现实世界客 观事务的软件化模拟,是变量(数据和数据结构)和相关方法(对数据操作和对象管理的程 序)的软件组合。 在面向对象的程序设计,你可以用软件对象表示现实世界的对象,而这些软件对象和 现实世界对象是相对应的。例如:如果你正在建立一个帐户管理系统,那么你的对象就是帐 户、欠款、信用卡、月收入、贷款、交易等等。如果你设计一个电实习交通工具系统,那 么你的对象就是汽车、摩托车、自行车等等。就自行车的软件对象而言,表示该对象的状态 和行为应为与变量和方法相对应。自行车的状态:数度是 10mp(每小时 10 米),步度是 90rpm (每分钟 90 转),当前传动装置是第 5 个齿轮。再面向对象的程序设计,这些数据应放在 变量。自行车的行为:刹车,改变步度和换档。在面向对象的程序设计,这些行为用方 法实现。 在 OOP 技术,对象充当了一个很重要的角色。对象的数据是组成对象的核心,而方法 则环绕这个核心并隐藏在对象之。 2.2.2 封装 "封装"是 OOP 语言的优点之一。把一个对象的数据加以包装并置于其方法的保护之下 称为封装。所谓封装就是对数据的隐藏。封装实现了把数据和操作这些数据的代码包装成为 一个对象(即离散的部件),而数据和操作细节(方法)隐藏起来。如果增加某些限制,使 得对数据的访问可按照统一的方式进行,那些能比较容易地产生更为强壮的代码。 OOP 语言提出一种(或称为协议),以保证对数据进行统一的操作。通常的做法是:程 序和对象数据的交互作用通过一个公开的接口进行,而不直接进行操作。由于把数据封装在 对象,所以,访问对象的数据只有一种途径,那就是利用一个公开的接口。 实际上,封装在程序和数据之间设置了一道栅栏,它可以阻止一部分的设计错误,不至 于涉足应用程序其他部分的数据。 2.2.3 消息 一个单独的对象一般不十分有用,而作为一员出现在包含有许多其他对象的大程序或应 用程序之,通过这些对象的相互作用,程序员可实现高层次的操作和更负责的功能。某此 对象通过向其他对象发送消息与其他对象进行交互作用和通信。 消息是以参数的形式传递给某方法的。一个消息通常由三部分组成: 1. 消息传送到对象的名称。 2. 要执行的方法的名称。 3. 方法需要的任意参数。 2.2.4 是一个蓝图或样板,定义了某种型的所有对象的变量和方法。 在 java 语言Java 程序的基本单位是,也就是说:一个 Java 程序是由多个组成 的。定义一个与定义一个数据型是有区别的。在程序设计语言,把定义数据型的能 力作为一种很重要的能力来对待。在面向对象的语言的功能更强大,这是因为不仅 含有定义数据型的功能,而且还包含了对方法的定义。 对象实际是的一个实例。生成实例的过程叫做把"一个对象实例化"。一个实例化 的对象实际上是由若干个实例变量和实例方法组成的。当你创建出一个的实例时,系统将 为实例变量指定内存,然后你就可以利用实例方法去做某些事情。 2.2.5 继承 继承是指建立子类的能力。子类继承了父亲的特征和功能。的层次结构似于一棵数 的结构,也像一个家庭谱系。它显示了根和它的导出之间的关系子类从它先辈那里继承了代码和数据,这样,它就可以执行先辈的功能和访问先辈 的数据。一个纯面向对象程序设计的语言将具有严格的继承性。 通过对象、,我们实现了封装,通过子类我们可以实现继承。例如,公共汽车、出租 车、货车等都是汽车,但它们是不同的汽车,除了具有汽车的共性外,它们还具有自己的特 点(如不同的操作方法,不同的用途等)。这时我们可以把它们作为汽车的子类来实现,它们 继承父类(汽车)的所有状态和行为,同时增加自己的状态和行为。通过父类子类,我们实 现了的的层次,可以从最一般的开始,逐步特殊化,定义一系列的子类。同时,通过继 承也实现了代码的复用,使程序的复杂性线性地增长,而不是呈几何级数增长。 2.2.6 抽象 面向对象的程序设计系统鼓励充分利用"抽象"。在现实世界,人们正是通过抽象来 理解复杂的事务。例如:人们并没有把汽车当作成百上千的零件组成来认识,而是把它当作 具有自己特定行为的对象。人们可以忽略发动机、液压传输、刹车系统等如何工作的细节, 而习惯于把汽车当作一个整体来认识。 包含通用对象的库叫作库。 2.2.7 多态型 面向对象程序的最后一个概念是多态性。凭借多态性,你可以创建一个新的对象,它具 有与基对象相同的功能,但是这些功能的一个或多个是通过不同的方式完成的。例如:在 Java 你可以凭借多态性,通过一个画圆的对象,来创建一个画椭圆或矩形的对象。不管是 画圆,画椭圆还是画矩形的方法,它们都有一个相同的方法名,但以不同的方式完成他们的 画圆的功能。 1.8 和对象 1.8.1 是组成 Java 程序的基本要素。它封装了一对象的状态和方法,是这一对象的 原型。定义一个,实际上就是指定该所包含的数据和对数据进行操作的代码。 通过关键字 class 来定义,一般格式为: 【说明修饰符】class 名【extends 句】【implements 句】 type instance-varable1; type instance-varable2; type instance-varable3; the methodname1(parameter-list){method-body;} the methodname2(parameter-list){method-body;} the methodnameN (parameter-list){method-body;} 下面将定义格式的项目说明如下: (1) class 是说明关键字。 (2) 名是由程序员自己定义的 Java 标识符,每个说明必须有 class 和名。 (3) 说明修饰符包括:  abstract 说明一个为抽象,抽象是指不能直接实例化对象的。  final 说明一个为最终,即改不能再有子类。  public 说明为公共,该可以被当前包以外的和对象使用。  private 说明为私有。 (4) extends 句用于说明的直接超。 (5) implements 句用于说明将实现哪些接口,接口是 Java 的一种引用 型。 (6) 体包含了变量和方法。在定义的数据、变量和方法称为的成员, 或称为实例变量和实例方法。 (7) 例如: 下例定义了一个 Point ,并且声明了它的两个变量 x、y 坐标 ,同时实现 init()方法 对 x、y 赋初值 。 class Ponit { int x,y; void init(int ix, int iy){ x=ix; y=iy; } } 所定义的变量和方法都是的成员。对的成员可以设定访问权限 ,来限定 其它对象对它的访问,访问权限所以有以下几种:private, protected, public, friendly。 1.8.2 对象 把实例化,我们可以生成多个对象,这些对象通过消息传递来进行交互(消息 传递即激活指定的某个对象的方法以改变其状态或让它产生一定的行为),最终完 成复杂的任务。一个对象的生命期包括三个阶段:创建对象、对象的引用和释放对 象 。 1.8.3 创建对象 创建对象包括声明、实例化和初始化三方面的内容。通常的格式为 : 1. 声明对象 对象声明实际上是给对象命名,也称定义一个实例变量。对象声明的一般格式为: type name 其,type 是一个名,用它声明的对象将属于改;name 是对象名。 例如: Date today; Rectangle myRectangle; 第一条语句说明了对象 today 属于 Date ,第二条语句说明了对象 myRectangle 属于 Rectangle 。对象说明并没有体现一个具体的对象,只有通过实例化后的对 象才能被使用。 2. 实例化对象 实例化对象就是创建一个对象。实例化对象意味着给对象分配必要的存储空间,用 来保存对象的数据和代码。实例化后的每个对象均占有自己的一块内存区域,实例 化时,每个对象分配有一个"引用"(reference)保存到一个实例变量。"引用" 实际上是一个指针,此指针指向对象所占有的内存区域。 因此,对象名(变量)实际上存放的是一个被实例化之后的对象所占有的内存区域 的指针。 例如: type objectName = new type ( [paramlist] ); 运算符 new 为对象分配内存空间 ,实例化一个对象 。new 调用对象的构造方法,返 回对该对象的一个引用(即该对象所在的内存地址)。用 new 可以为一个实例化, 多个不同的对象。这些对象分别占用不同的内存空间,因此改变其一个对象的状 态不会影响其它对象的状态 。 3.初始化对象 生成对象的最后一步是执行构造方法,进行初始化。由于对构造方法可以进行重写 ,所以通过给出不同个数或型的参数会分别调用不同的构造方法。 例:以 Rectangle 为例,我们生成 Rectangle 的对象: Rectangle p1=new Rectangle (); Rectangle p2=new Rectangle (30,40); 这里,我们为 Rectangle 生成了两个对象 p1、p2,它们分别调用不同的构造方法, p1 调用缺省的构造方法(即没有参数),p2 则调用带参数的构造方法。p1、p2 分别对 应于不同的内存空间,它们的值是不同的,可以完全独立地分别对它们进行操作。虽 然 new 运算符返回对一个对象的引用,但与 C、C++的指针不同,对象的引用是指 向一个间的数据结构,它存储有关数据型的信息以及当前对象所在的堆的地址, 而对于对象所在的实际的内存地址是不可操作的,这就保证了安全性。 1.8.4 对象的引用 对象的使用包括引用对象的成员变量和方法,通过运算符·可以实现对变量的访问和方法的调 用,变量和方法可以通过设定一定的访问权限(见下面的例)来允许或禁止其它对象对它的 访问。 我们先定义一个 Point。 例: class Point{ int x,y; String name = "a point"; Point(){ x = 0; y = 0; } Point( int x, int y, String name ){ this.x = x; this.y = y; this.name = name; } int getX(){ return x; } int getY(){ return y; } void move( int newX, int newY ){ x = newX; y = newY; } Point newPoint( String name ){ Point newP = new Point( -x, -y, name ); return newP; } boolean equal( int x, int y ){ if( this.x==x && this.y==y ) return true; else return false; } void print(){ System.out.println(name+" : x = "+x+" y = "+y); } } public class UsingObject{ public static void main( String args[] ){ Point p = new Point(); p.print(); //call method of an object p.move( 50, 50 ); System.out.println("** after moving **"); System.out.println("Get x and y directly"); System.out.println("x = "+p.x+" y = "+p.y); //access variabl es of an object System.out.println("or Get x and y by calling method"); System.out.println("x = "+p.getY()+" y = "+p.getY()); if( p.equal(50,50) ) System.out.println("I like this point!!!! "); else System.out.println("I hate it!!!!! "); p.newPoint( "a new point" ).print(); new Point( 10, 15, "another new point" ).print(); } } 运行结果为: C:\java UsingObject a point : x = 0 y = 0 **** after moving ***** Get x and y directly x = 50 y = 50 or Get x and y by calling method x = 50 y = 50 I like this point!!!! a new point : x = -50 y = -50 another new point : x = 10 y = 15 1.引用对象的变量 要访问对象的某个变量,其格式为: objectReference.variable 其 objectReference 是对象的一个引用,它可以是一个已生成的对象,也可以是能够生成对 象引用的表达式。 例如:我们用 Point p=newPoint();生成了 Point 的对象 p 后,可以用 p.x,p.y 来访问该点的 x、y 坐标,如 p.x = 10; p.y = 20; 或者用 new 生成对象的引用,然后直接访问,如: tx=new point().x; 2.调用对象的方法 要调用对象的某个方法,其格式为: objectReference.methodName ( [paramlist] ); 例 如我们要移动 Point 的对象 p,可以用 p.move(30,20); 虽然我们可以直接访问对象的变量 p.x、p.y 来改变点 p 的坐标,但是通过方法调用的方 式来实现能更好地体现面向对象的特点,建议在可能的情况下尽可能使用方法调用。 同样,也可以用 new 生成对象的引用,然后直接调用它的方法,如 new point(). move (30,20); 前面已经讲过,在对象的方法执行完后,通常会返回指定型的值,我们可以合法地使 用这个值,如:例 Point 的方法 equal 返回布尔值,我们可以用它来作为判断条件分别执 行不同的分支。如: if (p.equal (20,30)){ ...... //statements when equal }else { ...... //statements when unequal } 另外, Point 的方法 newPoint 返回该点关于原点的对称点,返回值也是一个 Point 型,我们 可以访问它的变量或调用它的方法,如: px = p.newPoint().x 或 px = p.newPoint(). getX(); 1.8.5 成员变量 对象具有状态和行为,而对象的状态则是用变量或数据来描述的。在一个,对象的 状态是以变量或数据的形式定义的。 例如: "盒"的体积的状态主要是宽度、高度、和深度。因此在定义"盒"对象时,只 将这三个属性作为其主要的状态,并用变量的形式来描述,这些变量称为成员变量。而在对 象实例化后,这些变量称为实例变量。 1.8.6 成员变量定义格式 成员变量定义的一般格式为: 【Modifer】type variablelist; 其, type 指定变量的型,它可以时 Java 的任意一种型。 variablelist 是一组逗号隔开的变量名(变量列表),每个变量都可带有自己的初始化的表达 式。 例如: xint ,z; aint ,b=2,c=3; Modifer 是定义变量的修饰符,它说明了变量的访问权限和某些使用规则。变量修饰符可以 是关键字 public、protected、private、final、static、transient 和 volatile 的组合。 1.8.7 成员变量的初始化 当成员变量含有自己的初始化表达式时,可以创建实例的方式使成员变量实例化。 例如: class Box{ double width = 10; double height= 15; double depth= } 变量 width、height、depth 是成员变量。在执行 Box myBox1 = new Box()语句之后, new 运算符就创建了一个实例,并将变量分别赋初值为 10、15、20。在此时的变量 width、 height、depth 称为实例变量。 注意:在初始化表达式,不能包含成员变量本身或同的其他成员变量。例如,下面 的用法式错误的: class Test{ int int t =j; int } 错误有两个:一个式变量 k 的初始化涉及对 k 自身的访问;二式对 t 进行初始化时含有 对 j 的访问,而 j 的说明在其后。 1.8.8 成员变量的访问权限 成员变量或方法的访问权限是用访问权限修饰符来指定的。Java 的访问权限修饰符包括四种 显示方式修饰符和一种隐含方式修饰符,即: 1. 公用变量 用 public 说明的变量是公有变量。 访问权限:允许任何包的任何的变量访问。 例如:下面的代码,在 Alpha 说明了一个公用变量 i_public,而在另一个 Beta 可以访问该变量。 class Alpha{ public int i_public ; } class Beta{ void accessmethod() { Alphaa= newAlpha(); a.i_public=10; } } 2. 私有变量 //说明公用变量 i_public //访问公用变量 i_public 用 private 说明的变量是私有变量。 访问权限:只能被定义它的的变量访问。 例如:下面的代码,在 Alpha 说明了一个私有变量 i_private,其他不允 许访问。 正确的访问格式: class Alpha{ 3. 保护变量 } public int i_private ; void accessmethod() { Alphaa= newAlpha(); a.i_private=10; } //说明私有变量 i_private //访问私有变量 i_private 用 protected 说明的变量是保护变量。 访问权限:允许自身、子类以及在同一个包的所有的变量访问。 例如:假定某个包 Geek 含有两个成员 Alpha 和 Beta,若在 Alpha 说明 了一个保护变量 i_protected,则在另外一个 Beta 可以访问该变量。 class Alpha{ public int i_protected; void accessmethod() } class Beta { void accessmethod() { Alpha a= new Alpha(); a.i_protected=10; } } 4. 私有保护变量 //说明保护变量 i_protected //访问保护变量 i_protected 用 private protected 说明的变量是私有保护变量。 访问权限:允许自身以及它的子类变量访问。 例如:下面的两种访问方式是可行的。 (1) 在访问私有保护变量 例如: class Alpha{ private protected int i_pri_prot ; void accessmethod() { Alphaa= newAlpha(); } } a. i_pri_prot =10; //访问私有保护变量 i_pri_prot (2) 在子类访问私有保护变量 例如: class Alpha{ private protected int i_pri_prot=10 ; } class Beta extends Alpha { void accessmethod() { Alphaa= newAlpha(); } } a. i_pri_prot =30; //访问私有保护变量 i_pri_prot 在程序执行时,变量 i_pri_prot 的值是 30,而不是 10; 5. 友好变量 如果一个变量没有显示地设置访问权限,则该变量为友好变量。 访问权限:允许自身以及在同一个包地所有地变量访问。 例如:下面的定义了一个友好变量: class Alpha{ int i_friendly ; void accessmethod() { Alphaa= newAlpha(); } } a. i_friendly=10; //访问友好变量 i_friendly 在了解了成员变量的访问权限之后,那么在说明每一个成员变量时,都可以按访问权限给变 量提供适当的保护措施,这样就加强了变量的安全性。 名称 公用 私有 保护 私有保护 访问权限修饰 public private protected private protected √ √ √ √ 子类 √ √ √ 包 √ * 所有 √ √ 友好 friendly √ √ 注:表√的为可选,打*的说明有特殊限制。*号是针对子类访问保护变量而言,即一个子类只有与超 在同一个包,才可以访问超对象的保护变量。 1.8.9 静态变量 用 static 说明的变量是静态变量。静态变量与其他成员变量有区别:其他成员变量必须通过 的对象来访问,每个对象都有这些变量的备份;而静态变量独立于改的任何对象,它 在的实例只有一个备份,可以直接使用,而不必通过的对象去访问,它一直属于定义 它的,因此也称为变量。的所有对象都共享 static 变量。static 变量通常也称为全局变 量。 例如: 静态变量的定义和引用。首先在 MyDemo 定义了 static 变量 x,y 然后在 MyStaticDemo 输入变量 x 和 y 的值。 import java.awt.Graphics; class MyDemo { static int x=80; static int y=120; } class MyStaticDemo extends java.applet.Applet { public void paint(Graphics g) { g.drawString("x="+MyDemo.x+"y="+MyDemo.y,25,50); } } 程序运行结果: x=80 y=120 在上面的程序,在访问的静态变量 x 和 y 时,是通过名 MyDemo 直接访问的。 static 也可以说明方法。用 static 说明的方法是静态方法或方法,在实例只有一 个备份。该方法具有以下约束: a) b) c) 它们仅可以调用其他 static 方法。 它们仅可以访问 static 变量。 它们不能参考 this 或 super。 如果的成员被定义为 static,则可以通过下面形式引用: 名,成员名 这里,名是定义 static 成员所属的Java 通过这样的方式,实现了全局方法和变量。 1.8.10 final 变量 用 final 说明的变量可以当作一个常量使用,不得对其进行任何修改。若某此变量为了 防止被修改,则定义变量时必须初始化一个 final 变量。在这一点上,final 与 C\C++的 const 相似。比如: final int MONDAY=1; final int TUSDAY=2; final int WEDNESDAY=3; ...... 以后程序可以把上述变量当作常量来使用,而不用担心其被修改。 final 变量用大写字母来表示,这是一种习惯约定。final 变量不占内存空间,实际上也 就是一个常数。 1.9 方法 1.9.1 方法的定义 方法也是的一个成员,定义方法时在定义的同时进行的。其一般格式为: type name(parameter -list) { //方法体 } 格式说明: (1) type 指定方法的返回型,简称方法的型,它可以是任何有效的型, 包括型。方法的返回或带值返回都由 return 语句实现,当一个方法没 有返回值时,其 type 必须为 void,且 return 语句可以省略。 (2) name 指定方法名,方法名可以是合适的 Java 标识符。 (3) parameter-list 指定方法的参数列表,参数包括参数的型和参数名,每个 参数用逗号隔开。在定义方法时,其参数将作为形参;在调用方法时,其 参数被称为实参。调用时是把实参的值传递给形参。入过方法没有参数, 参数列表为空,但括号"()"不能省略。 (4) 方法体包含了一组代码,它用于对数据处理。方法体用以对大括号"{}"括 起来。 例如:Box 封装"盒"的状态和行为,即数据变量和方法,用方法 volume 计 算 Box 对象的体积。 import java.awt.Graphics; class Box { double width; double height; double depth; void setDemo(double w,double h,double d) { width=w; height=h; depth=d; } } double volume() { return width*height*depth; } class BoxDemo extends java.applet.Applet { public void paint(Graphics g) { double d_volume; Box myBox = new Box(); myBox.setDemo(10,20,30); //调用方法 setDemo 给变量赋值 d_volumn = myBox.volume(); //计算体积 g.drawString("myBox 的体积是:"+ d_volumn,25,50); } } 程序运行的结果如下: myBox 的体积是:6000 1.9.2 方法的访问权限 方法同成员变量一样,可以在定义时说明方法的访问权限,其说明格式和访问机制与成 员变量完全一样。 例如:私有方法、私有保护方法只能被同一个的方法调用,公用方法可以被其他 的方法调用。 import java.awt.Graphics; class Alpah1 { pivateint i_private() { int x=10; int y=20; return x+y; } public int i_public1() { return i_private(); } } class Alpah2 { public public int x,y; private protected int i_protected(int a,int h) { x=a; y=b; return x+y; } public void i_public2(int i,int j) { k=i_protected(i,j); } } class Test extends java.applet.Applet { public void paint(Graphics g) { int p1; Alpah1 ap1= newAlpah1(); Alpah2 ap2= newAlpah2(); p1=ap1.i_public1(); ap2. i_public2(50,50); g.drawString("i_public1()的返回值是:"+p1,25,50); g.drawString("i_public2()的返回值是:"+ap2.k,25,50); } } 程序运行的结果如下: 方法 i_public1()的返回值是:30 方法 i_public2()的返回值是:100 程序说明: (1)在 Alpah1 ,方法 i_private()是私有的,它只能被同的方法 i_public1()调用。 而方法 i_public1()是公有的,它可以被另一 Demo 的方法 paint()调用。 (2)在 Alpah2 ,方法 i_protected()是私有保护性的,它不能被其他的方法调用, 而只能被同(或子类)的方法 i_public2()调用。同样,方法 i_public2()也是公有的,它可 以被另一 Test 的方法 paint()调用。 (3)在方法 i_public1(),语句 return i_private()执行的顺序为:先调用,后返回。其 返回值是 x+y 的和。 (4)在方法 i_public2(int i,int j),将形参 i 和 j 作为调用方法的实参。 如:k=i_protected(i,j); (5) 在 Alpha2 ,定义了成员变量 k、x 和 y。其 k 是公有的,它可被 Test 的方法引用,其格式为:ap2.k;而变量 x 和 y 是私有的。它只能被同一的方法引用。 (6)在 Alpah1 方法 i_private(),定义的变量 x 和 y 是局部变量。 局部变量作用域是:只能在定义它的方法有效,即使同一的方法也不能引用。 例如:方法 i_public()是不能访问局部变量 x 和 y 的。 1.9.3 对象作为参数 例:给定两个数,按大小顺序输出。 import java.awt.Graphics; class Test1 { public int a,b; void mov(int i,int j) { a=i; b=j; } } class Test2 { void max(Test1 test1) { int c; if(test1.a<test1.b) { c=test1.a; 引用 test1 对象的成员变量 a。 test1.a = test.b; test1.b=c; } } } class MaxTest extends java.awt.Applet { public void paint(Graphics g) { Test1myTest1=new Test1(); Test2 myTest2 = new Test2(); myTest1.mov(45,55); //调用 Test2 的方法 max,并将对象 myTest1 作为实参。 myTest2.max(myTest1); g.drawString("大小顺序为:"+ myTest1.a+","+myTest1.b,25,50); } } 1.9.4 对象作为返回值 下面的例是把对象作为返回值的编程方法。 例如:利用方法返回对象的特性,实现对实例变量的值的递增。 import java.awt.Graphics; class Test { public int a,b; void mov( int i,int j) { a=i; b=j; } Test max() //方法 max()的返回值型是 Test 型 { Test myTest = new Test(); myTest.mov(a+10,b+10);使实例变量的值增 10。 return myTest; } } class OutMyDemo extends java.applet.Applet; { public void paint(Graphics g) { Test p1 = new Test(); Test p2; p1.mov(15,55); g.drawString("p1 的实例变量值:a="+pa1.a+",b="+pa1.b,25,75); p2=p2.amx(); g.drawString("p2(p2 加 10)的值:a="+p2.a+",b="+p2.b,25,100); } } 程序运行的结果如下: p1 的实例变量值:a=15,b=55; p2(p1 加 10)的值:a=15,b=65; p2(p2 加 10)的值:a=35,b=75; 1.10 构造方法 1.10.1构造方法概述 构造方法是一个在创建对象初始化的方法,它具有与相同的名字。事实上,除了构造 方法,在不能再有别的方法与同名。一旦定义了构造方法,在执行 new 操作期间, 首先创建对象,然后自动调用构造方法将对象初始化。 与其他方法不同,构造方法必须在 new 运算符引用,而不能按引用一般方法的格式 去引用构造方法。 在同一个,允许定义多个构造方法。这些构造方法是以参数的个数来区分的。在创 建对象时,程序员应当根据参数的个数和型来选择合适的构造方法。 如果一个没有包含构造的说明,将提供隐含的构造方法,隐含的构造方法没有参数, 它将调用超不带参数的构造方法,如果超没有不带参数的构造方法,将产生编译错 误。 构造方法有些特殊,它没有返回型甚至 void。因为构造方法的缺省返回型是型 本身。构造方法的另一个特殊性是它不能继承。 例: import java.awt.Graphics; class Test { double width; double height; double depth; Test(double w,double h,double d) //定义构造方法 Box() { width = w; height = h; depth=d; } double volume() { return width*height*depth; } } class Testing extends java.applet.applet { public void paint(Graphics g) { double d_volume; Test test = new Test()//new 运算符创建对象 test 后,随即对 test 初始化。 } } d_volume = test.volume();//计算体积 g.drawString("test 的体积是:"+d_volume,25,50); 程序运行的结果如下: test 的体积是:6000 1.10.2构造方法的访问权限 在定义构造方法时可以对他们附加访问修饰符,它们时: pulic(公有型的构造方法) private (私有型的构造访问) proected (保护型的构造方法) private protected (私有保护型的构造方法) 这四种方法访问修饰符的权限范围和方法的访问权限的范围一样。构咱方法的访问修饰符不 能是 abstract、static、final、native 或 synchronized; 1.11 方法重载 在 java ,可以在同一个定义多个同名的方法,只要它们的参数列表不同,这叫做方 法的重载(Overload)。方法重载是 Java 最具有吸引力的有利特征。 当一个重载方法被激起时,Java 便根据参数的型和数目确定被调用的方法。这样,重载方 法之间一定具有不同的参数列表,包括参数的型和数目。 例:给定两个或三个数,将它们由大到小按顺序输出。 import java.awt.Graphics; class Test { double max1,max2,nax3; Test() { max1=-1; maxe2=-1; max3=-1; } void sort(double i,double j) { double s; max1=i; max2=j; if( max1<max2) { s=max1; max1=max2; } } max2=s; } void sort(double I,double j,double k) { double s; max1=i; max2=j; max3=k; if(max1<max2) { s=max1; max1=max2; max2=s; } if(max1<max3) { s=max1; max1=max3; max3=s; } if(max2<max3) { s=max2; max2=max3; max3=s; } } class outMaxTest extends java.awt.Applet { public void paint(Graphics g) { Testt1=new Testt(); t1.sort(200,300); g.drawString("两个数的大小顺序为:"+ t1.max1+","+t1.max2,25,10); t1.sort(100.9f,200.9f,300.9f); g.drawString("三个数的大小顺序为:"+ t1.max1+","+t1.max2+","+t1.max3,25,30); } } 程序运行的结果如下: 两个数的大小顺序为:300,200 三个数的大小顺序为:300.9,200.9,100.9 在上面的代码 Test 定义了三个方法: Test()是一个无参的构造方法,它在创建对象之后紧接着对变量进行初始化。如果没有该 方法,在创建对象时将产生编译错误。因为 Test 是直接超。 两个 sort()是排序方法,它们是用参数的数目来区分的,这两个 sort()方法能对任 何数字型的数据进行排序。当然,对多个数据进行排序最好用数组来实现。 1.12 this 1.12.1用 this 引用成员变量 例:在构造方法使用 this,this 代表当前对象的引用参考,并将参数值赋值到成员 变量 max1、max2 和 max3 。 import java.awt.Graphics; class Test { double max1; double max2; double max3; Test(double i,double j) { this.max1=i; this.max2=j; this.max3=k; } } class Test1 extends java.awt.Applet { public void paint(Graphics g) { Test t = new Test(10,20,30); g.drawString(t.max1+","+t.max2+","+t.max3,25,30); } } 程序运行的结果如下: 10,20,30 1.12.2在构造方法用 this 调用一般方法 例:在构造方法使用 this 调用 sort()方法。 import java.awt.Graphics; class Test { double max1,max2,max3; Test(double i,double j) { max1=i; max2=j; this.sort(i,j); //调用 sort 方法,将两个数排大小顺序。 } Test(double i,double j,double k) { max1=i; max2=j; max3=k; this.sort(i,j,k) //调用 sort 方法,将三个数排大小顺序。 } void sort(int i,double j) { double s; if(max1<max2) { s=max1; max1=max2; max2=s; } } void sort(double i,double j,double k) { double s; if(max1<max2) { s=max1; max1=max3; max2=s; } if(max1<max3) { s=max1; max1=max3; } max3=s; } } if(max2<max3) { s=max2; max2=max3; max3=s; } class ThisTest extends java.applet.Applet { public void paint(Graphics g) { Test t1 = newTest(10,100); g.drawString("两个数的大小顺序为:"+t1.max1+","t1.max2,25,10); Test t2 = new Test(100,10,1000); g.drawString("三个数的大小顺序为:"+t2.max1+","t2.max2+","+t2.max3,25,30); } } 程序运行的结果如下: 两个数的大小顺序为:100,10 三个数的大小顺序为:1000,100,10 1.12.3在方法用 this 调用另外一个方法 例:在上面的例上加一个方法 mov(),在 mov()引用 this 再调用 sort()方法。 import java.awt.Graphics; class Test { double max1,max2,max3; Test(double i,double j) { max1=i; max2=j; this.sort(i,j); //调用 sort 方法,将两个数排大小顺序。 } void sort(int i,double j) { double s; if(max1<max2) } { } s=max1; max1=max2; max2=s; } void mov(double i,double j) { max1=i; max2=j; this.sort(i,j); } class ThisTest extends java.applet.Applet { public void paint(Graphics g) { Test t1 = newTest(10,100); t1.mov(20,200); g.drawString("两个数的大小顺序为:"+t1.max1+","t1.max2,25,10); } } 程序运行的结果如下: 两个数的大小顺序为:200,20 注意:再初始化之后,变量 max1 和 max2 的值分别为 10 和 100,当调用 mov()之后, 其值为 20 和 200。 1.13 继承 继承是面向对象程序设计的重要概念之一。在 java ,被继承称为超继承称为 子类。通过继承可使子类继承的特征和功能。其基本规则如下: (1) 子类继承其超的代码和数据,即在子类可以直接执行超的方法和访问超 的数据。 (2) 在子类可以增加超没有的变量和方法。 (3) 在子类可以重新定义超已有的变量(包括实例变量和变量)。变量的重新 定义被称为变量的隐藏,也就是说,在子类允许定义与超同名的变量。 (4) 在子类可以重载超已有的方法(包括构造方法、实例方法和方法)。 (5) 在子类的构造方法,可以通过 super()方法将超的变量初始化。 (6) 当超为抽象时,子类继承的抽象方法,并在子类去实现该方法的细 节。 1.13.1 创建子类 实现继承要用 extends 关键词,其格式如下: 子类名 extends 超名 (1) 继承的方法和变量 例:给定三个数,将它们按大到小的顺序输出。在下面的程序子类 Test1 继承 Test 的全部代码和变量。在子类的方法,调用超的方法 sort()和更 新数据。 import java.awt.Graphics; class Test { double max1,max2,max3; Test() { max1=-1 max2=-1; max3=-1; } void sort() { double s; if(max1<max2) { s=max1; max1=max2; max2=s; } if(max1<max3) { s=max1; max1=max3; max3=s; } if(max2<max3) { s=max2; max2=max3; max3=s; } } } class Test1 extends Test { void subsort(double i,doublej,double k) { max=i; max2=j; max3=k; sort(); //调用超 Test 的方法 sort() } } class SortTest extends java.applet.Applet { public void paint(Graphics g) { Test1t1 =new Test1(); t1.subsort(100,.300,200); g.drawString("三个数的大小顺序为:"+t1.max1+","t1.max2+","+t1.max3,25,30); } } 程序运行的结果如下: 三个数的大小顺序为:300,200,100 (2) 隐藏实例变量和变量 在子类,若定义了与超同名的变量,则只有子类的变量有效,而超 的变量无效。 例:数据求和。 import java.awt.Graphics; class Test { double sum,num1,num2; static int num3; Test() { num1=0; num2=0; num3=0; sum=0; } } class Test1 extendsTest { int sum,num1,num2; //隐藏超 Test 的实例变量 static int num3; //隐藏超 Test 变量 } void sum(int i,int j,int k) { num1=i; num2=j; num3=k; sum=num1+num2+num3; } class SumTest extends java.awt.Applet { public void paint(Graphics g) { Test1t1 =new Test1(); t1.sum(100,200,300); g.drawString("sum="+ t1.num1+"+"+t1.num2+"+"+t1.num+"="+t1.sum,25,30); } } 程序运行的结果如下: sum=100+200+300+=600 (3)访问权限 尽管子类可以继承的所有成员,但子类不能继承的私有变量和方法,而只能 继承如下变量和方法。 .超定义为公有的、私有保护的或保护的成员变量和方法可被子类访问。 .同一个包的超的友好变量和方法可被子类访问。 (4)用继承的方法来扩充超的功能 如果子类继承的代码和数据是没有多大意义的,对继承来说,其真正的目的是想 通过子类来扩充超来的功能,只有这样,才能有效发挥继承的作用。 例:从超 Box 只计算"盒"的体积,但在子类 SubBox 不仅只计算"盒"的 体积,而且还能求得它重量。 import java.awt.Graphics; class Box { double width; double height; double depth; Box(double w,double h,double d) { width=w; height=h; } Box() { depth=d; } width=-1; height=-1; depth=-1; } double volume() { return width*height*depth; } class SubBox extends Box { double weight; SubBox(double w,double h,double d,double m) { width=w; height=h; depth=d; weight=m; } } class Test extends java.awt.Applet { public void paint(Graphics g) { double d_volume; Box box1=new Box(10,20,30); d_volume=box1.volume(); //计算 box1 的体积 } } g.drawString("box1 的体积是:"+d_volume,25,50); SubBox subBox = new SubBox(15,15,20,40); d_volume= subBox.volume(); g.drawString("subBox 的体积是:"+d_volume,25,75); g.drawString("subBox 的体积是:"+subBox.weight,25,90); 程序运行的结果如下: box1 的体积是:6000; subBox 的体积是:4500 subBox 的重量是:40 1.13.2 重载超的方法 要使多态性在程序设计运用成功,不仅要求超子类提供可直接使用的元素,更重要的 是在层次结构具有一致的接口,使子类在超的基础上扩充超的功能。 例:超 Test 方法 sort()实现对 n 个整个升序排列,子类 Test1 的 sort()实现对 n 个整数 按降序排列。 import java.awt.Graphics; class Test { int Test() { i=j=k=swap=0; } void sort(int t1,int t2[ ]) //用选择法按升序排列 { for(int i=0;i<t1-1;i++) { k=i; for(i=0;i<t1-1;j++) { if(t2[j]<t2[k]) { k=j; } if(k!=i) { swap=t2[i]; t2[i]=t2[k]; t2[k]=swap; } } } } } class Test1 extends Test { void sort(i=0;i<t1-1;i++)//重载超的方法 sort(),用选择法按降序排列 { for(int i=0;i<t1-1;i++) { k=i; for(i=0;it2[k]) { k=j; } if(k!=i) { swap=t2[i]; t2[i] =t2[k] t2[k]=swap; } } } } } class SortTest extends java.awt.Applet { public void paint(Graphics g) { int a[]={34,12,8,67,88,23,98,101,119,56}; g.drawString("排序前的数据为:",20,10); for(int i=0;i<10;i++) { g.drawString(""+a[i],20+i*30,30); } Test t1=new Test(); t1.sort(a.lenght,a); //调用 Test 的方法 g.drawString("按升序排列的数据为:",20,50); for(int i=0;i<10;i++) { } g.drawString(""+a[i],20+i*30,70); } } Test1 t2=new Test2(); t2.sort(a.lenght,a); g.drawString("按降序排列的数据为:",20,90); for(int i=0;i<10;i++) { g.drawString(""+a[i],20+i*30,110); } 程序运行的结果如下: 排序前的数据为: 34 12 8 67 88 23 98 101 119 56 按升序排列的数据为: 8 12 23 34 56 67 88 98 101 119 按降序排列的数据为: 119 101 98 67 56 34 23 12 8 1.13.3 super super 是一个方法,其格式为: super(parameter-list) 其,parameter-list 是参数列表。super()的作用是调用超的构造方法。降超的变量初 始化。super()总是用于子类的构造方法,而且在子类的构造方法最先执行 super().因此, 只有 parameter-list 与超的构造方法的参数相匹配,才能有效调用超的构造方法去实现 对超的变量初始化。同时,在子类也减少了初始化编码的重复工作。 super()的用法请见下面的例: 例:在下面的例里,将子类的构造方法的赋初值改用 super()方法来完成 import java.awt.Graphics; class Box { double width; double height; double depth; Box(double w,double h,double d) { width=w; height=h; depth=d; } Box() { } width=-1; height=-1; depth=-1; } double volume() { return width* height* depth; } class SubBox extends Box { double weight; SubBox(double w,double h,double d,double m) { super(w,h,d); weight=m; } } class BoxTest extends java.awt.Applet { public void paint(Graphics g) { double d_volume; Box box1=new Box(10,20,30); d_volume=box1.volume(); //计算 box1 的体积 } } g.drawString("box1 的体积是:"+d_volume,25,50); SubBox subBox = new SubBox(15,15,20,40); d_volume= subBox.volume(); //计算 subBox 的体积 g.drawString("subBox 的体积是:"+d_volume,25,75); g.drawString("subBox 的体积是:"+subBox.weight,25,90); 程序运行的结果如下: box1 的体积是:6000; subBox 的体积是:4500 subBox 的重量是:40 但要注意的是: (1) super(w,h,d)用于子类的构造方法 SubBox()。 (2) super(w,h,d)的参数应与超的构造方法参数相匹配,即参数个数及型 一样。 1.13.4 abstract 当要求将一个超定义为抽象时,前面加关键字 abstact。其格式如下: abstract 名{} abstract 的作用是说明该是一种抽象结构。抽象结构的包含了一些抽象的方法,而这些 抽象方法只有方法的形式,即方法体是空的,方法体的细节由子类去实现。抽象方法的定义 也由关键字 abstract 来说明,其格式为: abstract 型 方法名{parameter-list}; { 其,parameter-list 是参数列表。因此,整个抽象的结构如下形式: 成员变量 1; 。。。。。 构造方法 。。。。。。 abstract 型 方法名(parameter-list); } 抽象的定义也是多态的一种体现。因为多态性具有子类重载超的方法的特性,而在超 只限定子类重载规定的方法,但这些方法的细节必须由子类来完成。所有,常把这样的 作为抽象。 抽象不能直接用 new 运算符实例化一个对象。抽象方法只能是实例化方法,它不包括 对象。 例:在抽象 Test ,定义一个抽象方法 sort(),并在子类 Test1,Test2 ,分别去实现超 的抽象方法 sort()的细节,从而分别完成对 n 个整数的降序、升序的排列。 import java.awt.Graphics; abstract class Test { int i,j,k,swap; Test() { i=j=k=swap=0; } abstract void sort(int t1,int[] t2); //定义一个抽象的方法。 } class Test1 extends Test { void sort(int t1,int t2[ ]) //重载超的方法 sort(),用选择法按降序排列 { for(int i=0;i<t1-1;i++) { k=i; } } for(i=0;it2[k]) { k=j; } if(k!=i) { swap=t2[i]; t2[i]=t2[k]; t2[k]=swap; } } class Test2 extends Test { void sort(int t1,int t2[ ]) //重载超的方法 sort(),用选择法按升序排列 { for(int i=0;i<t1-1;i++) { k=i; for(i=0;i<t1-1;j++) { if(t2[j]<t2[k]) { k=j; } if(k!=i) { swap=t2[i]; t2[i]=t2[k]; t2[k]=swap; } } } } class SortTest extends java.awt.Applet } { public void paint(Graphics g) { int a[]={34,12,8,67,88,23,98,101,119,56}; //Test k=new Test(); 此句是非法的,不能创建实例对象。 Test1 k1=new Test1(); k1.sort(a.length,a); g.drawString("按降序排列的数据为",20,10); for(int i=0;i<10;i++) { g.drawString(""+a[i],20+i*30,30); } Test2 t2=new Test2(); t2.sort(a.lenght,a); g.drawString("按升序排列的数据为:",20,50); for(int i=0;i<10;i++) { g.drawString(""+a[i],20+i*30,70); } 程序运行的结果如下: 按降序排列的数据为: 119 101 98 67 56 34 23 12 8 按升序排列的数据为: 8 12 23 34 56 67 88 98 101 119 通过本例可以发现抽象的好处:从一个抽象可以派生出多个子类,而且在各个子类允 许对同一个抽象方法产生不同的方法体。 1.13.5 final final 有三个用途:其一,可以用于创建与常量一样的变量,其二,另外 2 个用途就是防止 继承或方法被重载。 1. 最终 Java 引入了最终的概念,所谓最终既是那些不能再有子类。说明最终时可以 在最前面加上修饰符 final。 例:final class A { //.... } class B extends A //错误!不能从 A 派生 { //....... } 注意:不能将一个抽象说明为 final ,因为抽象必须要被派生来实现它的抽象 方法。当一个被说明为 final 后,也相当于隐式的说明了它的所有方法为 final。 1.14 java 包,接口和异常 包是的容器,用于保证名空间的一致性。包以层次结构组织并可被明确地引入到一 个新定义。 接口是方法的显示说明,利用接口可以完成没有具体实现的。接口虽然与抽象相似, 但它具有多继承能力。一个可以有无数个接口,但是只能从一个父类派生。 异常是代码运行时出现地非正常状态。Java 的异常是一个出现在代码描述异常状态的 对象。每当一个异常情况出现,系统就创建一个异常对象,并转入到引进异常的方法,方 法就根据不同的型捕捉异常。为防止由于异常而引起的退出,在方法退出前应执行特定的 代码段。 1.14.1 包 1.14.1.1 package 语句 包是一种命名和可视控制的机制,用户可以把某些定义在一个包 ,也可以对定义在这个包施加访问权限,以限定包外或包 内的程序对其的某些进行访问。 定义包的格式: package pkg; Java 的文件系统将存储和管理这个包。例如:属于 pkg 包的.class 文件将存储到目录 pkg。注意:目录与包的名字完全一样。 package 语句可以创建包的层次结构,通过使用逗号,把每个包分开。 多级包层次结构的一般格式为: package pkg1[.pkg2[.pkg3]] 包层次结构必须反映 Java 开发系统的文件系统。比如:pacakge java.awt.Image; 1.14.1.2 import 语句 import 语句的功能是引入包或包。它们必须位于 package 语 句与这个文件的或接口之间。 格式:import pkg1[.pkg2.(classname|*)] 这里,pkg1 是顶层包名,pkg2 是下一层包名,其间用点隔开。除了 对文件系统的限制外,对包的层次深度没有限制。最后以一个显示 方式指定一个名 classname 或*号,星号*指示 Java 编译器应该引入 整个包。 例: import java.awt.Image; import java.lang.*; 1.14.2 接口 1.14.2.1 接口的概念 接口与存在着本质的差别,有它的成员变量和方法,而接口只有 常量和方法协议,从概念来讲,接口是一组方法协议和常量的集合。 接口在方法协议与方法体实体之间只起到一种称之为界面的作用,这 种界面限定了方法实体的参数型一定要与方法协议所规定的 参数型保持一致,除此以外,这种界面还限定了方法名、参数个数 及方法返回型的一致性。因此,在使用接口时,与接口之间并不 存在子类父类的那种继承关系,在实现接口所规定的某些操作时只 存在的方法与接口之间保持一致的关系,而且一个可以和多个 接口之间保持这种关系,即一个可以实现多个接口。 1.14.2.2 接口的定义 格式: access interface name { return method-name(parameter-list); type final-varname=value; } 其,access 是访问修饰符。它只有 public 和未指定访问修饰符 两种情况。当未指定访问修饰符时,该接口只能为同一个包的 其他成员所用;当 public 修饰符说明时,该接口可以被其他任何 代码使用。name 是接口的名字,可以是任何有效的标识符。接 口体包括方法协议和常量,它们都用分号结束。在接口定义的 常量必须用变量名标识。他们隐式为 final 和 static,不能被实现 所改变。 例:interface Back { void c_back(int param); int SOON=4; } 该接口定义了一个方法协议,其参数为整数型;还定义了一整 数常量,其变量名为 SOON。该接口只能为同一个包其他成员 所用。 1.14.2.3 接口的实现 一旦接口被定义,就可以实现它。在的定义可以使用关键 字 implements 实现接口,然后在创建接口所定义的方法, implements 关键字的的格式: access class classname[extends superclass] [implements interfacename[,interface...]] { } ..... 例:定义两个接口,其方法协议分别完成两个数的加法和减法 操作,然后分别实现这两个接口的方法。 import java.awt.Graphics; interface Demo_Add { public int add(int x,int y); } interface Demo_Sub { public int sub(int x,int y); } class Demo_Add_Sub implements Demo_Add, Demo_Sub { public int add(int x,int y) { return i+y; } public int sub(int x,int y) { return x-y; } } public class Add_Sub extends java.awt.Applet { public void paint(Graphics g) { Demo_Add_Sub k=new Demo_Add_Sub(); g.drawString("x+y="+k.add(30,10),30,30); g.drawString("x-y=" + k.sub(30,10),30,50); } } 程序运行结果如下: x+y=40; x-y=20; 1.14.2.4 接口的继承 一个接口可以继承其他接口,这可通过关键字 extends 来实现,其语 法与继承相同。当一个实现一个派生接口时,必须实现所有 接口及其派生接口所定义的全部方法协议。 例:定义 5 个接口,其两个超接口。 import java.awt.Graphics; //定义接口 Test_C interface Test_C { public int add(int x,int y); } interface Test_B extends Test_C { public int sub(int x,int y); } interface Test_A extends Test_B { public int mul(int x,int y); } //定义接口 Test_Y interface Test_Y { public int div (int x,int y); } interface Test_X extends Test_Y { public int mod (int x,int y); } //定义 Test class Test implements Test_A ,Test_X { public int add(int x,int y) { return x+y; } public int sub(int x,int y) { } return x-y; } public int mul(int x,int y) { return x*y; } public int div (int x,int y) { return x/y; } public int mod (int x,int y) { return x%y; } public class Add_Mod extends java.awt.Applet { public void paint(Graphics g) { Test k =new Test(); g.drawString("x+y="+k.add(66,10),30,10); g.drawString("x-y="+k.sub(66,10),30,10); g.drawString("x*y="+k.mul(66,10),30,10); g.drawString("x/y="+k.div(66,10),30,10); g.drawString("x%y="+k.mod(66,10),30,10); } } 程序运行结果如下; x+y=76 x-y=56 x*y=660 x/y=6 x%y=6 注意:在实现一个接口时,任何都必须实现该接口或接口树的所有方法。 1.14.3 异常处理 所谓异常就是代码在运行时发生的非正常状态。Java 的异常是一个出现在代码描 述异常状态的对象。每当出现一个异常情况,就创建一个异常对象,并向导致错误 的方法抛出该对象。该方法捕捉到异常对象之后,可以选择用来处理该异常或不 管它。异常通常由 Java 运行系统产生,或者由用户的程序代码产生。Java 抛出的异 常大多是用户违背了 Java 语言的基本规则,或者超出了 Java 执行环境的约束。 1.14.4 异常处理机制 Java 通过 5 个关键字 try、catch、throw、throws 和 finally 管理异常处理。 try 用来监视它所在的那个程序块是否发生异常,如果发生异常就抛出它。对于系统 产生的异常或程序块未用 try 监视所产生的异常,将一律被 Java 运行系统自动抛 出。 catch 用来捕捉 try 程序所抛出的异常,将一律被 Java 运行系统自动抛出。 throw 可以用以人工地抛出一个异常 throws 用于从一个方法抛出一个异常。 finally 用于调用缺省异常处理。 下面是异常处理地一般形式: try { //有可能会出错地代码块,被 try 监视。 } catch(ExceptionType1 ex) { //关于 ExceptionType1 的异常处理 } catch(ExceptionType2 ex) { //关于 ExceptionType2 的异常处理 } //...... finally { //在 try 块结束前被执行的代码块。 } 1.2 常用 System 全称:java.lang.System 扩展:Object 描述:公有最终。此与 Runtime 一起可以访问许多有用的系统功能。有一些方法在 两个都出现。exit()、gc()、load()和 loadLibrary()可以通过调用 Runtime 的同名方 法来响应。特别有用的是变量 err、in 和 out,它们可以访问基本控制台 I/O。System 完全由域组成,这些域可以通过"System.变量名"和"System.方法()"的方法 进行访问。此不能被实例化。 实例变量: public static PrintStream err; public static InputStream in; public static PrintStream out; 每个变量对整个程序而言都是唯一的对象变量。这些对象可以访问系统的输入、输出和 错误输出。 常用方法: void exit(int status) 导致 Java 程序退出,向系统传递指定的状态代码。 void gc() 请求立即激活垃圾收集器开始清除不再使用的对象。 String getProperty(String key) String getProperty(String key,String def) 在系统属性表查找的一个属性。如果未发现属性,而且在 getProperty()方法指定了 参数 def,那么返回 def。 SwingUtil.ities 全称:javax.swing.SwingUtilities 扩展:Object 描述:公用。此包含了一组在 Swing 工具包使用的帮助器方法 常用方法: void paintComponent(Graphics g,Component c,Container p,int x,int y,int w,int h); void paintComponent(Graphics g,Component c,Container p,Rectangle r); void invokeLate(Runnable doRun); boolean isEventDispatchThread(); Component getRoot(Component c); JRootPane getRootPane(Component c);

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值