类与对象的基本概念


类与对象的概念

:类是一个模板,它描述一类对象的行为和状态。

对象:对象是类的一个实例。有状态和行为。例如,一条狗是一个对象,它的状态有:颜色、名字、品种;行为有:摇尾巴、叫、吃等。

下图中男孩女孩为类,而具体的每个人为该类的对象:

类与对象的关系:类是对象的抽象,而对象是类的具体实例。类是抽象的,不占用内存,而对象是具体的,占用存储空间。类是用于创建对象的蓝图,它是一个定义包括在特定类型的对象中的方法和变量的软件模板。

1、类的声明

(1)类的结构

(2)声明格式

类修饰符的含义:

public 将一个类声明为公共类,它可以被任何对象访问。

abstract 将一个类声明为抽象类,没有实现方法,需要子类提供方法的实现。

final 将一个类声明为最终类即非继承类,表示它不能被其它类所继承。

friendly 友元类型,默认的修饰符,只有在相同包中的对象才能使用这样的类。

(3)类的成员变量

在类中声明的变量就是成员变量,作用域是整个类。它描述了该类的内部信息,一个成员变量可以是简单变量,也可以是对象、数组等其它结构性数据。

成员变量修饰符的含义:

public 公有访问控制符。指定该变量为公共的,它可以被任何对象的方法访问。

private 私有访问控制符。指定该变量只允许自己类的方法访问,其它任何类(包括子类)中的方法均不能访问此变量。

protected 保护访问控制符。指定该变量只可以被它自己的类及其子类访问,在子类中可以覆盖此变量。

static 静态修饰符。指定该变量被所有对象共享,即所有的实例都可以使用该变量。

final 最终修饰符。指定常量。

transient 过度修饰符。指定该变量是一个系统保留,暂无特别作用的临时性变量。

volatile 易失修饰符。指定该变量可以同时被几个线程控制或修改。

(4)类的成员方法

成员方法描述对象所具有的功能和操作,反映对象的行为,是具有某种相对独立功能的程序模块。一个类或对象可以有多个成员方法,对象通过执行它的成员方法对传来的消息作出相应,完成特定的功能。

成员方法一旦定义,便可以在不同的场合中多次调用,故可增强程序结构的清晰度,提高编程效率。

格式:

如果不需要传递参数到方法中,只需将方法名后的括号中的参数去掉即可,并将返回值类型定义为void,return语句也就可以省略。

成员方法修饰符的含义:

public 公有访问控制符。指定该方法为公共的,它可以被任何对象的方法访问。

private 私有访问控制符。指定该方法只允许自己类的方法访问,其它任何类(包括子类)中的方法均不能访问此变量。

protected 保护访问控制符。指定该方法只可以被它自己的类及其子类访问。

friendly 默认的友元访问控制符,在同一个包中的其它类可以访问此方法,而其它包中的类不能访问该方法。

final 最终修饰符。指定该方法不能被重载。

static 静态修饰符。指定不需要实例化一个对象就可以激活的方法。

synchronized 同步修饰符。在多线程程序中,该修饰符用于在运行前,对它所属的方法加锁,以防止其它线程访问,运行结束后解锁。

native 本地修饰符。指定此方法的方法体是用其它语言在程序外部编写的。

示例:创建一个类,该类含有类的成员变量和成员方法

示例:创建一个类,该类含有判断质数的成员方法,测试时从键盘输入一个数,判断是否为质数

2、方法的重载

方法的重载指一个类中有多个方法有相同的名字,但是这些方法的参数必须不同,或者是参数的个数不同,或者是参数的类型不同。返回值类型不能用来区分重载的方法。

作用:实现同名的构造方法可以接受不同的参数。

示例:创建一个类,该类包含两个重载的方法,对该类进行测试

3、构造方法

构造方法(constructor)是一种特殊的方法,它是在对象被创建时初始化对象的成员的方法。构造方法的名称必须与它所在的类名完全相同。构造方法没有返回值,但在定义构造方法时,构造方法名前不能用修饰符void来修饰,这是因为一个类的构造方法的返回值类型就是该类本身。

