第4章 类与对象

主要内容
 类
 构造方法与对象的创建
 类与程序的基本结构
重点与难点:
 重点:Java类的语法规则、构造方法与对象的创建。
 难点:对象的创建过程,对象引用与实体的关系、理解类的封装。
4.1.1 面向机器语言
4.1.2 面向过程语言
4.1.3 面向对象语言
面向对象编程主要体现下列三个特性:封装性 ;继承;多态
§4.2 类
Java语言是面向对象语言,它的源程序是由若干个类组成,源文件是扩展名为.java的文本文件。
类是Java语言中最重要的“数据类型”,类声明的变量被称作对象(见后面的4.3节),即类是用来创建对象的模板。
类的实现包括两部分:类声明和类体。基本格式为:
class 类名 {
类体的内容
}
其中:class是关键字,用来定义类。“class 类名”是类的声明部分,类名必须是合法的Java标识符。两个大括号以及之间的内容是类体。
§4.2.1 类声明
写类的目的是为了描述一类事物共有的属性和功能。
类声明 :class 类名
以下是两个类声明的例子。
class People {

}
class 植物 {

}
如:class People”和“class 植物”称作类声明;
“People”和“动物”分别是类名。
给类命名时,遵守下列编程风格(这不是语法要求,但应当遵守):
1.如果类名使用拉丁字母,那么名字的首字母使用大写字母。
2.类名最好容易识别、见名知意。当类名由几个“单词”复合而成时,每个单词的首字母使用大写。
§4.2.2 类体
类声明之后的一对大括号“{”,“}”以及它们之间的内容称作类体,大括号之间的内容称作类体的内容。
类体的内容由两部分构:一部分是变量的声明,用来刻画属性;另一部分是方法的定义,用来刻画行为功能。
§4.2.3 成员变量
类体的内容一部分是变量的声明,另一部分是方法的定义。
成员变量的类型
类体中变量定义部分所定义的变量被称为类的成员变量。
成员变量的有效范围
成员变量在整个类内都有效,其有效性与它在类体中书写的先后位置无关。
定义梯形类如下:
class Lader
{ float above,area;
float computerArea()
{ area=(above+bottom)height/2;
return area;
}
float bottom;
void setHeight(float h)
{ height=h;
}
float height;
}
编程风格
§4.2.4 方法
方法的定义包括两部分:方法声明和方法体.一般格式为:
方法声明部分 {
方法体的内容
}
1.方法声明部分(方法头)
方法头由方法的类型、名称和名称之后的一对小括号以及其中的参数列表所构成。例如:
int speak(){ //无参数的方法头
return 23;
}
int add(int x,int y,int z) //有参数的方法头
{ return x+y+z;
}
注意:方法返回的数据类型可以是Java中的任何数据类型之一,当一个方法不需要返回数据时,返回类型必须是void。
2.方法体
方法声明之后的一对大括号“{” ,“}”以及之间的内容称为方法的方法体.
方法体的内容包括局部变量的声明和Java语句。如:
int getSum(int n) { //参数变量n是局部变量
int sum=0; // 声明局部变量sum
for(int i=1;i<=n;i++) { // for循环语句
sum=sum+i;
}
return sum; // return 语句
}
和类的成员变量不同的是,局部变量只在方法内有效,而且与其声明的位置有关。
方法的参数在整个方法内有效,方法内的局部变量从声明它的位置之后开始有效。如果局部变量的声明是在一个复合语句中,那么该局部变量的有效范围是该复合语句。如果局部变量的声明是在一个循环语句中,那么该局部变量的有效范围是该循环语句。请看下例:
例题
public class A {
void f() {
int m = 10,sum = 0; //成员变量,在整个类中有效
if(m>9) {
int z = 10; //z仅仅在该复合语句中有效
z = 2
m+z;
}
for(int i=0;i<m;i++) {
sum = sum+i; //i仅仅在该循环语句中有效
}
m = sum; //合法,因为m和sum有效
z = i+sum; //非法,因为i和z已无效
}
}
3.区分成员变量和局部变量

§4.2.5 需要注意的问题
类体的内容由两部分构成:一部分是变量的声明,另一部分是方法的定义。
§4.2.6 类的UML图
UML(Unified Modeling Language Diagram)
是被用于描述一个系统的静态结构。一个UML中通常包含有类(Class)的UML图,接口(Interface)的UML图以及泛化关系(Generalization)的UML图、关联关系(Association)的UML图、依赖关系(Dependency)的UML图和实现关系(Realization)的UML图。
在类的UML图中,使用一个长方形描述一个类的主要构成,将长方形垂直地分为三层。
第1层是名字层;
第2层是变量层,也称属性层;
第3层是方法层,也称操作层。

