目录
第 6 章 类和对象
类可以看作是对象的载体,它定义了对象所具有的功能。
知识架构及重难点:
6.1 面向对象概述
面向对象思想是人类最自然的一种思考方式,它将所有预处理的问题抽象为对象,通过了解这些对象具有哪些相应的属性以及展示这些对象的行为,以解决这些对象面临的一些实际问题。在程序开发中引入面向对象设计的概念,其实质上就是对现实现界中的对象进行建模操作。
6.1.1 对象
对象:对象是事物存在的实体。
通常会将对象划分为两个部分,即静态部分与动态部分。
静态部分:不能动的部分,这个部分称为“属性”,任何对象都会具备其自身属性,如一个人,其属性有身高、年龄、性别等。
动态部分:对象可执行的动作,这部分称为“行为”,如人的喜怒哀乐、说话、行走等。
6.1.2 类
不能将一个事物描述成一类事物,如一只鸟不能称为鸟类。
类:封装对象的属性和行为的载体,是同一类事物的统称,具有相同特性和行为的一类事物实体被称为类。
如果将现实世界中的一个事物抽象成对象,类就是这类对象的统称。类是构造对象时所依赖的规范,类是时间事物的抽象称呼,而对象则是这个事物对应的实体。
类对象的行为是以方法的形式定义的,对象的属性是以成员变量的形式定义的,所以类包括对象的属性和方法。
6.1.3 封装
面向对象程序设计具有以下特点:封装性、继承性和多态性。
封装是面向对象编程的核心思。想
在面向对象程式设计方法中,封装是指一种将抽象性函式接口的实现细节部分包装、隐藏起来的方法。
采用封装的思想保证了类内部数据结构的完整性,使用类的用户不能轻易的直接操作类的数据结构,只能执行类允许公开的数据,这样就避免了外部操作对内部数据的影响,提高了程序的可维护性。
使用类实现封装特性:
6.1.4 继承
类与类之间同样具有关系,这种关系被称为关联。关联主要描述两个类之间的一般二元关系。两个类之间的关系有很多种,继承是关联中的一种。
设计软件时,使用继承思想可以缩短软件开发的周期,复用那些已经定义好的类可以提高系统性能,减少系统在使用过程中出现错误的概率。
继承性主要利用特定对象之间的共有属性。
从图中可以看出继承关系可以使用树形关系来表示父类与子类存在一种层次关系,一个类处于继承体系中,它既可以是其他类的父类,为其他类提供属性和行为,也可以是其他类的子类,继承父类的属性和方法,如三角形内既是图形类的子类也是等边三角形内的父类。
6.1.5 多态
在6.1.4节中介绍了继承、父类和子类,其实将父类对象应用于子类的特征就是多态。
多态性允许以统一的风格编写程序,已处理种类繁多的已存在的累积相关类。
6.2 类
对象的属性一成员变量的形式存在,对象的方法以成员方法的形式存在。
6.2.1 成员变量
对象的属性也称为成员变量,成员变量可以是任意类型,整个类中均是成员变量作用范围。
public class part{//类
private String name;//String类型的成员变量
public String getName() {//name的Getter方法
return name;
}
public void setName(String name) {//name的Setter方法
this.name=name;//将参数值赋予类中的成员变量
}
}
6.2.2 成员方法
在Java语言中,使用成员方法对应于类对象的行为。
定义成员方法的语法格式如下:
权限修饰符 返回值类型 方法名(参数类型 参数名){
.... //方法体
return 返回值;
}
6.2.3 权限修饰符
Java中的权限修饰符主要包括public、protect、default、private,这些修饰符控制着对类和类的成员变量以及成员方法的访问。
Java语言中的修饰符权限
6.2.4 局部变量
如果在成员方法内定义一个变量,那么这个变量被称为局部变量。在实际上,方法中的形参也可以作为一个局部变量。
局部变量是在方法被执行时创建,在方法执行结束时被销毁。局部变量在使用时必须进行赋值操作或被初始化,否者会出现编译错误 。
【例】交换两个整数的值
在ChangeDemo类中创建静态的exchange()方法,该方法可以将数组参数arr的前两个元素值互换,通过在方法中定义一个保存临时数据的局部变量tmp,利用tmp交换两个元素的值。
public class ChangeDemo{
public static int[] exchange(int[] arr){
int tmp=arr[0];//创建局部变量tmp,保存数组第一个元素的值
arr[0]=arr[1];//第二个元素值赋给第一个元素
arr[1]=tmp;//第二个元素值改为tmp
return arr;
}
public static void main(String[] args) {
int arr[]= {17,29};
System.out.println("第一个值="+arr[0]+",第二个值="+arr[1]);//输出
arr=exchange(arr);
System.out.println("第一个值="+arr[0]+",第二个值="+arr[1]);//输出
}
}
6.2.5 局部变量的有效范围
可以将局部变量的有效范围称为变量的作用域,局部变量的有效范围从该变量的声明开始到该变量的结束为止。
在相互不嵌套的作用域中,可以同时声明两个名称和类型相同的局部变量。
但是在相互嵌套的区域中不可以这样声明,如果将区域变量id在方法体的for循环中再次进行定义,编译器将会报错。
6.2.6 this关键字
this关键字用来表示本类当前的对象,当前对象不是某个new出来的实体对象,而是当前正在编辑的类。this关键字只能在本类中使用。
public void setName(String name) {//定义一个setName()方法
this.name=name;//将参数值赋予类中的成员变量
}
}
this除了可以调用成员变量或成员方法,还可以作为方法的返回值。
public Book getBook{
return this;//返回Book类的本类对象
}
6.3 类的构造方法
在类中,除成员方法外,还存在一种特殊类型的方法,那就是构造方法。构造方法是一个与类同名的方法,对象的创建就是通过构造方法完成的。每当类实例化一个对象时,类都会自动调用构造方法。
构造方法的特点:
构造方法没有返回值。
构造方法的名称要与本类的名称相同。
构造方法的定义语法格式:(public :构造方法修饰符;Book:构造方法的名称)
public Book(){
..... //构造方法体
}
在构造方法中可以为成员变量赋值,这样当实例化一个本类对象时,相应的成员变量也将被初始化。如果类中没有明确定义构造方法,编译器会自动创建一个不带参数的默认构造方法。
【例】“构造”鸡蛋灌饼:
当顾客购买鸡蛋灌饼时,如果要求加两个蛋,店家就给饼加两个蛋;不要时,店家会默认给饼加一个蛋。创建鸡蛋灌饼类,使用this关键字,在无参数构造方式中调用有构造方法,实现上加述加蛋过程。代码如下:
public class EggCake {
int eggCount;//鸡蛋灌饼里蛋的个数
public EggCake(int eggCount) {//参数为鸡蛋灌饼里蛋的个数的构造方法
this.eggCount=eggCount;//将参数依据eggCount的值赋给属性eggCount
}
public EggCake() {//无参数构造方法默认给饼加一个蛋
this(1);//调用参数为鸡蛋灌饼里蛋的个数的构造方法,并设置鸡蛋灌饼里蛋的个数为1
}
public static void main(String[] args) {
// TODO Auto-generated method stub
EggCake cake1=new EggCake();
System.out.println("顾客不要求加蛋的数量,饼里会有"+cake1.eggCount+"蛋");
EggCake cake2=new EggCake(2);
System.out.println("顾客要求加2个蛋的数量,饼里会有"+cake2.eggCount+"蛋");
}
}
6.4 静态变量和静态方法
由static修饰的变量和方法被称为静态变量和静态方法。被声明为static的变量和方法被称为静态成员。静态成员属于类所有,区别于个别对象,可以在本类或其他类使用类名和”.“运算符调用静态成员。语法如下:
类名.静态类成员
创建并调用静态属性和静态变量,创建StaticDemo类,在类中使用static关键字定义一个属性和一个方法,并在主方法中条用。代码如下:
【例】创建并调用静态属性和静态变量
创建homework类,在类中使用static关键字定义一个属性和一个方法,并在主方法中调用。
public class StaticDemo{
static double PI=3.1415;//在类中定义静态变量
public static void method() {//在类中定义静态方法
System.out.println("这就是静态方法");
}
public static void main(String[] args) {
System.out.println(StaticDemo.PI);//调用静态变量
StaticDemo.method();//调用静态方法
}
}
静态变量与静态方法的作用通常是为了提供共享数据或方法,如数学计算公式等。尽管使用这种方式调用静态成员比较方便,但静态成员同样遵循着public、private和protected修饰符的约束。
【例】统计顾客总数
在Cust类中创建一个静态整数类型属性count,在构造方法中让count自增。
public class Cust{//顾客类
static int count=0;//共享的属性:人数
String name;//名称属性
public Cust(String name) {
this.name=name;//记录名称
count++;//人数递增
}
public static void main(String[] args) {
Cust c1=new part("tom");
System.out.println("我是第"+Cust.count+"名顾客,我叫"+c1.name);
Cust c2=new part("张三");
System.out.println("我是第"+Cust.count+"名顾客,我叫"+c2.name);
Cust c3=new part("狗蛋儿");
System.out.println("我是第"+Cust.count+"名顾客,我叫"+c3.name);
}
}
总结以下使用static关键字要注意的几点:
- 在静态方法中不可使用this关键字。
- 在静态方法中不可以直接调用非静态方法。
- 局部变量不可以使用static关键字声明。
- 主方法必须用static声明。
- 只有内部类可以使用static关键字声明。
6.5 类的主方法
主方法是类的入口点,它定义了程序从何处开始。主方法提供对程序流向的控制,Java编译器通过主方法来执行程序。主方法的语法如下:
public stasti void mian(String args){
.... //方法体
}
在主方法的定义中可以看到其具有以下特点:
主方法是静态的,所以如要直接在主方法中条用其他方法,则该方法必须也是静态的。
主方法没有返回值。
主方法的形参为数组。其中,args[0]~[n]分别代表程序的第一个参数到n个参数,可以使用args.length获取参数的个数。
【例】读取主方法的参数组
在项目创建TestMain类,在主方法中编写一下代码,并在Eclipse中设置程序参数。
public class TestMain{
public static void main(String[]args){//定义主方法
for(int i=0;i<args.length;i++) {//根据参数个数做循环操作
System.out.println(args[i]);//循环打印参数内容
}
}
}
6.6 对象
对象是由类实例化而来的,所有问题都通过对象来处理。对象可以通过操作类的属性和方法来解决相应的问题,所以了解对象的产生操作和交往是十分必要的
6.6.1 对象的创建
对象可以认为是在一类事物中抽象出某一个特例,可以通过这个特例来处理这类事物出现的问题。
可以在Java语言中使用new操作符调用构造方法创建对象。语法如下:
Test test=new Test();
Test test=new Test("a");
创建对象语法中的参数说明
设置值 | 描述 | 设置值 | 描述 |
Test | 类名 | new | 创建对象操作符 |
test | 创建Test类对象 | ”a“ | 构造方法的参数 |
【例】创建人类并创建其对象
public class People{
String name;
int age;
String sex;
public People() {
}
public People(String name,int age,String sex) {
this.name=name;
this.age=age;
this.sex=sex;
}
public static void main(String []args) {
People p1=new People("tom",23,"男");
People p2=new People("lily",19,"女");
}
}
6.6.2访问对象的属性和行为
用户使用new操作对象符创建一个对象后,可以使用“对象.类成员”来获取对象的属性和行为。
【例】描述狗的特征
public class People {
String name;//名字
String color;//颜色
String vioce;//叫声
public People(String name,String color,String vioce) {
this.name=name;
this.color=color;
this.vioce=vioce;
}
public void call() {//叫
System.out.println(vioce);
}
public static void main(String []args) {
People d1=new People("毛毛","白色","汪汪汪");
System.out.print(d1.name+"的颜色是"+d1.color);//访问对象的属性
System.out.print("叫起来的声音:");
d1.call();//访问对象的行为
People d2=new People("灰灰","灰色","嗷呜~");
System.out.print(d2.name+"的颜色是"+d2.color);
System.out.print("叫起来的声音:");
d2.call();
}
}
6.6.3 对象的引用
真正的操作标识符实质上是一个引用,引用的语法:
类名 对象的引用变量
b d1 =new b();
b是类名,d1是引用名,new b对象的实体;
6.6.3 对象的销毁
每个对象都有生命周期,当对象的生命周期结束时,分配给该对象的内存地址需要被回收。在其他语言中,需要用户手动回收废弃的对象。Java拥有一套完整的垃圾回收机制,用户不必担心废弃的对象占用内存,垃圾回收器会自动回收无用却占用内存的资源。
怎么判断对象会被JAVA虚拟机视为垃圾。主要包括两种情况
虽然JAVA的垃圾回收机制已经很完善,但垃圾回收器只能回收那些由new操作符创建的对象。某些对象不是通过new创造并获得存储空间的,这种对象是无法被垃圾回收机制所识别。