1、第章 类和对象,面向对象技术基础 类的概念、定义与使用 对象的生成、使用、清除 static关键字 this关键字 final关键字 Java类中的限定词 包和import语句,3.1面向对象技术基础,3.1.1面向对象的基本概念 面向对象是一种新兴的程序设计方法,或者是一种新的程序设计规范(paradigm),其基本思想是使用对象、类、继承、封装、消息等基本概念来进行程序设计。从现实世界中客观存在的事物(即对象)出发来构造软件系统,并且在系统构造中尽可能运用人类的自然思维方式。,1对象的基本概念,对象是系统中用来描述客观事物的一个实体,它是构成系统的一个基本单位。一个对象由一组属性和对这组属
2、性进行操作的一组服务组成。从更抽象的角度来说,对象是问题域或实现域中某些事物的一个抽象,它反映该事物在系统中需要保存的信息和发挥的作用;它是一组属性和有权对这些属性进行操作的一组服务的封装体。客观世界是由对象和对象之间的联系组成的。 主动对象是一组属性和一组服务的封装体,其中至少有一个服务不需要接收消息就能主动执行(称作主动服务)。,2类的基本概念,把众多的事物归纳、划分成一些类是人类在认识客观世界时经常采用的思维方法。分类的原则是抽象。类是具有相同属性和服务的一组对象的集合,它为属于该类的所有对象提供了统一的抽象描述,其内部包括属性和服务两个主要部分。在面向对象的编程语言中,类是一个独立的程
3、序单位,它应该有一个类名并包括属性说明和服务说明两个主要部分。类与对象的关系就如模具和铸件的关系,类的实例化结果就是对象,而对一类对象的抽象就是类。,3消息,消息就是向对象发出的服务请求,它应该包含下述信息:提供服务的对象标识、服务标识、输入信息和回答信息。服务通常被称为方法或函数。,3.1.2面向对象的基本特征,1封装性 封装性就是把对象的属性和服务结合成一个独立的单位,并尽可能隐蔽对象的内部细节,包含两个含义: 把对象的全部属性和全部服务结合在一起,形成一个不可分割的独立单位(即对象)。 信息隐蔽,即尽可能隐蔽对象的内部细节,对外形成一个边界或者说形成一道屏障,只保留有限的对外接口使之与外
4、部发生联系。 封装的原则在软件上的反映是:要求使对象以外的部分不能随意存取对象的内部数据(属性),从而有效的避免了外部错误对它的“交叉感染”,使软件错误能够局部化,大大减少查错和排错的难度。,2继承性 特殊类的对象拥有其一般类的全部属性与服务,称作特殊类对一般类的继承。例如,轮船、客轮;人、大人。一个类可以是多个一般类的特殊类,它从多个一般类中继承了属性与服务,这称为多继承。例如,客轮是轮船和客运工具的特殊类。在Java 语言中,通常我们称一般类为父类(superclass,超类),特殊类为子类(subclass)。,3多态性 对象的多态性是指在一般类中定义的属性或服务被特殊类继承之后,可以具
5、有不同的数据类型或表现出不同的行为。这使得同一个属性或服务在一般类及其各个特殊类中具有不同的语义。例如:“几何图形”的“绘图”方法,“椭圆”和“多边形”都是“几何图”的子类,其“绘图”方法功能不同。,3.1.3面向对象程序设计方法,面向对象程序设计方法可分为面向对象的分析(OOA,Object Oriented Analysis)、面向对象的设计(OOD,Object Oriented Design)和面向对象的实现(OOI,Object Oriented Implementation)三个阶段。,3.2类的定义与使用,类是组成Java程序的基本要素,是Java 中的一种重要的复合数据类型。它
6、封装了一类对象的状态和方法,是这一类对象的原形。 一个类的实现包括两个部分:类声明和类体。 基本格式为: class class是关键字,用来定义类。“class ”是类的声明部分,类名必须是合法的Java标识符。两个大括号以及之间的内容是类体。,3.2.2类声明,Java中类声明的语法如下: publicabstract|final class className extends superclassName implements interfaceNameList 其中,修饰符public,abstract,final 说明了类的属性,className为类名,superclassName
7、为类的父类的名字,interfaceNameList为类所实现的接口列表,习惯上类名的第一个字母大写,但这不是必需的。类的名字不能是Java中的关键字,要符合标识符规定,名字可以由字母、下划线、数字或美元符号组成,并且第一个字符不能是数字。给类命名时,最好遵守下列习惯。 1)如果类名使用拉丁字母,那么名字的首写字母使用大写字母,如Hello、Time、People等。 2)类名最好容易识别,当类名由几个“单词”复合而成时,每个单词的首写字母使用大写,如BeijingTime、AmericanGame、HelloChina等。,3.2.3类体,Java中类体定义的语法如下: class clas
8、sName public | protected | private static final transient volatile type variableName; /成员变量的语法 public | protected | private static final | abstract native synchronized returnType methodName(paramList) throws exceptionList statements /成员方法的语法 ,3.2.4成员变量和局部变量,类体中的变量分为两部分。变量定义部分所定义的变量称为类的成员变量,在方法体中定义的变
9、量和方法的参数被称为局部变量。,成员变量的声明方式如下: public | protected | private static final transient volatile type variableName; /成员变量 其中: static :静态变量(类变量);相对于实例变量(后面会详细介绍)。 final :常量。 transient :暂时性变量,用于对象存档。 volatile :贡献变量,用于并发线程的共享。,1成员变量和局部变量的共同之处 成员变量和局部变量的类型都可以是Java中的任何一种数据类型,包括基本类型:整型、浮点型、字符型;引用类型:数组类型、对象。 成员变量
10、和局部变量的名字都必须符合标识符规定,名字如果使用拉丁字母,首写字母小写;如果多个单词组成,从第2个单词开始的其他单词的首写字母使用大写。,2成员变量和局部变量的区别,成员变量在整个类内都有效,局部变量只在定义它的方法内有效。 成员变量又分为实例成员变量(简称实例变量)和类变量(也称静态变量),如果成员变量的类型前面加上关键字static,这样的成员变量称为类变量或静态变量。,2成员变量和局部变量的区别,如果局部变量的名字与成员变量的名字相同,则成员变量被隐藏,也就是说,这个成员变量在这个方法内暂时失效。 public class Benson int x = 100, y;void f()
11、int x = 10;y = x; / 注意这里y得到的值为10,而不是100. ,2成员变量和局部变量的区别,如果局部变量的名字与成员变量的名字相同,则成员变量被隐藏,这时如果想在该方法内使用成员变量,必须使用关键字this。 public class Employee int sideA, sideB, sideC;void setSide(int sideA, int sideB, int sideC) this.sideA = sideA;this.sideB = sideB;this.sideC = sideC; ,3.2.5成员方法,一个类的类体由两部分组成:变量的定义和方法的定义
12、,方法的定义包括两部分内容:方法声明和方法体。一般格式为: public | protected | private static final | abstract native synchronized returnType methodName(paramList) throws exceptionList /方法声明 statements /方法体,方法声明中的限定词的含义: static :类方法,可通过类名直接调用。 abstract :抽象方法,没有方法体。 final :方法不能被重写。 native :集成其它语言的代码。 synchronized :控制多个并发线程的访问。,
13、1方法声明,方法声明包括方法名、返回类型和外部参数。其中参数的类型可以是简单数据类型,也可以是复合数据类型(又称引用数据类型)。 对于简单数据类型来说,Java 实现的是值传递,方法接收参数的值,但不能改变这些参数的值。如果要改变参数的值,则用引用数据类型,因为引用数据类型传递给方法的是数据在内存中的地址,方法中对数据的操作可以改变数据的值。,【例3-1】 一个展示简单数据类型与引用数据的区别的例子。,import java.io.*; public class PassTest float ptValue;public void changeInt(int value) value = 55
14、; / 在方法内部对值参数进行了修改public void changeObjValue(PassTest ref) ref.ptValue = 99f; / 在方法内部对引用参数进行了修改public static void main(String args) int val;PassTest pt = new PassTest();val = 11;System.out.println(“初始的整型值是: “ + val);pt.changeInt(val); / 值参数System.out.println(“改变后整型值是: “ + val);/ 值参数值的修改,没有影响值参数的值pt.
15、ptValue = 101f;System.out.println(“初始的整型值是: “ + pt.ptValue);pt.changeObjValue(pt); / 引用类型的参数System.out.println(“改变后整型值是: “ + pt.ptValue);/ 引用参数值的修改,改变了引用参数的值 ,2方法体,方法体是对方法的实现,它包括局部变量的声明以及所有合法的Java 指令。方法体中声明的局部变量的作用域在该方法内部。若局部变量与类的成员变量同名,则类的成员变量被隐藏。,【例3-2】一个展示局部变量和类成员变量作用域的例子。,class Variable int x =
16、0, y = 0, z = 0; /类的成员变量void init(int x, int y) this.x = x;this.y = y;int z = 5; /局部变量System.out.println(“* 初始化中 *“);System.out.println(“x=“ + x + “ y=“ + y + “ z=“ + z); public class VariableTest public static void main(String args) Variable v = new Variable();System.out.println(“* 初始化之前 *“);System
17、.out.println(“x=“ + v.x + “ y=“ + v.y + “ z=“ + v.z);v.init(20, 30);System.out.println(“* 初始化之后 *“);System.out.println(“x=“ + v.x + “ y=“ + v.y + “ z=“ + v.z); ,3.2.6方法重载,方法重载是指在一个类中用同一个名字定义多个方法,每个方法的参数必须不同,或者是参数的个数不同,或者是参数类型不同。 方法的名字与所属类型以及参数的顺序构成了方法的签名(signature),在类中每个方法的签名必须是不完全一样的,这样才能使编译器准确地判断在
18、一个特定位置上你调用的是哪个方法。,注意:方法返回值的类型不能用来区分重载的方法。不能通过两个方法的返回值的类型来区分它们。这是因为当你调用一个方法时,返回值的类型是不显示的。 参数类型的区分度一定要足够,例如不能是同一简单类型的参数,如int与long。 在很多情况下,使用方法重载是十分便利的,使用重载的最多场合是为一个类编写多个构造函数。,【例3-3】 一个方法重载的示例。,class MethodOverloading void receive(int i) System.out.println(“Receive one int data“);System.out.println(“i=
19、“ + i);void receive(int x, int y) System.out.println(“Receive two int datas“);System.out.println(“x=“ + x + “ y=“ + y); public class MethodOverloadingTest public static void main(String args) MethodOverloading mo = new MethodOverloading();mo.receive(1);mo.receive(2, 3); ,3.2.7构造方法,构造方法是一个特殊的方法。Java中
20、的每个类都有构造方法,用来初始化该类的一个对象;构造方法具有和类名相同的名称,而且不返回任何数据类型;构造方法也可以重载; 构造方法只能由new运算符调用,当用类创建对象时,使用构造方法。,【例3-4】 一个构造方法的示例。,class Point int x, y;Point() x = 0;y = 0;Point(int x, int y) this.x = x;this.y = y; 构造方法的名称必须和类名相同,区分大小写。另外,当用类创建对象时,使用构造方法。,3.2.8值得注意的问题,对成员变量的操作只能放在类方法中进行,方法可以对成员变量和方法体中的局部变量进行操作。在定义类成员
21、变量时候可以同时赋初值。比如: class A int a=12; 不可以这样做: class A int a=12;a=12; /这么赋值是非法的 主要原因就是前面我们已经介绍过的,类体的内容只有成员变量的定义和方法的定义两部分,不允许有其他任何内容。,3.3对象,定义类的最终目的是要使用这些类,创建并操纵某类的对象是使用该类的最主要手段。类是创建对象的模板,类实例化可生成对象,对象通过消息传递来进行交互。消息传递即激活指定的某个对象的方法以改变其状态或让它产生一定的行为。一个对象的生命周期包括三个阶段:生成、使用和消除。,3.3.1对象的生成,创建一个对象包括对象的声明、实例化和初始化三个
22、步骤。一般格式为: 类名 对象名 = new 类名(参数); 1声明:类名 对象名 声明并不为对象分配内存空间,而只是分配一个引用空间;对象的引用类似于指针,是32位的地址空间,它的值指向一个中间的数据结构,它存储有关数据类型的信息以及当前对象所在的堆的地址,而对于对象所在的实际的内存地址是不可操作的,这就保证了安全性。,2实例化 运算符new为对象分配内存空间,它调用对象的构造方法,返回引用。一个类的不同对象分别占据不同的内存空间。 3生成 执行构造方法,进行初始化;根据参数不同调用相应的构造方法。,【例3-5】 一个创建对象的示例。,class Student float height,
23、weight;String head, ear, hand, foot, mouth;void speak(String s) System.out.println(s); class A public static void main(String args) Student ZhangSan; / 声明对象/ 为对象分配内存,使用new 运算符和默认的构造方法ZhangSan = new Student(); ,使用new运算符和类的构造方法为声明的对象分配内存,如果类中没有构造方法,系统会自动调用默认的构造方法(默认的构造方法是无参数的,构造方法的名字必须和类名相同)。如果类里面定义了一
24、个或多个构造方法,那么Java不提供默认的构造方法,必须使用类里面定义的构造方法,否则会报错。,3.3.2对象的使用,对象不仅可以改变自己变量的状态,而且还拥有使用创建它的那个类中的方法的能力,对象通过使用这些方法可以产生一定的行为。通过运算符“.”可以实现对变量的访问和方法的调用。变量和方法可以通过设定访问权限来限制其它对象对它的访问。,1对象操作自己的变量,对象创建之后,就有了自己的变量,通过使用运算符“.”,对象可以实现对自己的变量的访问,一般格式为: 对象引用.变量 对象引用是一个已生成的对象,也可以是能生成对象的表达式。例如: p.x = 10; tx = new Point( ).
25、x;,2对象调用类中的方法,除了可以操作自己的变量外,对象还可以通过运算符“.”调用创建它的类中的方法,从而产生一定的行为功能,一般格式为: 对象引用.方法名(参数); 例如: p.move(30,20); new Point().move(30,20); 当对象调用方法时,方法中出现的成员变量就是指该对象的成员变量,方法中的局部变量被分配内存空间,方法执行完毕,局部变量即可释放内存。局部变量声明时如果没有初始化,就没有默认值,因此在使用局部变量之前,要事先为其赋值。,3.3.3对象的引用和实体,当用类创建一个对象时,类中的成员变量被分配内存空间,这些内存空间称为该对象的实体,而对象中存放着引
26、用,以确保实体由该对象操作使用。 如果一个类创建的两个对象具有相同的引用,那么就具有完全相同的实体。没有实体的对象称为空对象,空对象不能使用,即不能让一个空对象去调用方法产生行为。假如程序中使用了空对象,在运行时会出现异常:NullPointerException。但由于对象是动态地分配实体,所以Java的编译器对空对象不做检查,在编写程序时要避免使用空对象。,【例3-7】 对象引用和实体的示例。,class Point int x, y;Point(int a, int b) x = a;y = b; public class ep3_7 public static void main(St
27、ring args) Point p1, p2; / 声明对象p1和p2p1 = new Point(10, 10); / 为对象分配内存,使用 new 和类中的构造方法p2 = new Point(23, 35); / 为对象分配内存,使用 new 和类中的构造方法System.out.println(p1 = p2);p1 = p2;System.out.println(p1 = p2); ,3.3.4参数传值,当方法被调用时,如果方法有参数,参数必须要实例化,即参数变量必须有具体的值。在Java中,方法的所以参数都是“传值”的,也就是说,方法中的参数变量的值是调用者指定的值的副本。例如,
28、如果向方法的int类型参数x传递一个值,那么参数x得到的值是传递值的副本。方法如果改变参数的值,不会影响向参数“传值”的变量的值。,1基本数据类型参数的传值,基本数据类型的参数,向该参数传递的值的级别不可以高于该参数的级别,比如,不可以向int类型参数传递一个float值,但可以向double类型参数传递一个float值。,2引用类型参数的传值,Java的引用类型数据包括对象、数组和接口,当参数是引用类型时,“传值”传递的是变量的引用而不是变量所引用的实体。如果改变参数变量所引用的实体,就会导致原变量的实体发生同样的变化,但是如果改变参数的引用不会影响向其传值的变量的引用。,【例3-8】 引用
29、类型和基本数据类型参数区别的示例。,class People String face;void setFace(String s) face = s; class C void f(int x, double y, People p) x = x + 1;y = y + 1;p.setFace(“笑脸“);System.out.println(“参数x和y的值分别是:“ + x + “,“ + y);System.out.println(“参数对象p的face是:“ + p.face); public class ep3_8 public static void main(String arg
30、s) int x = 100;double y = 100.88;People zhang = new People();zhang.setFace(“很严肃的样子“);C a = new C();a.f(x, y, zhang);System.out.println(“main方法中x和y的值仍然分别是:“ + x + “,“ + y);System.out.println(“main方法中对象zhang的face是:“ + zhang.face); ,3.3.5对象的清除,Java有所谓的“垃圾收集”机制,这种机制周期地检测某个实体是否已不再被任何对象所拥有。当不存在对一个对象的引用时,该
31、对象成为一个无用对象。Java 的垃圾收集器自动扫描对象的动态内存区,把没有引用的对象作为垃圾收集起来并释放实体占有的内存。 System.gc(); 当系统内存用尽或调用System.gc()要求垃圾回收时,垃圾回收线程与系统同步运行。,3.4 static关键字,成员变量可以分为实例变量和类变量。同样,类中的方法也可分为实例方法和类方法。用static关键字修饰的变量是类变量,同样的,用static关键字修饰的方法是类方法,其格式如下: static type classVar; /类变量 static returnType classMethod(paramlist) /类方法 如果在声
32、明时不用static关键字修饰,则声明为实例变量和实例方法。,3.4.1实例变量和类变量的区别,每个对象的实例变量都分配内存,通过该对象来访问这些实例变量,不同的实例变量是不同的。 类变量仅在生成第一个对象时分配内存,所有实例对象共享同一个类变量,每个实例对象对类变量的改变都会影响到其它的实例对象。类变量可通过类名直接访问,无需先生成一个实例对象,也可以通过实例对象访问类变量。 在下面的例子中,两个梯形对象共享一个底。,【例3-9】 实例变量和类变量举例。,class 梯形 float 上底, 高;static float 下底;梯形(float x, float y, float h) 上底
33、 = x;下底 = y;高 = h;float 获取下底() return 下底;void 修改下底(float b) 下底 = b; ,class ep3_9 public static void main(String args) 梯形 laderOne = new 梯形(3.0f, 10.0f, 20), laderTwo = new 梯形(2.0f, 3.0f, 10);梯形.下底 = 200; / 通过类名操作类变量System.out.println(“laderOne的下底:“ + laderOne.获取下底();System.out.println(“laderTwo的下底:“
34、 + laderTwo.获取下底();laderTwo.修改下底(60); / 通过对象操作类变量System.out.println(“laderOne的下底:“ + laderOne.获取下底();System.out.println(“laderTwo的下底:“ + laderTwo.获取下底(); ,3.4.2实例方法和类方法的区别,实例方法可以对当前对象的实例变量进行操作,也可以对类变量进行操作,实例方法由实例对象调用。 但类方法不能访问实例变量,只能访问类变量。类方法可以由类名直接调用,也可由实例对象进行调用。类方法中不能使用this或super关键字。,【例3-10】 关于实例成
35、员和类成员的例子。,class Member static int classVar;int instanceVar;static void setClassVar(int i) classVar = i;/ instanceVar=i; / 类方法不能访问实例变量static int getClassVar() return classVar;void setInstanceVar(int i) classVar = i; / 实例方法不但可以访问类变量,也可以实例变量instanceVar = i;int getInstanceVar() return instanceVar; ,publ
36、ic class MemberTest public static void main(String args) Member m1 = new Member();Member m2 = new Member();m1.setClassVar(1);m2.setClassVar(2);System.out.println(“m1.classVar=“ + m1.getClassVar() + “m2.ClassVar=“+ m2.getClassVar();m1.setInstanceVar(11);m2.setInstanceVar(22);System.out.println(“m1.In
37、stanceVar=“ + m1.getInstanceVar()+ “ m2.InstanceVar=“ + m2.getInstanceVar(); ,3.5 this关键字,this是Java的一个关键字,表示某个对象。this可以出现在实例方法和构造方法中,但不可以出现在类方法中。this关键字出现在类的构造方法中时,代表使用该构造方法所创建的对象。实例方法必须通过对象来调用,当this关键字出现在类的实例方法中时,代表正在调用该方法的当前对象。 成员函数中定义了和成员变量中相同的变量时,引用成员变量要用this. 构造函数中调用同一个类的其他构造函数时用this。,【例3-11】编写
38、两个重载构造器的类,在第一个构造器中使用this调用第二个构造器。,public class ThisConstructorCall public ThisConstructorCall(String s) System.out.println(“s = “ + s);public ThisConstructorCall(int i) this(“i = “ + i);public static void main(String args) new ThisConstructorCall(“String call“);new ThisConstructorCall(47); ,第二个构造器的输
39、出会显示“s=i=47”,当在同一个类中想要用构造器调用构造器时用的是this这个关键字,而且必须写在构造器的首行,和方法调用差不多,当见到this时,说明你要调用另外一个符合标准的构造器。 new ThisConstructorCall(“String call“); 调用构造器完成实例化和初始化,在JVM中开辟了一个空间,里面放的是ThisConstructorCall类型的对象。 new ThisConstructorCall(47); 这句调用的是 public ThisConstructorCall(int i); 这个构造器,进入构造器内部执行里面的内容,当遇到 this(“i =
40、 “ + i); 语句时,又调用了 ThisConstructorCall(String s) 这个构造器,把“i=47”作为一个字符串传给了s,所以最后的输出结果就是“s=i=47”。,3.6 final关键字,final 关键字可以修饰类、类的成员变量和成员方法。用final修饰成员变量,说明该成员变量是最终变量,即为常量。程序中的其他部分可以访问,但不能够修改。用final修饰成员方法,则该方法不能再被子类所重写,即该方法为最终方法。,1final 修饰成员变量,final修饰变量,则成为常量,例如 final type variableName; 修饰成员变量时,定义时同时给出初始值,
41、而修饰局部变量时不做要求。,2final 修饰成员方法,final修饰方法,则该方法不能被子类重写。 final returnType methodName(paramList) ,3final 类,final修饰类,则类不能被继承。如果一个类被final关键字修饰,说明这个类不能再被其他类所继承,该类被称为最终类。final class finalClassName 在默认情况下,所有的成员变量或成员方法都可以被隐藏或重写,如果父类的成员不希望被子类的成员所隐藏或重写则将其声明为final。,【例3-12】final用法举例。,class ep3_12_a static final doub
42、le pi = 3.1415926; / 声明静态常量public final void f() / 声明最终方法System.out.println(“pi=“ + pi); class ep3_12_b extends ep3_12_a private int num = 100;public void f() / 出错,不可覆盖父类的最终方法System.out.println(“num=“ + num); class ep3_12 public static void main(String args) ep3_12_b One = new ep3_12_b();One.f(); ,由
43、于父类方法f已经被声明为final,所以在子类ep3_12_b中对f方法重写出现错误。变量pi被声明为final所以子类也不能继承该变量。 需要注意的是: 被private声明为私有的方法,以及包含在final类中的方法都被默认为是最终的。 用static和final两个关键字修饰变量时,若不给定初始值,则按照默认规则对变量初始化。若只用final修饰而不用static,就必须且只能对该变量赋值一次,不能默认。,3.7 Java类中的限定词,Java 语言中有四种不同的限定词,提供了四种不同的访问权限,限定词主要用来修饰成员变量或方法。,1private,用private修饰的成员变量和方法称
44、为私有变量和私有方法,类中限定为private的成员,只能被这个类本身访问。如果一个类的构造方法声明为private,则其它类不能生成该类的一个实例。 对于私有成员变量和方法,只有在本类中创建该类的对象时,这个对象才可以访问自己的私有成员变量和类中的私有方法,如下例所示:,【例3-13】私有成员变量和方法的用法举例。,class ep3_13 private int money;ep3_13() money = 2000;private int getMoney() return money;public static void main(String args) ep3_13 exa = n
45、ew ep3_13();exa.money = 3000;int m = exa.getMoney();System.out.println(“money=“ + m); ,2default 类中不加任何访问权限限定的成员属于缺省的(default)访问状态,可以被这个类本身和同一个包中的类所访问。非本包内的类不能访问。 3protected 类中限定为protected的成员,可以被这个类本身、它的子类(包括同一个包中以及不同包中的子类)和同一个包中的所有其他的类访问。 4public 用public修饰的成员变量和方法称为共有变量和共有方法,类中限定为public的成员,可以被所有的类访问
46、。在任何一个类中用构造方法创建了一个对象后,这个对象都可以访问自己的public变量和方法。,3.8 包,包是将一些类聚集在一起的一个实体,是Java语言中有效管理类的一个机制。 当一个大型程序交由数个不同的程序人员开发时,用到相同的类名是很有可能的,Java程序开发中为了避免这种情况,提供了一个包的概念(package)。同一个包内的类名不允许重复,不同包内可以有相同名称的类。,3.8.1包语句,使用包很简单,通过关键字package声明包语句。package语句作为Java源文件的第一条语句,指明该源文件定义的类所在的包。package语句一般格式为: package packageNam
47、e; 包名可以是一个合法的标识符,也可以是若干个标识符加“.”分割而成,如: package tom; package ; 如果源文件中省略了package语句,那么源文件定义的类隐含地认为是无名包的一部分,也就是说源文件定义命名的类在同一个包中,但该包没有名字。,【例3-14】使用包的范例。,package chapter3; public class ep3_14 public void getPrimnumber(int n) int sum = 0, i, j;for (i = 1; i i / 2)System.out.print(“ “ + i);public static voi
48、d main(String args) ep3_14 p = new ep3_14();p.getPrimnumber(20); ,程序中如果使用了包语句,例如 package chapter3; 那么目录必须包含有相对应的结构: chapter3 并且要将源文件保存在目录chapter3下,然后编译该文件:运行该程序必须到chapter3的上一层目录中运行,如:因为起了包名,所以类ep3_14的全名已经是chapter3.ep3_14了,所以要到上一层目录来运行。,3.8.2 import语句,在编写程序时,除了自己编写类外,还经常需要使用Java提供的许多类,这些类可能在不同的包中,使用i
49、mport语句可以引入包中的类。 在一个Java源文件中可以有多个import语句,它们在程序中的位置是有要求的,必须写在package语句和源文件的类定义之间。 要引入java.util包中的Date类,使用: import java.util.Date; 如果要引入一个包中的全部类,则可以用星号来代替,如: import java.awt.*;,【例3-14】使用import语句的范例。,import java.applet.Applet; import java.awt.*; public class ep3_15 extends Applet Button redbutton;public void init() redbutton = new Button(“我是一个红色的按钮“);redbutton.setBackground(Color.red);redbutton.setForeground(Color.white);add(redbutton); 注意:如果使用import语句引入整个包中的类,那么可能会增加编译的时间,但不会影响程序运行的性能,因为当程序执行时,只是将真正使用的类的字节码文件加载到内存。,