4.3 构造方法与对象的创建
§4.3.1 构造方法
构造方法是一种特殊方法,它的名字必须与它所在的类的名字完全相同,而且没有类型。
1.默认构造方法与自定义构造方法
2.构造方法没有类型
§4.3.2 创建对象
创建一个对象包括对象的声明和为对象分配变量两个步骤。
1.对象的声明
一般格式为: 类的名字 对象名字;
如: XiyoujiRenwu zhubajie;
2.为声明的对象分配变量
使用new运算符和类的构造方法为声明的对象分配变量,并返回一个引用值给对象名称。即创建对象。如果类中没有构造方法,系统会调用默认的构造方法,默认的构造方法是无参数的,且方法体中没有语句。
例如: zhubajie = new XiyoujiRenwu();
例子1
Example4_1.java

class XiyoujiRenwu {
float height,weight;
String head, ear;
void speak(String s) {
System.out.println(s);
}
}
public class Example4_1 {
public static void main(String args[]) {
XiyoujiRenwu zhubajie; //声明对象
zhubajie = new XiyoujiRenwu();
}
}
例子2
Example4_2.java

class Point {
int x,y;
Point(int a,int b) {
x = a;
y = b;
}
}
public class Example4_2 {
public static void main(String args[]) {
Point p1,p2; //声明对象p1和p2
p1 = new Point(10,10); //为对象p1分配变量(使用new和类中的构造方法)
p2 = new Point(23,35); //为对象p2分配变量(使用new和类中的构造方法)
}
}
当用类创建一个对象时,类中的成员变量被分配内存空间,这些内存空间称作该对象的实体或对象的变量,而对象中存放着引用值。
3.对象的内存模型
(1)声明对象时的内存模型
图4.3
(2)对象分配变量后的内存模型
图4.4
(3)创建多个不同的对象
图4.5
一个类通过使用new运算符可以创建多个不同的对象。例如创建两个对象:zhubajie、sunwukong
如:zhubajie = new XiyoujiRenwu();
sunwukong = new XiyoujiRenwu
§4.3.3 使用对象
对象创建成功后,可以操作类中的变量和方法:
1.对象操作自己的变量(体现对象的属性)
通过使用运算符“.” 对象操作自己的变量(对象的属性)。
2.对象调用类中的方法(体现对象的行为)
对象创建之后,可以使用点运算符“.”调用创建它的类中的方法,从而产生一定的行为(功能)。
例子3中,主类的main方法中使用XiyoujiRenwu创建两个对象:zhubajie、sunwukong,运行效果如图4.6。
Example4_3.java
class XiyoujiRenwu {
float height,weight;
String head, ear;
void speak(String s) {
head = “歪着头”;
System.out.println(s);
}
}
public class Example4_3 {
public static void main(String args[]) {
XiyoujiRenwu zhubajie,sunwukong; //声明对象
zhubajie = new XiyoujiRenwu(); //为对象分配变量
sunwukong = new XiyoujiRenwu();
zhubajie.height = 1.80f; //对象给自己的变量赋值
zhubajie.head = “大头”;
zhubajie.ear = “一双大耳朵”;
sunwukong.height = 1.62f; //对象给自己的变量赋值
sunwukong.weight = 1000f;
sunwukong.head = “秀发飘飘”;
System.out.println(“zhubajie的身高:”+zhubajie.height);
System.out.println(“zhubajie的头:”+zhubajie.head);
System.out.println(“sunwukong的重量:”+sunwukong.weight);
System.out.println(“sunwukong的头:”+sunwukong.head);
zhubajie.speak(“俺老猪我想娶媳妇”); //对象调用方法
System.out.println(“zhubajie现在的头:”+zhubajie.head);
sunwukong.speak(“老孙我重1000斤,我想骗八戒背我”);//对象调用方法
System.out.println(“sunwukong现在的头:”+sunwukong.head);
}
}

§4.3.4 对象的引用和实体
一个类创建的两个对象,如果具有相同的引用,那么就具有完全相同的实体。
假如在程序中使用了如下的赋值语句:
p1 = p2;
即把p2中的引用赋给了p1,因此p1和p2本质上是一样的.
一个类创建的两个对象,如果具有相同的引用,那么就具有完全相同的实体(变量)。内存模型由图4.9变成图4.10所示。

