《Java第4章类和对象基础.ppt》由会员分享,可在线阅读,更多相关《Java第4章类和对象基础.ppt(137页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、第4章 类和对象基础内容提要Java语言是面向对象的语言,类和对象是Java语言最基本的要素。本章要点本章首先介绍面向对象的基本概念,然后介绍如何定义类、如何定义类的成员变量和成员方法;如何创建和使用对象;如何定义重载方法和构造方法、方法参数的传递;static变量和方法的使用;包的概念和import语句的使用等。4.1面向对象基础4.1.1 面向对象的基本概念4.1.2 面向对象的基本特征4.1.1 面向对象的基本概念1.对象在现实世界中,对象(object)无处不在。我们身边存在的一切事物都是对象,例如一个人、一辆汽车、一台电视机、一所学校甚至一个地球,这些都是对象。除了这些可以触及的事物
2、是对象外,还有一些抽象的概念,例如一次会议、一场足球比赛、一次账户等也都可以抽象为一个对象。一个对象一般具有两方面的特征:状态和行为。状态用来描述对象的静态特征,行为用来描述对象的动态特征。4.1.1 面向对象的基本概念例如,一辆汽车可以用下面的特征描述:生产厂家、颜色、最高时速、出厂年份、价格等。汽车可以启动、加速、转弯和停止等,这些是汽车所具有的行为或者说施加在汽车上的操作。再比如,一场足球比赛可以通过比赛时间、比赛地点、参加的球队和比赛结果等特性来描述。软件对象也是对现实世界对象的状态和行为的模拟,如软件中的窗口就是一个对象,它可以有自己的状态和行为。4.1.1 面向对象的基本概念通过上
3、面的说明,可以给“对象”下一个定义,即对象是现实世界中的一个实体,它具有如下特征:有一个状态用来描述它的某些特征。有一个状态用来描述它的某些特征。有一组操作,每个操作决定对象的一种功能或有一组操作,每个操作决定对象的一种功能或行为。行为。4.1.1 面向对象的基本概念2.类(class)类是面向对象系统中最重要的概念。在日常生活中经常提到类这个词,如人类、鱼类、鸟类等。类可以定义为具有相似特征和行为的对象的集合,如人类共同具有的区别于其他动物的特征有直立行走、使用工具、使用语言交流等。所有的事物都可以归到某类中。例如,家用电器是一类电子产品。属于某个类的一个具体的对象称为该类的一个实例(ins
4、tance)。例如,我的汽车是汽车类的一个实例。实例与对象是同一个概念。4.1.1 面向对象的基本概念类与实例的关系是抽象与具体的关系。类是多个实例的综合抽象,实例是某个类的个体实物。在Java语言中,类是一种数据类型。对于汽车类(Car)可以通过下面方式定义。public class Carprivate String model;/品牌private double price;/价格private int year;/生产年份public void start()/启动方法public void speedUp(double speed)/加速方法 4.1.1 面向对象的基本概念publi
5、c void speedDown(double speed)/减速方法public void stop()/停止方法要创建一个汽车类的实例,可以使用new运算符,例如:Car myCar=new Car();4.1.1 面向对象的基本概念3.消息对象与对象之间不是孤立的,它们之间存在着某种联系,这种联系是通过消息传递的。例如,开汽车就是人向汽车传递消息。一个对象发送的消息包含3个方面的内容:接收消息的对象;接收对象采用的方法;方法所需要的参数。请看下面下面两行代码。myCar.start();/启动汽车myCar.speedUp(50);/加速到50公里/小时这里,myCar是接收消息的对象,
6、start()和speedUp()是接收对象采用的方法,50为speedUp()方法的参数。一般发送消息的对象不用指定。4.1.2 面向对象的基本特征为支持面向对象的设计原理,所有OOP语言,包括Java在内,都有三个特性:封装性、继承性和多态性。1.封装性封装(encapsulation)就是把对象的状态(属性)和行为(方法)结合成一个独立的系统单位,并尽可能地隐藏对象的内部细节。例如,一辆汽车就是一个封装体,它封装了汽车的状态和操作。封装使一个对象形成两个部分:接口部分和实现部分。对用户来说,接口部分是可见的,而实现部分是不可见的。4.1.2 面向对象的基本特征封装提供了两种保护。首先封装
7、可以保护对象,防止用户直接存取对象的内部细节;其次封装也保护了客户端,防止对象实现部分的改变可能产生的副作用,即实现部分的改变不会影响到客户端的改变。在对象中,代码或数据对该对象来说都可以是私有的(private)或公有的(public)。私有代码和数据仅能被对象本身的其他部分访问,不能被该对象外的任何程序部分所访问。当代码或数据是公有的时,虽然它们是定义在对象中的,但程序的其他部分也可以访问。4.1.2 面向对象的基本特征类是Java的基本封装单位。类定义了对象的形式,指定了数据和操作数据的代码。Java使用一个类规范来构造对象。对象是类的实例。因此,类在本质上是指定如何构建对象的一系列规定
8、。组成类的代码或数据称为类的成员(member)。具体来说,类定义的数据称为成员变量(member variable)或实例变量(instance variable)。处理这些数据的代码称为成员方法(member method)或简称为方法(method)。方法是子例程在Java中的术语。4.1.2 面向对象的基本特征2.继承性继承(inheritance)的概念普遍存在于现实世界中。它是一个对象获得另一个对象的属性的过程。继承之所以重要,是因为它支持层次结构类的概念。我们发现,在现实世界中,许多知识都是通过层次结构方式进行管理的。例如,一个富士苹果是苹果类的一部分,而苹果又是水果类的一部分,
9、水果类则是食物类的一部分。食物类具有的某些特性(可食用,有营养)也适用于它的子类水果。除了这些特性以外,水果类还具有与其他食物不同的特性(多汁、味甜等)。苹果类则定义了属于苹果的特性(长在树上、非热带植物)。4.1.2 面向对象的基本特征如果不使用层次结构,那么对象就不得不明确定义出自己的特征。如果使用继承,对象就只需定义使自己在类中不同的属性就可以了,至于基本的属性则可以从自己的父类继承。继承性体现了类之间的是一种(IS-A)关系。类之间的关系还有组合、关联等。食物米饭水果蔬菜橘子苹果图4.1 食物类及子类层次4.1.2 面向对象的基本特征3.多态性多态性(polymorphism)是面向对
10、象编程语言的一个重要特性。所谓多态,是指一个程序中相同的名字表示不同含义的情况。面向对象的程序中的多态有多种情况。在简单的情况下,在同一个类中定义了多个名称相同的方法,即方法重载,另一种情况是子类中定义的与父类中的方法同名的方法,即方法覆盖。这两种情况都称为多态,且前者称为静态多态,后者称为动态多态。有关Java语言的多态性请参考7.6节的介绍。4.2 Java类与对象4.2.1 类的定义 4.2.2 对象的使用4.2.3 用UML图表示类 4.2.4 理解栈与堆4.2 Java类与对象本节讨论使用Java语言定义类和创建对象。类和对象这两个术语在Java语言中非常重要。Java程序的所有代码
11、都存放在类中,程序的运行就是各种对象的相互作用。类是组成Java程序的基本要素,它封装了一类对象的状态和行为,是这一类对象的原形。定义一个新的类,就创建了一种新的数据类型,实例化一个类,就得到一个对象。4.2.1 类的定义可以说Java程序一切都是对象。要想得到对象,首先必须定义类(也可以使用事先定义好的类),然后创建对象。先看下面的程序代码。程序4.1 Circle.java 4.2.1 类的定义程序定义了一个Circle类表示圆,编译该程序可得到一个Circle.class类文件。在该类中定义了一个变量radius表示圆的半径,另外定义了4个方法,分别是设置和返回圆的半径、求圆的周长和面积
12、。其中圆周率使用了常量。有了Circle类,就可以创建该类的对象,然后调用对象的方法完成有关操作,如求一个圆的面积等。4.2.1 类的定义一个类的定义包括两个部分:类声明和类体的定义。1.类声明类声明的一般格式为:publicabstract|final class ClassName extends SuperClass implements InterfaceNameList /成员变量声明 /成员方法声明4.2.1 类的定义说明:(1)类的修饰符类的访问修饰符可以是public或者缺省。若类用public修饰,则该类称为公共类,公共类可被任何包中的类使用。若不加public修饰符,类只能
13、被同一包中的其他类使用。如果类使用abstract修饰符,则该类为抽象类,抽象类不能被实例化,即不能创建该类的对象。若用final修饰则该类为最终类,最终类不能被继承。(2)class ClassName类的定义使用class 关键字,ClassName为类名,类名是由类的定义者确定的。一般类名以大写字母开头,如Circle、Employee、MyPoint、ComplexNumber等,这是Java类命名的约定(不是必须的)。4.2.1 类的定义(3)extends SuperClass如果一个类要继承某个类需使用extends指明该类的超类,SuperClass为超类名,即定义该类继承了哪
14、个类。如果定义类的时候没有指明所继承的超类,那么它自动继承Object类,Object类是Java的根类。因为Java只支持单继承,所以一个类至多只能有一个超类。有关继承的概念将在7.1节讲述。(4)implements InterfaceNameList该选项定义该类实现哪个或哪些接口。一个类可以实现多个接口,若实现多个接口,接口名中间用逗号分开。有关接口的概念将在7.6节讲述。4.2.1 类的定义2.成员变量的定义类声明结束后是一对大括号,大括号括起来的部分称为类体。类体中通常定义两部分内容:成员变量(member variable)和成员方法(member method)。成员变量和成员
15、方法称为成员(members)。成员变量提供类及对象的状态,成员方法实现类及对象的行为。成员变量的声明格式为:public|protected|privatestaticfinaltransientvolatiletype variableName=value;4.2.1 类的定义说明:(1)变量的访问修饰符public|protected|private为变量的访问修饰符。用public修饰的变量为公共变量,公共变量可以被任何方法访问;用protected修饰的变量称为保护变量,保护变量可以被同一个包中的类或子类访问;没有使用访问修饰符,该变量只能被同一个包中的类访问;用private修饰的
16、变量称为私有变量,私有变量只能被同一个类的方法访问。(2)实例变量和类变量如果变量用static修饰,则该变量称为类变量,类变量又称为静态变量。没有用static修饰的变量称为实例变量。关于实例变量和类变量的使用,请参阅4.4节。4.2.1 类的定义(3)变量类型和变量名type variableName用来指定成员变量的类型和变量名。成员变量的类型可以是任何Java数据类型,包括基本数据类型和引用数据类型。(4)使用final修饰的变量叫作最终变量,也称为标识符常量。常量可以在声明时赋初值,也可以在后面赋初值,一旦为其赋值,就不能再改变了。(5)用transient 修饰的变量称为临时变量。
17、临时变量在对象序列化时不被作为持久状态的一部分存储。(6)用volatile修饰的变量称为共享变量。在多线程的程序中,共享变量可以被异步修改。4.2.1 类的定义3.成员方法的定义类体中另一个重要的成份是成员方法。方法用来实现对象的动态特征,也是在类的对象上可完成的操作。成员方法的定义包括方法的声明和方法体的定义,一般格式如下:public|protected|privatestaticfinal|abstractnativesynchronizedreturnType methodName(paramList)throws ExceptionList/方法体4.2.1 类的定义说明:(1)方
18、法返回值与方法名mehtodName为方法名,每个方法都要有一个方法名。returnType为方法的返回值类型,返回值类型可以是任何数据类型(包括基本数据类型和引用数据类型)。若一个方法没有返回值,则returnType 应为void。例如:public void setRadius(double r)4.2.1 类的定义(2)方法参数在方法名的后面是一对括号,括号内是方法的参数列表,声明格式为:type paramName1,type paramName2type为参数的类型,paramName为参数名,这里的参数称为形式参数。方法可以没有参数,也可以有一个或多个参数。如果有多个参数,参数的
19、声明中间用逗号分开。例如:public void methodA(String s,int n)该方法声明了两个参数,在调用方法时必须提供相应的实际参数。4.2.1 类的定义(3)访问修饰符public、protected和private为方法的访问修饰符。private方法只能在同一个类中被调用,protected方法可以在同一个类、同一个包中的类以及子类中被调用,而用public修饰的方法可以在任何类中调用。一个方法如果缺省访问修饰符,则称包可访问的,即可以被同一个类的方法访问和同一个包中的类访问。(4)实例方法和类方法没有用static修饰的方法称为实例方法,用static修饰的方法称为
20、类方法。关于static修饰符的使用,请参阅4.4节。4.2.1 类的定义(5)final和abstract方法用final修饰的方法称为最终方法,最终方法不能被覆盖。方法的覆盖与继承有关。用abstract修饰的方法称为抽象方法。(6)synchronized和native修饰符用synchronized修饰的方法称为同步方法。同步方法主要用于开发多线程的程序。有关多线程请参考第13章的内容。用native修饰的方法称为本地方法,本地方法用来调用其他语言(如C语言)编写的函数。4.2.1 类的定义(7)声明方法抛出异常如果方法本身对其抛出的异常不处理,可以声明方法抛出异常。异常的声明使用th
21、rows关键字,后面给出异常名称的列表。有关异常处理请参阅第8章。提示:在类体中,经常需要定义类的构造方法,构造方法用于创建新的对象。有些专家认为构造方法不是方法,它们也不是类的成员。4.2.2 对象的使用有了类就可以创建对象并指定对象的初始状态,然后通过调用对象的方法实现对象的操作。下面程序使用Circle类求给定半径的圆的周长和面积。程序4.2 CircleTest.java4.2.2 对象的使用1.创建对象为了使用对象,一般还要声明一个对象名,即声明对象的引用(reference),然后使用new运算符号调用类的构造方法创建对象。对象声明格式如下:TypeName objectName;
22、TypeName为引用类型名,可以是类名也可以是接口名,objectName是对象名或引用名或实例名。例如,在CircleTest类中有如下两条语句:Circle cc=new Circle();4.2.2 对象的使用代码声明了一个Circle类的的引用,实际上cc只保存着实际对象的内存地址。当该语句执行后,程序创建了一个实际对象。这里使用new 运算符调用Circle类的构造方法并把对该对象的引用赋给cc。创建一个对象也叫实例化,对象也称为类的一个实例。4.2.2 对象的使用若要声明多个同类型的对象名,可用逗号分开。Circle c1,c2;通常在声明对象引用的同时创建对象。Circle c
23、c=new Circle();Integer i=new Integer(18);/Integer类的对象String s=new String(Hello);/String类的对象Date d=new Date();/Date类的对象若对象仅在创建处使用,也可以不声明引用名,如下面语句直接创建一个Circle对象,然后调用其getRadius()方法。new Circle().getRadius();4.2.2 对象的使用2.对象的使用创建了一个对象引用后,就可以通过该引用来操作对象。使用对象主要是通过对象的引用访问对象的成员变量和调用对象的成员方法。例如,在CircleTest.java程
24、序中,使用下面语句访问对象c的成员变量radius和调用对象c的成员方法:System.out.println(半径=+cc.radius);System.out.println(面积=+cc.area();4.2.2 对象的使用3.对象引用赋值对于基本数据类型的变量赋值,是将变量的值的一个拷贝赋给另一个变量,例如:int x=10;int y=x;/将x 的值10赋值给变量y对于对象的赋值是将对象的引用(地址)赋值给变量。例如:Circle c1=new Circle();Circle c2=c1;/将c1的引用赋给对象c24.2.2 对象的使用上面的赋值语句执行结果是把c1的引用赋值给了c
25、2,即c1和c2的地址相同,也就是c1和c2指向同一个对象,如图4.3所示。由于引用变量c1和c2指向同一个对象,这时如果修改了c1对象,如执行c1.setRadius(10),则输出c2的半径值也将为10。4.2.3 用UML图表示类UML(Unified Modeling Language)称为统一建模语言,它是一种面向对象的建模语言,它运用统一的、标准化的标记和定义实现对软件系统进行面向对象的描述和建模。在UML中可以用类图描述一个类。图4.4是Employee类的类图,它用长方形表示,一般包含三个部分:上面是类名,中间是成员变量清单,下面是方法清单。4.2.3 用UML图表示类从图中可
26、以看到,Employee类包含3个私有成员变量,两个构造方法和三个普通方法。在UML图中,成员变量和类型之间用冒号分隔。方法的参数列表放在圆括号中,参数需指定名称和类型,它的返回值类型写在一个冒号后面。在一个UML类图中,可以包含有关类成员访问级别的信息。public成员的前面加一个“+”,protected成员前加“#”,private成员前加“-”,不加任何前缀的成员被看作具有默认访问级别。4.2.4 理解栈与堆当Java程序运行时,JVM需要给数据分配内存空间。内存空间在逻辑上分为栈(stack)与堆(heap)两种结构。理解栈与堆对理解Java程序运行机制很有帮助。当Java程序运行时
27、,被调用方法参数和方法中定义的局部变量都存储在内存栈中,当程序使用new运算符创建对象时,JVM将在堆中分配内存。假设已经定义了Employee类,在main()方法中创建该类的一个对象,4.2.4 理解栈与堆public static void main(String args)Employee emp=new Employee(LiMing,20,4500.00);当main()方法执行时,JVM首先在栈中为其命令行参数args分配空间,这里假设传递两个参数“Args1”和“Args2”,然后为局部变量emp分配空间。如果在执行程序时传递两个命令行参数,JVM将在堆中创建String数组,
28、若在main()方法中创建了Employee对象,则该对象在堆中分配内存,上述代码执行后的栈与堆的情况如图4.5所示。4.2.4 理解栈与堆4.3 方法设计4.3.1 如何设计方法4.3.2 方法的调用4.3.3 方法重载4.3.4 构造方法4.3.5 方法参数的传递4.3.1 如何设计方法在类的设计中,方法的设计尤为重要。设计方法包括方法的返回值、参数以及方法的实现等。1.方法的返回值方法的返回值是方法调用结束后返回给调用者的数据。很多方法需要返回一个数据,这时要指定方法返回值,具体是在声明方法时要指定返回值的类型。有返回值的方法需要使用return语句将值返回给调用者,它的一般格式是:re
29、turn expression;这里,expression是返回值的表达式,当调用该方法时,该表达式的值返回给调用者。4.3.1 如何设计方法例如,Circle类的area()方法需返回面积值,因此需要指定返回值类型,如下所示:public double area()return Math.PI*radius*radius;4.3.1 如何设计方法如果方法调用结束后不要求给调用者返回数据,则方法没有返回值,此时返回类型用void表示,在方法体中可以使用return语句表示返回void,格式如下:return;注意,这里没有返回值,它仅表示将控制转回到调用处。当然,也可以缺省return,这时当
30、方法中的最后一个语句执行完以后,程序自动返回到调用处。4.3.1 如何设计方法2.方法的参数方法可以没有参数,也可以有参数。没有参数的方法在定义时只需一对括号。例如,Circle类的perimeter()方法、area()方法都没有参数。有参数的方法在定义时要指定参数的类型和名称,指定的参数称为形式参数。例如Circle类setRadius()方法带一个double型参数。对带参数的方法,在调用方法时要为其传递实际参数。方法的参数类型可以是基本类型,也可以是引用类型。4.3.1 如何设计方法3.方法的实现方法声明的后面是一对大括号,大括号内部是方法体。方法体是对方法的实现,它包括局部变量的声明
31、和所有合法的Java语句。方法的实现是在方法体中通过编写有关的代码,实现方法所需要的功能。例如,在Circle类的area()方法是要计算圆的面积,因此通过有关公式计算得到结果,然后将其返回。方法体中可以包含多条语句。area()方法体还可以写成:double area;area=Math.PI*radius*radius;return area;4.3.1 如何设计方法4.访问方法和修改方法一般地,把能够返回变量值的方法称为访问方法(accessor method),把能够修改变量值的方法称为修改方法(mutator method)。访问方法名一般为getXxx(),因此,访问方法也称get
32、ter方法。修改方法名一般为setXxx(),因此,修改方法也称setter方法。访问方法的返回值一般与原来的变量值类型相同,而修改方法的返回值为void。例如,Circle类中定义的两个方法:public void setRadius(double r)public double getRadius()就分别是修改方法和访问方法。这种设计也是Java Beans规范所要求的。4.3.1 如何设计方法5.方法签名在一个类中可定义多个方法,我们通过方法签名来区分这些方法。方法签名(signature)是指方法名、参数个数、参数类型和参数顺序的组合。注意,方法签名的定义不包括方法的返回值。方法签名
33、将用在方法重载、方法覆盖和构造方法中4.3.2 方法的调用一般来说,要调用类的实例方法应先创建一个对象,然后通过对象引用调用,例如:Circle cc=new Circle();cc.setRadius(10);4.3.2 方法的调用如果要调用类的静态方法,通常使用类名调用,例如:double rand=Math.random();/返回一个随机浮点数在调用没有参数的方法时,只使用圆括号即可,对于有参数的方法需要提供实际参数。方法调用主要使用在三种场合:用用对对象引用象引用调调用用类类的的实实例方法。例方法。类类中的方法中的方法调调用本用本类类中的其他方法。中的其他方法。用用类类名直接名直接调
34、调用用staticstatic方法。方法。4.3.3 方法重载Java语言提供了方法重载的机制,它允许在一个类中定义多个同名的方法,这称为方法重载(method overloading)。实现方法重载,要求同名的方法要么参数个数不同,要么参数类型不同,仅返回值不同不能区分重载的方法。方法重载就是在类中允许定义签名不同的方法。在类中定义了重载方法后,对重载方法的调用与一般方法的调用相同,下面的程序在OverloadDemo类中定义了4个重载的show()方法。4.3.3 方法重载程序4.3 OverloadDemo.java 程序运行结果为:No parameters.a=10a=50,b=60
35、d=100.04.3方法设计在调用重载的方法时还可能发生自动类型转换。假设没有定义带一个int参数的show()方法,od.show(10);语句将调用带double参数的show()方法。4.3.4 构造方法构造方法也叫构造器(constructor),是类的一种特殊方法。Java中的每个类都有构造方法,它的作用是在创建对象时初始化对象的状态。构造方法也有名称、参数和方法体。构造方法与普通方法的区别是:构造方法的名称必构造方法的名称必须须与与类类名相同。名相同。构造方法不能有返回构造方法不能有返回值值,也不能返回,也不能返回voidvoid。构造方法必构造方法必须须在在创创建建对对象象时时用
36、用newnew运算符运算符调调用。用。4.3.4 构造方法构造方法定义的格式为:public|protected|private ClassName(paramList)/方法体这里,public|protected|private为构造方法的访问修饰符,它用来决定哪些类可以使用该构造方法创建对象。这些访问修饰符与一般方法的访问修饰符的含义相同。ClassName为构造方法名,它必须与类名相同。paramList为参数列表,构造方法可以带有参数。4.3.4 构造方法1.默认构造方法默认构造方法(default constructor)是不带参数的构造方法。在定义一个类时,若没有定义构造方法,J
37、ava编译器自动提供一个默认构造方法。例如,对于Circle类,编译器就提供了下面的默认的构造方法:public Circle()在Circle类没有定义构造方法,但使用new Circle()创建了Circle类的对象,这实际是调用了类的默认构造方法。4.3.4 构造方法构造方法主要作用是初始化类的成员变量。对类的成员变量,若声明时没有明确赋初值,则当使用默认构造方法初始化对象时,新建对象的成员变量值都被赋予默认值。使用编译器提供的默认构造方法为成员变量初始化时,对于不同类型的成员变量,其默认值不同。整型数据的默认值是0、浮点型数据默认值是0.0、字符型数据默认值是u0000、布尔型数据默认
38、值是false、引用类型数据默认值是null。4.3.4 构造方法2.带参数构造方法如果希望在创建一个对象时就将其成员变量设置为某个值,而不是采用默认值。这时可以定义带参数构造方法。例如,在创建一个Circle对象时就将圆的半径初始化为给定的值,则可以定义如下带double型参数的构造方法。public Circle(double r)radius=r;然后,在创建Circle对象时可以指定圆的半径,如可用下面代码创建一个半径为10的圆:Circle cc=new Circle(10);4.3.4 构造方法注意,一旦为类定义了带参数的构造方法,编译器就不再提供默认的构造方法了。创建对象时,编译
39、器就会调用我们提供的构造方法。假设只定义了上面的构造方法,再使用下面语句创建对象Circle cc=new Circle();编译器就会给出如下错误提示:The constructor Circle()is undefined含义是没有定义无参构造方法。如果还希望使用默认构造方法创建对象,也可以自己定义默认构造方法,例如:public Circle()radius=0.0;4.3.4 构造方法3.构造方法的重载构造方法也可以重载。如对Circle类就可以定义一个默认构造方法和带一个参数的构造方法。public Circle()radius=0.0;public Circle(double d)
40、radius=d;通过重载构造方法,就可以有多种方式创建对象。由于有了这些重载的构造方法,在创建Circle对象时就可以根据需要选择不同的构造方法。4.3.4 构造方法4.this关键字的使用this关键字表示对象本身。在一个方法的方法体或参数中,也可能声明与成员变量同名的局部变量,此时的局部变量会隐藏成员变量。要使用成员变量就需要在前面加上this关键字,请看下面的程序。程序4.4 ABTest.java 4.3.4 构造方法在AB类的init()方法中,声明了一个与成员变量同名的局部变量b,并为其赋值5,因此在输出语句中,输出b的值为5。此处若需要使用成员变量b,就应该使用this关键字,
41、如下所示:System.out.println(a=+this.a+b=+this.b);同样在定义方法时,方法参数名也可以与成员变量同名。这时在方法体中要引用成员变量也必须加上this。例如,在Circle类中可以像下面这样定义设置圆半径的方法:4.3.4 构造方法public void setRadius(double radius)this.radius=radius;这里,参数名与成员变量同名,因此,在方法体中通过this.radius使用成员变量radius,而没有带this的变量radius是方法的参数。在构造方法中也可以使用this,例如:public Circle(double
42、 radius)this.radius=radius;4.3.4 构造方法this关键字的另一个用途是在一个构造方法中调用该类的另一个构造方法。例如,假设在Circle类定义了一个构造方法Circle(double radius),现在又要定义一个无参数的构造方法,这时可以在下面的构造方法中调用该构造方法,如下所示:public Circle()this(1.0);4.3.4 构造方法注意:如果在构造方法中调用另一个构造方法,则该语句必须是第一条语句。综上所述,this关键字主要使用在下面3种情况。解决局部解决局部变变量与成量与成员变员变量同名的量同名的问题问题。解决方法参数与成解决方法参数与
43、成员变员变量同名的量同名的问题问题。用来用来调调用用该类该类的另一个构造方法。的另一个构造方法。Java语言规定,this只能用在非static方法(实例方法和构造方法)中,不能用在static方法中。实际上,在对象调用一个非static方法时,向方法传递了一个引用,这个引用就是对象本身,在方法体中用this表示。4.3.5 方法参数的传递很多情况下,调用方法需要向方法传递参数,那么参数是如何传递的呢?在Java语言中,方法的参数传递是按值传递,即在调用方法时将实际参数的值的一个拷贝传递给方法中的形式参数,方法调用结束后实际参数的值并不改变。形式参数是局部变量,其作用域只在方法内部,离开方法后
44、自动释放。尽管参数传递是按值传递的,但对于基本数据类型的参数和引用数据类型的参数的传递还是不同的。对于基本数据类型的参数,是将实际参数值的一个拷贝传递给方法,方法调用结束后,对原来的值没有影响。4.3.5 方法参数的传递当参数是引用类型时,实际传递的是引用值,因此在方法的内部有可能改变原来的对象。下面程序说明了这两种类型的参数传递。程序4.5 PassByValue.java 程序的运行结果为:y=200 x=100 c的半径=10.0 c的半径=100.04.3.5 方法参数的传递从程序运行结果可以看到,当参数为基本数据类型时,若在方法内修改了参数的值,在方法返回时,原来的值不变。当参数为引
45、用类型时,传递的是引用,方法返回时引用没有改变,但对象可能已经改变了。4.4 static 修饰符4.4.1 实例变量和静态变量4.4.2 实例方法和静态方法4.4.3 static修饰符的一个应用4.4.4 方法的递归调用4.4 static 修饰符如果成员变量用static修饰,则该变量称为静态变量或类变量(class variable),否则称为实例变量(instance variable)。如果成员方法用static修饰,则该方法称为静态方法或类方法(class method),否则称为实例方法(instance method)。4.4.1 实例变量和静态变量实例变量和静态变量的区别是
46、:在创建类的对象时,Java运行时系统为每个对象的实例变量分配一块内存,然后可以通过该对象来访问该实例变量。不同对象的实例变量占用不同的存储空间,因此它们是不同的。4.4.1 实例变量和静态变量而对于静态变量,Java运行时系统在类装载时为这个类的每个静态变量分配一块内存,以后再生成该类的对象时,这些对象将共享同名的静态变量,每个对象对静态变量的改变都会影响到其他对象。下面的类定义了一个静态变量x。程序4.6 Counter.javapublic class Counterint y;/实例变量static int x=0;/静态变量public Counter()x+;4.4.1 实例变量和
47、静态变量这里成员变量x是静态变量。这意味着在任何时刻不论有多少个Counter类的对象都只有一个x。可能有一个、多个甚至没有Counter类的实例,总是只有一个x。静态变量x在类Counter被装载时就分配了空间。在每次调用构造方法时静态变量x都被增1,所以可以知道创建了多少个Counter类的实例。可以通过下面两种方法访问静态变量:通通过类过类的任何的任何实实例例访问访问。通通过类过类名名访问访问。4.4.1 实例变量和静态变量可以通过实例名访问静态变量,但这种方法可能产生混乱的代码。下面代码说明了原因:Counter c1=new Counter();Counter c2=new Coun
48、ter();c1.x=100;c2.x=200;System.out.println(c1.x);/输出结果为200如果忽略了x是静态变量,可能认为c1.x的结果为100,实际上它的值为200,因为c1.x和c2.x引用的是同一个变量。4.4.1 实例变量和静态变量最好的方法是通过类名访问静态变量,下面的代码与上面的代码效果相同:Counter c1=new Counter();Counter c2=new Counter();Counter.x=100;Counter.x=200;System.out.println(Counter.x);4.4.1 实例变量和静态变量通常,static与f
49、inal一起使用来定义类常量。例如,Java类库中的Math类中就定义了两个类常量:/自然对数的底 /圆周率4.4.1 实例变量和静态变量可以通过类名直接使用这些常量。例如,下面语句可输出半径为10的圆的面积:System.out.println(面积=+Math.PI*10*10);Java类库中的System类中也定义了三个类变量,分别是in、out和err,它们分别表示标准输入设备(通常是键盘)、标准输出设备(通常是显示器)和标准错误输出设备。我们使用的System.out就是用类名访问的类常量。因为out是PrintSteam类型的常量,可以调用PrintSteam类的方法printl
50、n()来输出信息。4.4.2 实例方法和静态方法实例方法和静态方法的区别是:实例方法可以对当前的实例变量进行操作,也可以对静态变量进行操作,但静态方法只能访问静态变量。实例方法必须由对象来调用,而静态方法除了可以由对象调用外,还可以由类名直接调用。另外在静态方法中不能使用this和super关键字。请看下面的程序。4.4.2 实例方法和静态方法程序4.7 SomeClass.javapublic class SomeClassstatic int i=48;int j=5;public static void display()i=i+100;System.out.println(i=+i);