构造方法定义后,创建对象时就会自动调用它,因此构造方法不需要在程序中直接调用,而是在对象产生时自动执行。这一点不同于一般的方法,一般的方法是在需要时才调用。

构造方法的形式:

每个类至少有一个构造方法。类被定义时如果没有显示地定义一个构造方法,那么编译器会自动创建一个默认构造方法,默认构造方法没有参数,而且方法体为空。其形式如上图b所示。

示例:利用构造方法来初始化圆柱体类Cylinder的成员变量

4、对象

对象是系统中用来描述客观事物的一个实体,它是构成系统的一个基本单位。一个对象由一组属性和对这组属性进行操作的一组方法组成。

一个对象的生命周期包括三个阶段:生成、使用和消除。

(1)对象的生成

对象的生成包括声明、实例化。

格式:类名 对象名=new类名([参数列表]);

声明:类名 对象名

声明并不为对象实体分配内存空间,而只是分配一个引用空间。

实例化:运算符new为对象分配内存空间,它调用对象的构造方法,返回对象的引用;一个类的不同对象分别占据不同的内存空间。如果类中没有显示给出构造方法,系统会调用默认的构造方法。

对象的内存模型图:

(2)对象的使用

通过运算符“.”可以实现对对象属性和方法的调用。

访问对象属性的格式:对象名.变量名; 如:person.name="张三";

调用对象的方法的格式:对象名.方法名([参数列表]);如:x.speak("music");

(3)对象的清除

Java的垃圾收集机制会周期性地自动扫描对象的动态内存区,检测某个实体是否已不再被任何对象所引用,如果发现这样的实体,就释放实体占有的内存。系统垃圾回收方法为System.gc(),当系统内存用尽或调用System.gc()要求垃圾回收时,垃圾回收线程与系统同步运行。

示例:设计一个计算阶乘的类Fact,对该类进行测试

5、父类、子类和继承

Java中,所有的类都是通过直接或间接地继承java.lang.Object得到的。Object类是所有类的父类,如果一个类没有使用extends关键字明确标识继承另外一个类,那么这个类就默认继承Object类。因此,Object类是Java类层中的最高层类,是所有类的超类。Java中任何一个类都是它的子类,由于所有的类都是由Object衍生出来的,所以Object的方法适用于所有类。

继承而得到的类为子类,被继承的类为父类,父类包括所有直接或间接被继承的类。子类继承父类的状态和行为,同时也可以修改父类的状态或重载父类的行为,并添加新的状态和行为。

(1)创建子类

格式:class SubClass extends SuperClass{.....}

通过extends把SubClass声明为SuperClass的直接子类,如果SuperClass又是某个类的子类,则SubClass同时也是该类的间接子类。子类可以有选择的继承父类中访问权限设定为public、protected的成员变量和方法。但不能继承访问权限为private的内容。

(2)继承

继承是一种由已有的类创建新类的机制,通过继承实现代码复用。利用继承,我们可以先创建一个共有属性的一般类,根据该一般类再创建具有特殊属性的新类,新类继承一般类的状态和行为,并根据需要增加它自己的新的状态和行为。

子类不能继承父类中访问权限为private的成员变量和方法。子类可以重写父类的方法及命名与父类同名的成员变量。但Java不支持多重继承,即一个类从多各超类派生的能力。

子类继承父类的方法和属性,而自己又增加了新的属性和方法,所以子类的功能比父类要强大。

子类不继承父类的构造方法。

(2.1)子类与父类在同一包中的继承性

子类自然地继承了父类中不是private的成员变量和方法作为自己的成员变量和方法。

示例:子类和父类在同一包中的继承性。

(2.2)子类和父类不在同一包中的继承性

子类和父类不在同一个包中,子类继承了父类的protected,public成员变量和方法;但能不继承父类的友好变量和方法。

示例:Father和Jerry分别隶属不同的包

(3)成员变量的隐藏和方法的重写

当在子类中定义的成员变量和父类中的成员变量名同名时,则父类中成员变量被隐藏,此时称子类的成员变量隐藏了父类的成员变量。

如果局部变量的名字与成员变量的名字相同,则成员变量被隐藏,即这个成员变量在这个方法内暂时失效。这时如果想在该方法内使用成员变量,就必须使用关键字this。