本次课总结
类是组成Java源文件的基本元素。
类体可以有两种重要的成员:成员变量和方法。
类是面向对象语言中最重要的一种数据类型,那么就可以用它来声明变量。在面向对象语言中,用类声明的变量被称作对象。对象创建成功后,可以操作类中的变量和方法。

§4.4 类与程序的基本结构
一个Java应用程序(也称为一个工程)是由若干个类所构成,这些类可以在一个源文件中,也可以分布在若干个源文件中,如图4.12所示 。
例子5 中一共有三个Java源文件(Example4_5.java Rect.java Lader.java ,需要打开记事本三次,分别编辑、保存这三个Java源文件),其中Example4_5.java是含有主类的Java源文件。
Java应用程序从主类的main方法开始执行。在编写一个Java应用程序时,可以编写若干个Java源文件,每个源文件编译后产生一个类的字节码文件。
Rect.java

public class Rect {
double width; //矩形的宽
double height; //矩形的高
double getArea() {
double area = width*height;
return area;
}
}

Lader.java

public class Lader {
double above; //梯形的上底
double bottom; //梯形的下底
double height; //梯形的高
double getArea() {
return (above+bottom)*height/2;
}
}

Example4_5.java

public class Example4_5 {
public static void main(String args[]) {
Rect ractangle = new Rect();
ractangle.width = 109.87;
ractangle.height = 25.18;
double area=ractangle.getArea();
System.out.println(“矩形的面积:”+area);
Lader lader = new Lader();
lader.above = 10.798;
lader.bottom = 156.65;
lader.height = 18.12;
area = lader.getArea();
System.out.println(“梯形的面积:”+area);
}
}
§4.5 参数传值
 方法中最重要的部分之一就是方法的参数,参数属于局部变量,当对象调用方法时,参数被分配内存空间,并要求调用者向参数传递值,即方法被调用时,参数变量必须有具体的值。
§4.5.1 传值机制
 在Java中,方法的所有参数都是“传值”的,也就是说,方法中参数变量的值是调用者指定的值的拷贝。
1)对于基本数据类型的参数,向该参数“传值”,传递的是值的拷贝.
例如,如果向方法的int型参数x传递一个int值,那么参数x得到的值是传递的值的拷贝。
2)对于参数是引用类型时,“传值”传递的是变量的引用而不是变量所引用的实体。Java的引用型数据包括对象、数组和接口。
§4.5.2 基本数据类型参数的传值
 对于基本数据类型的参数,传递的是值的拷贝。同时向该参数传递的值的级别不可以高于该参数的级别 。

例子6
Example4_6.java

class Computer{
int add(int x,int y){
return x+y;
}
}
public class Example4_6 {
public static void main(String args[]){
Computer com = new Computer();
int m = 100;
int n = 200;
int result = com.add(m,n); //将m,n的值“传值”给参数x,y
System.out.println(result);
result = com.add(120+m,n10+8);
//将表达式120+m和n
10+8的值“传值”给参数x,y
System.out.println(result);
}
}

§4.5.3 引用类型参数的传值
 当参数是引用类型时,“传值”传递的是变量中存放的“引用”,而不是变量所引用的实体。如图4.13所示
例题
 例子7模拟收音机使用电池。例子7中使用的主要类如下。
Radio类负责创建一个“收音机”对象(Radio类在Radio.java中).
Battery类负责创建“电池”对象(Battery类在Battery.java中).
Radio类创建的“收音机”对象调用openRadio(Battery battery)方法时,需要将一个Battery类创 建“电池”对象传递给该方法的参数battery,即模拟收音机使用电池。
在主类(Example4_7.java )中将Battery类创建“电池”对象:nanfu,传递给openRadio(Battery battery)方法的参数battery,该方法消耗了battery的储电量(打开收音机会消耗电池的储电量),那么nanfu的储电量就发生了同样的变化
 收音机使用电池的示意图以及程序的运行效果如图4.14(a)和4.14(b)。
例子7
Battery.java

public class Battery {
int electricityAmount;
Battery(int amount){
electricityAmount = amount;
}
}

Radio.java

public class Radio {
void openRadio(Battery battery){
battery.electricityAmount = battery.electricityAmount - 10; //消耗了电量
}
}

Example4_7.java

public class Example4_7 {
public static void main(String args[]) {
Battery nanfu = new Battery(100); //创建电池对象
System.out.println(“南孚电池的储电量是:”+nanfu.electricityAmount);
Radio radio = new Radio(); //创建收音机对象
System.out.println(“收音机开始使用南孚电池”);
radio.openRadio(nanfu); //打开收音机
System.out.println(“目前南孚电池的储电量是:”+nanfu.electricityAmount);
}
}

4.5.4 可变参数
可变参数(The variable arguments)数是指在声明方法时不给出参数列表中从某项开始直至最后一项参数的名字和个数,但这些参数的类型必须相同。可变参数使用“…”表示若干个参数,这些参数的类型必须相同,并且最后一个参数必须是方法的参数列表中的最后一个参数。

§4.6 对象的组合
一个类可以把对象作为自己的成员变量,如果用这样的类创建对象,那么该对象中就会有其它对象,也就是说该对象将其他对象作为自己的组成部分,或者说该对象是由几个对象组合而成。
§4.6.1 组合与复用
如果一个对象a组合了对象b,那么对象a就可以委托对象b调用其方法,即对象a以组合的方式复用对象b的方法。
例题
 例子8中(运行效果如图4.15)模拟圆锥用圆作为底,涉及的类如下。
Circle类负责创建圆对象。
Circular类负责创建圆锥对象, 该圆锥对象可以调用方法
Circle.java

public class Circle {
double radius,area;
void setRadius(double r) {
radius=r;
}
double getRadius() {
return radius;
}
double getArea(){
area=3.14radiusradius;
return area;
}
}

Circular.java

public class Circular {
Circle bottom;
double height;
void setBottom(Circle c) { //设置圆锥的底是一个Circle对象
bottom = c;
}
void setHeight(double h) {
height = h;
}
double getVolme() {
if(bottom == null)
return -1;
else
return bottom.getArea()*height/3.0;
}
double getBottomRadius() {
return bottom.getRadius();
}
public void setBottomRadius(double r){
bottom.setRadius®;
}
}

Example4_8.java

public class Example4_8 {
public static void main(String args[]) {
Circle circle = new Circle(); //【代码1】
circle.setRadius(10); //【代码2】
Circular circular = new Circular(); //【代码3】
System.out.println(“circle的引用:”+circle);
System.out.println(“圆锥的bottom的引用:”+circular.bottom);
circular.setHeight(5);
circular.setBottom(circle); //【代码4】
System.out.println(“circle的引用:”+circle);
System.out.println(“圆锥的bottom的引用:”+circular.bottom);
System.out.println(“圆锥的体积:”+circular.getVolme());
System.out.println(“修改circle的半径,bottom的半径同样变化”);
circle.setRadius(20); //【代码5】
System.out.println(“bottom的半径:”+circular.getBottomRadius());
System.out.println(“重新创建circle,cirlce的引用将发生变化”);
circle = new Circle(); //重新创建circle 【代码6】
System.out.println(“circle的引用:”+circle);
System.out.println(“但是不影响circular的bottom的引用”);
System.out.println(“圆锥的bottom的引用:”+circular.bottom);
}
}

§4.6.2 关联关系和依赖关系的UML图
简单介绍关联关系和依赖关系。
本次课总结:当参数是引用类型时,“传值”传递的是变量中存放的“引用”,而不是变量所引用的实体。
§4.7 实例成员与类成员
4.7.1 实例变量和类变量的声明
在声明成员变量时,用关键字static给予修饰的称作类变量,否则称作实例变量(类变量也称为static变量,静态变量)。
4.7.2 实例变量和类变量的区别
 不同对象的实例变量互不相同
 所有对象共享类变量
 通过类名直接访问类变量
 例子10中的Lader.java中的Lader类创建的梯形对象共享一个下底。程序运行效果如图4.23。
例子10
Lader.java

public class Lader {
double 上底,高; //实例变量
static double 下底; //类变量
void 设置上底(double a) {
上底 = a;
}
void 设置下底(double b) {
下底 = b;
}
double 获取上底() {
return 上底;
}
double 获取下底() {
return 下底;
}
}

Example4_10.java

public class Example4_10 {
public static void main(String args[]) {
Lader.下底 = 100; //Lader的字节码被加载到内存,通过类名操作类变量
Lader laderOne = new Lader();
Lader laderTwo = new Lader();
laderOne.设置上底(28);
laderTwo.设置上底(66);
System.out.println(“laderOne的上底:”+laderOne.获取上底());
System.out.println(“laderOne的下底:”+laderOne.获取下底());
System.out.println(“laderTwo的上底:”+laderTwo.获取上底());
System.out.println(“laderTwo的下底:”+laderTwo.获取下底());
}
}