当子类中定义了一个方法,并且这个方法的名字、返回类型、参数个数和类型与父类中的某个方法完全相同时,父类的这个方法将被隐藏,这就是父类方法的重写,也称为方法的覆盖。

子类通过隐藏父类的成员变量和重写父类的方法,可以把父类的状态和行为改变为自身的状态和行为。

示例:子类重写父类的方法

6、super关键字

子类在隐藏了父类的成员变量或覆盖了父类的方法后,常常还要用到父类的成员变量,或在覆盖的方法中使用父类中被覆盖的方法以简化代码的编写,这时就要访问父类的成员变量或调用父类的方法,Java中通过super来实现对父类成员的访问,super用来引用当前对象的父类。

主要有三种情况:

用来访问父类被隐藏的成员变量,如super.variable。

用来调用父类中被覆盖的方法,如super.Method([paramlist])。

用来调用父类的构造方法,如super([paramlist])。

子类不继承父类的构造方法,如果子类想使用父类的构造方法,子类必须在自己的构造方法中使用关键字super来表示父类的构造方法,而且super必须是子类构造方法中的头一条语句。

示例:子类使用关键字super来调用父类的构造方法。

示例:使用关键字super调用被子类隐藏了的父类的成员变量或方法

7、上转型对象

假设A类是B类的父类,当我们用子类创建一个对象,并把这个子类对象的引用放到父类的对象中时,如:

称这个父类对象a是子类对象的b的上转型对象,上转型对象的实体是子类负责创建的,但上转型对象会失去原对象中新增的一些属性和方法。

上转型对象特点:

(1)上转型对象不能操作子类新增的成员变量和子类新增的方法,失去了这部分属性和功能。

(2)上转型对象可以操作子类继承的成员变量,也可以使用子类继承的或重写的方法。

(3)如果子类重写了父类的某个方法后,当对象的上转对象调用这个方法时一定是调用了这个重写的方法,因为程序在运行时知道,这个上转型对象的实体是子类创建的,只不过改变了一些功能而已。

不要将父类创建的对象和子类对象的上转型对象混淆。

示例:上转型对象

8、多态性

多态体现在两个方面:由方法重载实现的静态多态性(编译时多态)和方法重写时实现的动态多态性(运行时多态)。

(1)编译时多态:在编译阶段,具体调用那个被重载的方法,编译器会根据参数的不同来静态确定调用相应的方法。

(2)运行时多态:指父类的某个方法被子类重写时,可以各自产生自己的功能行为。

子类继承了父类除私有的所有属性,对于重载和继承的方法,Java运行时系统根据调用该方法的实例的类型来决定选择哪个方法调用。对于子类的一个实例,如果子类重载了父类的方法,则运行时系统调用子类的方法,如果子类继承了父类的方法(未重载)则运行时调用父类的方法。

示例:运行时多态

示例


类的访问权限与包的概念

1、类的访问控制

类的访问控制有public、abstract、final及friendly(无修饰符或默认)4种,不能用protected和private修饰符。

(1)public类

表示所有其它的类都可以使用此类,这个类作为整体是可见和可使用的,程序的其它部分可以创建这个类的对象,访问这个类可用的成员变量和方法。

(2)abstract类

抽象类有点类似“模板”的作用,其目的是根据它的格式来创建和修改新的类。但是并不能直接由抽象类创建对象,只能通过抽象类派生出新的子类,再由其子类来创建对象。也就是说,抽象类就是不能用new运算符来创建实例对象的类,它可以作为父类被它的所有子类所共享。

说明:在抽象类中的方法可分为两种,一种是一般方法;另一种是抽象方法,由abstract关键字开头的方法,此方法只声明返回值的数据类型、方法名与所需要的参数,但没有方法体。也就是说,抽象方法只需声明,而不需实现。当一个方法为抽象方法时,意味着这个方法必须被子类的方法所覆盖,否则子类仍然是abstract的。抽象方法中,修饰符static和abstract不能同时使用。

示例:写两个类Dog和Bird,继承抽象类Animal,子类对 父类的抽象方法进行重写。

(3)final类