4.7.3 实例方法和类方法的定义
类中的方法也可分为实例方法和类方法。方法声明时,方法类型前面不加关键字static修饰的是实例方法、加static关键字修饰的是类方法(静态方法)。
4.7.4 实例方法和类方法的区别
1)对象调用实例方法
当对象调用实例方法时,该方法中出现的实例变量就是分配给该对象的实例变量;该方法中出现的类变量也是分配给该对象的变量,只不过这个变量和所有的其他对象共享而已。
2)类名调用类方法
从而类方法不仅可以被类创建的任何对象调用执行,也可以直接通过类名调用。和实例方法不同的是,类方法不可以操作实例变量,这是因为在类创建对象之前,实例成员变量还没有分配内存。
§4.8 方法重载与多态
方法重载的意思是:一个类中可以有多个方法具有相同的名字,但这些方法的参数必须不同,即或者是参数的个数不同,或者是参数的类型不同。
4.8.1 方法重载的语法规则
例子12
class People {
float hello(int a,int b) {
return a+b;
}
float hello(long a,int b) {
return a-b;
}
double hello(double a,int b) {
return a*b;
}
}
public class Example4_12 {
public static void main(String args[]) {
People tom = new People();
System.out.println(tom.hello(10,20));
System.out.println(tom.hello(10L,20));
System.out.println(tom.hello(10.0,20));
}
}
例子13
Circle.java

public class Circle {
double radius,area;
void setRadius(double r) {
radius = r;
}
double getArea(){
area = 3.14radiusradius;
return area;
}
}

Tixing.java

public class Tixing {
double above,bottom,height;
Tixing(double a,double b,double h) {
above = a;
bottom = b;
height = h;
}
double getArea() {
return (above+bottom)*height/2;
}
}

Student.java

public class Student {
double computerArea(Circle c) { //是重载方法
double area = c.getArea();
return area;
}
double computerArea(Tixing t) { //是重载方法
double area = t.getArea();
return area;
}
}

Example4_13.java

public class Example4_13 {
public static void main(String args[]) {
Circle circle = new Circle();
circle.setRadius(196.87);
Tixing lader = new Tixing(3,21,9);
Student zhang = new Student();
System.out.println(“zhang计算圆的面积:”);
double result = zhang.computerArea(circle);
System.out.println(result);
System.out.println(“zhang计算梯形的面积:”);
result = zhang.computerArea(lader);
System.out.println(result);
}
}
4.8.2 避免重载出现歧义
§4.9 this关键字
 this是Java的一个关键字,表示某个对象。this可以出现在实例方法和构造方法中,但不可以出现在类方法中。

4.9.1 在构造方法中使用this
this关键字出现在类的构造方法中时,代表使用该构造方法所创建的对象.

例子14
People.java

public class People{
int leg,hand;
String name;
People(String s){
name = s;
this.init(); //可以省略this,即将this.init();写成init();
}
void init(){
leg = 2;
hand = 2;
System.out.println(name+“有”+hand+“只手”+leg+“条腿”);
}
public static void main(String args[]){
People boshi = new People(“布什”); //创建boshi时,构造方法中的this就是 //对象boshi
}
}

4.9.2 在实例方法中使用this
当this关键字出现实例方法中时,this就代表正在调用该方法的当前对象。

本次课总结
除构造方法外,其它方法分为实例方法和类方法。
实例方法即可以操作实例变量也可以操作类变量,当对象调用实例方法时,方法中的成员变量就是指分配给该对象的成员变量,其中的实例变量和其它对象的不相同,即占有不同的内存空间;类变量和其它对象的相同,即占有相的内存空间。
类方法只能操作类变量,当对象调用类方法时,方法中的成员变量一定都是类变量,也就是说该对象和所有的对象共享类变量。

§4.10 包
包是Java语言中有效地管理类的一个机制。
包名的目的是有效的区分名字相同的类。不同Java源文件中两个类名字相同时,它们可以通过隶属不同的包来相互区分。
§4.10.1包语句
通过关键字package声明包语句。
package语句作为Java源文件的第一条语句, 为该源文件中声明的类指定包名。
package语句的一般格式为:
package 包名;
§4.10.2 有包名的类的存储目录
程序如果使用了包语句,例如:
package tom.jiafei;
那么存储文件的目录结构中必须包含有如下的结构
…\tom\jiafei
如:c:\1000\tom\jiafei
并且要将源文件编译得到的类的字节码文件保存在目录c:\1000\tom\jiafei中(源文件可以任意存放)。
§4.10.3 运行有包名的主类
如果主类的包名是tom.jiafei,那么主类的字节码一定存放在…\tom\jiefei目录中,运行时必须到tom\jiefei的上一层(即tom的父目录)目录中去运行主类。
假设tom\jiefei的上一层目录是1000,那么,必须如下格式来运行:
C:\1000\java tom.jiafei.主类名
例子15
Student.java