在类名前加关键字final,这个类就被定义为final类,当一个类被定义为final时,它的所有方法都自动成为final方法。

final类不能被继承,不能被覆盖,其执行速度比一般类快。API中的String、Math等就是典型的final类。

(4)friendly类

当没有修饰符时,称此类为friendly类,表示该类只能被本包中的其它类使用。

示例:friendly类被本包中的其它类使用

2、类成员的访问控制

当用一个类创建了一个对象之后,该对象可以通过"."点运算符访问自己的变量,并使用类中的方法。但访问自己的变量和使用类中方法是有一定限制的。通过修饰符private、default、protected和public来说明类成员的使用权限。

private(私有的):类中限定为private的成员只能在这个类中被访问,在类外不可见。

default(无修饰符,默认的):若没有访问控制符,则该类成员可以被该类所在包中的所有其它类访问。

protected(受保护的):用该关键字修饰的类成员可以被同一类、被该类所在包中的所有其它类或其子类(可以不在同一包中)的实例对象访问。

public:其修饰的成员可以被其它任何类访问,前提是对类成员所在的类有访问权限。

3、类的组织

(1)包package

包是Java语言提供的一种区别类名空间的机制,是类的组织方式,每个包对应一个文件夹,包中还可以再有包,称为包等级。在源程序中可以声明类所在的包,就像保存文件时要说明文件保存在哪个文件夹中一样。同一包中的类名不能重复,不同包中的类名可以相同。所以说,包实际上提供了一种命名机制和可见性限制机制。

当源程序中没有声明类所在的包时,Java将类放在默认包中,这意味着每个类使用的名字必须互不相同,否则会发生冲突,,就像在一个文件夹中文件名不能相同一样。一般不要求处于同一包中的类有明确的相互关系,如包含、继承等,但是由于同一包中的类在默认情况下可以相互访问,所以为了方便编程和管理,通常把需要在一起工作的类放在一个包里。

包的创建:若要创建自己的包,就必须以package语句作为Java源文件的第一条语句,指明该文件中定义的类所在的包。格式如下:

package 包名1[.包名2[.包名3]...];

包名的命名规则:所有字母全部小写,其可以是一个合法的标识符,也可以是若干个标识符加“."点分割而成。如果在package语句的包名中含有“."点号,则其代表了目录分隔符。这是,需要按照包名分割的顺序,依次创建文件夹中的子文件夹。如:

package com.learnhelp;

那么程序文件的目录结构必须包含有如下的结构:

\com\learnhelp

(2)导入包

使用import语句可以引入包中的类。

在编写源程序时,除了自己编写的类外,还经常需要使用Java提供的许多类,这些类可能在不同的包中。这时可以使用import来导入。

import 包名.类名;

如:

(3)Java常用类包

(3.1)java.lang包

包含了各种定义Java语言时必须的类,这些类能够以其他类不能使用的方式访问Java的内部。任何Java程序都将自动引入这个包。

Object类:Java中最原始、最重要的类,每个Java类都是它的子类,它实现了每个类都必须具有的基本方法。

基本类型包装器:Boolean、Character、Number、Double、Float、Integer、Long。

String类:字符串类。

Math类:数学函数的集合。

执行线程类Thread、ThreadGroup、接口Runnable。

System类和Runtime类:可以通过类Runtime和System访问外部系统环境。System类的两个常用功能就是访问标准输入/输出流和错误流、退出程序。

异常和错误:类Exception、Error。

接口Throwable。

(3.2)java.io包

Java的输入输出模式是完全建立在流的基础之上的。流是一种字节从一个地方到另一个地方的单向流动,可以把流附加于文件、管道和通信链路等。java.io类包中定义的许多种流类通过继承的方式进行组织,其中也包括一些用来访问本地文件系统上的文件流类。

(3.3)java.util包

包含了一些实用类和有用的数据结构,如字典、散列表、堆栈、向量以及枚举类等。

(3.4)java.sql包

该包是实现JDBC的类库,利用这个包可以使Java程序具有访问不同种类数据库的功能,只要安装了合适的驱动程序,同一个Java程序不需要修改就可以存取、修改这些不同的数据库中的数据。