package tom.jiafei;
public class Student{
int number;
Student(int n){
number = n;
}
void speak(){
System.out.println(“Student类的包名是tom.jiafei,我的学号:”+number);
}
}

Example4_15.java

package tom.jiafei;
public class Example4_15 {
public static void main(String args[]){
Student stu = new Student(10201);
stu.speak();
System.out.println(“主类的包名也是tom.jiafei”);
}
}
§4.11 import 语句
一个类可能需要另一个类声明的对象作为自己的成员或方法中的局部变量,如果这两个类在同一个包中,当然没有问题。
§4.11.1 引入类库中的类
如果一个类想要使用的那个类和它不在一个包中,要使用import语句完成使命。如果用户需要类库中的类就可以使用import语句。
例如:
Import java.util.Date; 表示引入java.util包中的Date类 .
例如:
import java.util.*;表示引入java.util包中所有的类
例子16
Example4_16.java

import java.util.Date;
public class Example4_16 {
public static void main(String args[]) {
Date date = new Date();
System.out.println(“本地机器的时间:”);
System.out.println(date.toString());
}
}
§4.11.2 引入自定义包中的类
用户程序也可以使用import语句引入非类库中有包名的类,如:
import tom.jiafei.*;
在用户程序所在目录下建立和包相对应的子目录结构,比如用户程序所在目录是C:\ch4,想使用import语句引入tom.jiafei包中的类,那么根据包名建立如下的目录结构:
C:\ch4\tom\jiafei
例题
例子17
Triangle.java

package sohu.com;
public class Triangle {
double sideA,sideB,sideC;
public double getArea() {
double p = (sideA+sideB+sideC)/2.0;
double area = Math.sqrt(p*(p-sideA)(p-sideB)(p-sideC)) ;
return area;
}
public void setSides(double a,double b,double c) {
sideA = a;
sideB = b;
sideC = c;
}
}
例子18中的Example4_18.java中的主类(无包名)使用import语句引入sohu.com包中的Triangle类,以便创建三角形,并计算三角形的面积。将Example4_18.java保存在C:\ch4目录中(因为ch4下有sohu\com子目录)。程序运行效果如图4.30。

例子18
Example4_18.java

package hello.nihao;
import sohu.com.Triangle;
public class Example4_18 {
public static void main(String args[]) {
Triangle tri = new Triangle();
tri.setSides(30,40,50);
System.out.println(tri.getArea());
}
}
§4.12 访问权限
当用一个类创建了一个对象之后,该对象可以通过“.”运算符操作自己的变量、使用类中的方法,但对象操作自己的变量和使用类中的方法是有一定限制的。
§4.12.1 何谓访问权限
所谓访问权限是指对象是否可以通过“.”运算符操作自己的变量或通过“.”运算符使用类中的方法。
访问限制修饰符有private、protected和public,都是Java的关键字,用来修饰成员变量或方法。
§4.12.2 私有变量和私有方法
用关键字private修饰的成员变量和方法称为私有变量和私有方法。
对于私有成员变量或方法,只有在本类中创建该类的对象时,这个对象才能访问自己的私有成员变量和类中的私有方法。
某个类在另外一个类中创建对象后,如果不希该对象直接访问自己的变量,即通过“.”运算符来操作自己的成员变量,就应当将该成员变量访问权限设置为private。
面向对象编程提倡对象应当调用方法来改变自己的属性,类应当提供操作数据的方法,这些方法可以经过精心的设计,使得对数据的操作更加合理。
例子19(Example4_19.java , Student.java )所示。
例子19
Student.java

public class Student {
private int age;
public void setAge(int age) {
if(age>=7&&age<=28) {
this.age = age;
}
}
public int getAge() {
return age;
}
}

Example4_19.java

public class Example4_19 {
public static void main(String args[]) {
Student zhang = new Student();
Student geng = new Student();
zhang.setAge(23);
System.out.println(“zhang的年龄:”+zhang.getAge());
geng.setAge(25);
//zhang.age = 23;或geng.age = 25;都是非法的,因为zhang和geng已经不在 //Student类中
System.out.println(“geng的年龄:”+geng.getAge());
}
}

§4.12.3 共有变量和共有方法
用public修饰的成员变量和方法被称为共有变量和共有方法 。
我们在任何一个类中用类Tom 创建了一个对象后,该对象能访问自己的public变量和类中的public方法(也可以通过类名来操作成员变量、方法) 。
§4.12.4 友好变量和友好方法
当在另外一个类中用类Tom 创建了一个对象后,如果这个类与Tom类在同一个包中,那么该对象能访问自己的友好变量和友好方法。
在任何一个与Tom同一包中的类中,也可以通过Tom类的类名访问Tom类的类友好成员变量和类友好方法。

§4.12.5 受保护的成员变量和方法
用protected修饰的成员变量和方法被称为受保护的成员变量和受保护的方法 。

§4.12.6 public类与友好类
类声明时,如果在关键字class前面加上public关键字,就称这样的类是一个public 类 。
可以在任何另外一个类中,使用public类创建对象。
如果一个类不加public修饰,这样的类被称作友好类。
在另外一个类中使用友好类创建对象时,要保证它们是在同一包中。

本次课总结
方法重载的意思是:一个类中可以有多个方法具有相同的名字,但这些方法的参数必须不同。
包是Java语言有效地管理类的一个机制。
所谓访问权限是指对象是否可以通过“.”运算符操作自己的变量或通过“.”运算符调用类中的方法。Java提供了基本数据类型相关的类,实现了对基本数据类型的封装。

§4.13 基本类型的类封装
Java的基本数据类型包括
byte、int、short、long、float、double、char。
Java提供了基本数据类型相关的类,实现了对基本数据类型的封装。
Byte、Integer、Short、Long、Float、Double和Character类。这些类在java.lang包中。
§4.13.1 Double和Float类
Double类和Float类实现了对double和float基本型数据的类包装。
– Double类的构造方法:Double(double num)
– Float类的构造方法: Float(float num)
Double对象调用doubleValue()方法可以返回该对象中含有的double型数据。
Float对象调用floatValue()方法可以返回该对象中含有的float型数据。

§4.13.2 Byte、Short 、Integer、Long类
上述类的构造方法分别 :
Byte(byte num)
Short(short num)
Integer(int num)
Long(long num)
Byte、Short、Integer和Long对象分别调用byteValue ()、shortValue()、intValue()和longValue ()方法返回该对象含有的基本型数据。
§4.13.3 Character类
Character类实现了对char基本型数据的类包装。
Character类的构造方法:Character(char c)
Character类中的一些常用类方法:
public static boolean isDigit(char ch) ch是数字字符返回true.
public static boolean isLetter(char ch) ch是字母返回 true。
§4.14 对象数组
如果程序需要某个类的若干个对象,比如Student类的10个对象,显然如下声明10个Student对象是不可取的:
Student stu1,stu2, stu3,stu4,stu5,stu6,stu7,stu8, stu9,stu10;
正确的做法是使用对象数组,即数组的元素是对象,例如:
Student [] stu;
stu = new Student[10];
需要注意的是,上述代码仅仅定义了数组stu有10个元素,并且每个元素都是一个Student类型的对象,但这些对象目前都是空对象,因此在使用数组stu中的对象之前,应当创建数组所包含的对象。
例如: stu[0] = new Student();
例子21
class Student{
int number;
}
public class Example4_21 {
public static void main(String args[ ]) {
Student stu[] = new Student[10]; //创建对象数组stu
for(int i=0;i<stu.length;i++) {
stu[i] = new Student(); //创建Student对象stu[i]
stu[i].number = 101+i;
}
for(int i=0;i<stu.length;i++) {
System.out.println(stu[i].number);
}
}
}

§4.15 JRE扩展与jar文件
可以使用jar.exe命令把一些类的字节码文件压缩成一个jar文件,然后将这个jar文件存放到Java运行环境的扩展中,即将该jar文件存放在JDK安装目录的jre\lib\ext文件夹中。这样,Java应用程序就可以使用这个jar文件中的类来创建对象了。
将C:\1000\moon\star目录中的TestOne.class 和TestTwo.class(二者包名是moon.star)压缩成一个jar文件:Jerry.jar的步骤:
§4.16 文档生成器
使用JDK提供的javadoc.exe可以制作源文件类结构的html格式文档。
D:\test> javadoc Example.java
javadoc –d F:\gxy\book Example.java
§4.17 应用举例
有理数有两个重要的成员:分子和分母,另外还有重要的四则运算。我们用Rational类实现对有理数的封装。
例子23中的Example4_23.java的主类使用Rational对象计算两个分数的四则运算,并计算了2/1+3/2+5/3…的前10项和
例子22
Rational.java

public class Rational {
int numerator = 1 ; //分子
int denominator = 1; //分母
void setNumerator(int a) { //设置分子
int c=f(Math.abs(a),denominator); //计算最大公约数
numerator = a/c;
denominator = denominator/c;
if(numerator<0&&denominator<0) {
numerator = -numerator;
denominator = -denominator;
}
}
void setDenominator(int b) { //设置分母
int c=f(numerator,Math.abs(b)); //计算最大公约数
numerator = numerator/c;
denominator = b/c;
if(numerator<0&&denominator<0) {
numerator = -numerator;
denominator = -denominator;
}
}
int getNumerator() {
return numerator;
}
int getDenominator() {
return denominator;
}
int f(int a,int b) { //求a和b的最大公约数
if(a==0) return 1;
if(a<b) {
int c = a;
a = b;
b = c;
}
int r=a%b;
while(r!=0) {
a = b;
b = r;
r = a%b;
}
return b;
}
Rational add(Rational r) { //加法运算
int a = r.getNumerator(); //返回有理数r的分子
int b = r.getDenominator(); //返回有理数r的分母
int newNumerator = numeratorb+denominatora; //计算出新分子
int newDenominator = denominatorb; //计算出新分母
Rational result = new Rational();
result.setNumerator(newNumerator);
result.setDenominator(newDenominator);
return result;
}
Rational sub(Rational r) { //减法运算
int a = r.getNumerator();
int b = r.getDenominator();
int newNumerator = numerator
b-denominatora;
int newDenominator = denominator
b;
Rational result = new Rational();
result.setNumerator(newNumerator);
result.setDenominator(newDenominator);
return result;
}
Rational muti(Rational r) { //乘法运算
int a = r.getNumerator();
int b = r.getDenominator();
int newNumerator = numeratora;
int newDenominator = denominator
b;
Rational result = new Rational();
result.setNumerator(newNumerator);
result.setDenominator(newDenominator);
return result;
}
Rational div(Rational r) { //除法运算
int a = r.getNumerator();
int b = r.getDenominator();
int newNumerator = numeratorb;
int newDenominator = denominator
a;
Rational result = new Rational();
result.setNumerator(newNumerator);
result.setDenominator(newDenominator);
return result;
}
}

下面例子23中的Example4_23.java的主类使用Rational对象进行两个分数的四则运算,并计算了2/1+3/2+5/3+…的前10项和。
例子23
Example4_23.java

public class Example4_23 {
public static void main(String args[]) {
Rational r1=new Rational();
r1.setNumerator(1);
r1.setDenominator(5);
Rational r2=new Rational();
r2.setNumerator(3);
r2.setDenominator(2);
Rational result=r1.add(r2);
int a=result.getNumerator();
int b=result.getDenominator();
System.out.println(“1/5+3/2 = “+a+”/”+b);
result=r1.sub(r2);
a=result.getNumerator();
b=result.getDenominator();
System.out.println(“1/5-3/2 = “+a+”/”+b);
result=r1.muti(r2);
a=result.getNumerator();
b=result.getDenominator();
System.out.println(“1/5×3/2 = “+a+”/”+b);
result=r1.div(r2);
a=result.getNumerator();
b=result.getDenominator();
System.out.println(“1/5÷3/2 = “+a+”/”+b);
int n=10,k=1;
System.out.println(“计算2/1+3/2+5/3+8/5+13/8+…的前”+n+“项和.”);
Rational sum=new Rational();
sum.setNumerator(0);
Rational item=new Rational();
item.setNumerator(2);
item.setDenominator(1);
while(k<=n) {
sum=sum.add(item);
k++;
int fenzi=item.getNumerator();
int fenmu=item.getDenominator();
item.setNumerator(fenzi+fenmu);
item.setDenominator(fenzi);
}
a=sum.getNumerator();
b=sum.getDenominator();
System.out.println(“用分数表示:”);
System.out.println(a+"/"+b);
double doubleResult=(a*1.0)/b;
System.out.println(“用小数表示:”);
System.out.println(doubleResult);
}
}

上述程序的运行结果如下。

1/5+3/2 = 17/10
1/5-3/2 = -13/10
1/5×3/2 = 3/10
1/5÷3/2 = 2/15
计算2/1+3/2+5/3+8/5+13/8+…的前10项和
用分数表示:
998361233/60580520
用小数表示:
16.479905306194137

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值