Java--面向对象编程

一,面向对象程序设计方法概述

1,面向对象问题求解的基本思想

    面向对象方法的出发点和基本原则,是尽可能模拟人类习惯的思维方式,使描述问题的问题空间(也称为问题域)与实现解法的解空间(也称为求解域)在结构上尽可能一致。

面向对象问题求解的基本思想就是以对象为基本元素。

2,面向对象程序设计方法的内涵

  基础概念:对象,类,封装,继承,多态

万物皆对象:对象被当作一种新型的变量,它保存着数据,能对自己的数据进行操作,并且对外提供服务。

程序是一系列对象的组合。

每个对象都有自己的存储空间,可容纳其他对象。也就是说,通过封装现有对象,可以构造出新型对象。

每个对象都有一种类型。每个对象都是某个“类”的一个“实例”。一个类最重要的特征就是对外接口。

同一个类的所有对象都能接受相同的消息。子类与父类属于“同一类型”,它们可以接收相同的消息,因此可以向父类对象发送消息来统一控制所有子类对象的操作。

3,对象与类

对象的变量一般对外不可见,只有通过对象的方法才能操作它们。所有对象的方法都能访问该对象的变量和其他方法,但并不都能与外部对象通信。

类定以后可以像基本数据类型一样创建变量(即引用),引用可以指向一个具体的类对象,然后通过该引用实现对象的操作。

类是对象的创建模板,不能参与具体的操作;对象是类生成的具体实例,每一个对象都有一定的内存空间来存储它的属性和方法。

4,面向对象的特性

将对象变量和方法实现细节包装,隐藏起来的方法称为封装。

封装实现了数据的隐藏,减少了不当操作带来的负面影响。Java语言的封装性较强。

父子类之间具有继承关系,子类可在父类的基础上进行定义。即每个子类都继承了其父类的变量和方法,子类重用了父类中部分代码。更重要的是子类继承并具有父类的接口,使得发给父类对象的消息也可以被子类接收,子类对象可以作为父类对象使用。因为一般由类能够接收的消息来了解一个类的类型,所以这意味着子类和父类具有相同的类型。另外,在继承的基础上,子类还能对父类进行扩充,增加自己新的变量和方法,更重要的是子类可以利用重写改变继承父类的方法,这就意味着子类使用与父类相同的接口却能实现不同的操作。

多态:对外一个接口,内部多种实现。

编译时多态主要通过重载实现,在一个类中可以定义多个名字相同而参数列表和实现代码不同的方法,在编译时编译器会根据具体的参数形式调用相应的方法体,从而实现同一方法的不同实现。

运行时多态是在程序运行时动态产生的多态,它建立在类的继承体系上,通过类之间的继承,方法重写以及动态绑定来实现。父类定义对外统一的方法,子类继承这些方法并根据具体情况重写方法体。当通过父类的引用调用统一方法时,不需要在编译阶段考虑方法的具体实现,而是到执行时再根据父类引用指向的具体对象来执行子类重写的方法体,获得子类特殊的服务。

二,类

1,类的基本结构

在Java中,类是实现封装的基本单位,包含成员变量和成员方法两种成分,分别表示类的属性和行为。

成员方法与其他语言的函数区别在于:成员方法只能在类中定义;调用类的成员方法实际上是进行对象之间或用户与对象之间的消息传递。

[public][abstract/final] class name [extends 父类名] [ implements 接口列表]

public表示类是公有访问类型,缺省则表示类是默认(包)访问类型;abstract和final表示抽象类还是最终类,二者只能选其一;extends表示类继承了指定的父类;implements表示类实现了接口列表中的所有接口;

类体包含成员变量,构造方法和成员方法;其中构造方法用来创建并初始化对象;注意:成员变量和成员方法统称为类的成员,但构造方法不是类的方法,不能成为类的成员。

Java中成员的访问权限有四种:私有,公有,保护和默认(包)权限。

private:属于类自身分私有成员,只要类的方法才能访问,属于对外完全隐藏型。

2,成员变量

[public/protected/private] [static] [final] [transient] [volatile] 数据类型  变量名  ;

[public/protected/private]限定成员变量的访问权限;

static表示该变量为类变量,一个类变量在内存中只有一个存储空间,该类的所有对象实例都共享存储空间,没有static的成员变量是实例变量,每一个对象都为实例变量开辟一个存储空间,所以不同对象相同变量的变量值可以不同。

final常量,不能修改它的值,它常与static共同使用表示常量。

transient临时变量,只在内存中存在,不随对象保存在外存中,系统默认为类对象的永久变量,当对象保存到外存时,这些变量值必须同时保存;

volatile多线程的共享变量。

3,成员方法

成员方法定义包括两部分:方法声明和方法体。格式如下:

[public/protected/private] [static] [abstract/final] [native] [synchronized] 返回类型 方法名(参数列表) [throws<异常类列表>]

{    方法体     }

static表示方法为类方法,类方法只处理static类变量,实例方法不需要static修饰符;

abstract抽象方法,没有方法体;

final表示方法是最终方法,不能被子类重写;

native表示方法用其他语言实现;

定义成员方法的局部变量与参数变量时尽量不要与类的成员变量同名,否则成员变量将在该方法中被隐藏,如果要操作成员变量,就必须用this关键词使其显露出来。

成员方法的参数传递:传值和传引用。

基本数据类型,采用传值方式,即方法调用时会新开辟一块内存空间,存放参数传过来的数值,方法处理的都是这一新空间的值,当调用结束时释放该空间,而原变量值并没有改变,这一点同C语言;

当方法的参数是对象或数组等引用类型变量时,参数传递的是它们的引用(地址),即参数中存放的不是对象或数组的具体值,而是存放它们的首地址。这样,对新变量的操作实际上就是对原对象或数组的操作,所以原变量会随着新变量的变化而变化。

当调用形参数组时,系统首先为方法形参数组变量分配存储空间,同时将main()方法中已创建的实参数组变量的值赋给形参变量,对形参的操作就是对实参的操作,方法结束后,数组变量占用的空间被释放。

当调用形参对象时,系统首先为方法的对象引用分配存储空间,同时将已指向对象的对象变量的值赋给对象引用。

4,成员方法重载

有时候需要在同一个类中定义几个功能相似但参数不同的方法。(例如实现两个数相加,但加数可能有不同的类型,若考虑每一种类型则很麻烦)

方法的重载是指在同一个类里面,有两个或两个以上具有相同名称,不同参数的列表的方法。

重载方法通常用来命名一组功能相似的方法,这样就可以减少方法名的数量。

Java规定重载体必须满足以下规则:方法的参数列表必须不同,即参数个数不同或参数类型不同;方法的返回类型或修饰符可以相同,也可以不同。

方法重载实现了Java的编译时多态,即由编译器在编译时根据方法所用的参数类型和个数来确定具体调用哪个被重载的方法。

5,构造方法

主要完成对类的对象初始化。

[public/protected/private] 构造方法名 (参数列表) {  方法体  }

[public/protected/private]表示哪些类对象能够创建该类的一个实例。

构造方法的方法名与类名相同;构造方法没有返回值;构造方法不能由用户直接调用,必须通过new关键词由系统自动调用。

缺省的构造方法:没有参数,方法体也为空,它用各种数据类型的默认值来自动初始化对象的成员变量。

缺省的构造方法是在类没有定义构造方法时系统自动添加的,一旦类中定义了构造方法,它就不添加了。只要类中定义了构造方法,最好也要把无参的构造方法加上。

构造方法也可以重载,目的是实现对象的不同初始化,为类对象初始化提供方便。

6,this关键词

this表示指向当前对象自身的引用。在创建一个对象之后,Java虚拟机自动将该对象地址分配给this。

静态方法中不能使用this。

(1)区分局部变量和成员变量

this.变量名/方法名        简单起见,将this省略。

但是当成员方法或构造方法中的参数变量或局部变量与类的成员变量同名时,成员变量会被隐藏,即参与操作的是局部变量或参数变量。这时如果想访问类的成员变量,就必须用this.变量名.

(2)使用this调用构造方法

构造方法重载后,可用this(参数列表)的形式实现构造方法相互调用,从而简化构造方法的程序代码。

注意:this([参数列表])必须是构造方法体中第一条语句而且只能调用一次。

class Box{
  private double widch;
  private double height;
  private double depth;
  public Box(){
     this(1,1,1);  }       各赋值为1
  public Box(double x){
     this(w,1,1);  }

(3)this作为参数

把当前的对象的引用作为参数传递给其他对象。由其他对象调用this所指对象的方法。

三,对象

一个对象完成了所有操作后,将被垃圾回收器释放其所占用的内存。一个对象的生命周期包括创建,使用和回收三个阶段。

(1)对象的创建

类是对象的模板,对象是类的实例。类与对象就是数据类型与变量的关系。

对象变量的声明:类名  对象变量名;    为该变量分配了一个引用空间,声明后不能直接使用。

对象的实例化:   new 构造方法([参数列表]);

首先为对象分配内存空间,并用系统默认的值为成员变量初始化;其次执行显式初始化,即执行成员变量声明时的复制表达式;然后执行构造方法体中的语句,进行对象的初始化;最后返回对象占用存储空间的首地址即对象的引用。

(2)对象的使用

当一个对象被实例化后,该对象就拥有了自己的成员变量和成员方法,就可以使用点运算符来访问对象的成员。

一般不提倡直接操作对象的成员变量,因为这样会破坏类的封装和信息隐藏。比较好的访问方式就是把成员变量的访问权限设置为private,然后通过对象提供的get和set成员方法来读和写,而且可在set()方法中进行数据正确性,完整性的约束检查。

(3)对象的清除

在对象使用完之后释放它所占用的内存空间。

Java使用了与C++完全不的内存管理机制--垃圾回收机制,即用户在创建对象后不必考虑对象删除问题,系统会监控每个对象的运行状态,在确定某个对象不再被使用后自动释放其内存空间。

用户可通过System.gc()方法显示地进行垃圾回收。

四,继承

当一个类能够获取另一个类中所有非私有的成员变量和方法作为自己的一部分或全部时,这两个类之间就具有了继承关系。

一个父类可以同时拥有多个子类,此时这个父类实际上就是所有子类公共变量和公共方法的集合,每一个子类则是父类的一个特例。

(1)子类的创建

Java中extends是实现类继承的关键词。

class 子类名   extends  父类名  [implements 接口]

Java不支持多重继承,只支持单继承,所以extends后的父类只能有一个;

Java提供了接口机制,使得子类虽然只能有一个父类,但是可以实现多个接口,这样既避免了多重继承的复杂性,又达到了多重继承的效果。

子类定义时,只需要写出自己新增的成员变量,成员方法和对父类方法的修改,父类中的成员是默认继承的,可以直接使用。

父类中private修饰的私有变量和方法子类不能继承;父类的构造方法子类不能继承。

若定义类时省略了extends关键字,则所定义的类默认为java.lang.Object的子类。

(2)super关键词

super关键词表示的是指向该关键词所在类的父类对象即当前对象的直接父类对象的引用,使用super关键词可显式的引用父类的变量或方法即super.成员变量。

注意super调用的方法不一定是在当前类的直接父类中定义的,但可以是直接父类在类的继承体系中继承而来的。

super的主要用途如下:在子类的构造方法中直接调用父类的构造方法;用于在子类中显式的引用被隐藏的继承自父类的同名变量;用于在子类中调用被重写的父类的成员方法。

(3)子类对象的创建与实例化

一个子类对象的创建与实例化都要经历以下步骤:分配成员变量的存储空间并进行默认的初始化;绑定构造方法参数。

在构造方法里面,首先要检查是否有this或super调用,二者只能出现一个,并且只能作为构造函数的第一句。


Java的安全模型要求对象的初始化时必须首先将从父类继承的部分进行完全的初始化。因此Java在执行子类构造方法之前通常要调用父类的一个构造方法。一般在子类的构造方法的第一条语句通过super([参数列表])调用父类相应的构造方法,如果不显式使用super调用父类构造方法,则Java将隐式调用父类的构造方法即super()。如果父类中没有无参数的构造方法,则产生编译错误。

(4)隐藏与重写

子类成员变量隐藏父类同名成员变量。

成员变量隐藏时,只要同名即可,变量类型可以不相同。

只能隐藏非私有成员变量。

子类中重写方法的方法名与参数列表必须与父类中被重写非方法相同,返回值类型与父类中被重写方法的返回值类型相同或兼容。

子类中重写方法的访问权限可以扩大但不能缩小;不能重写子类中被final修饰的方法;父类中的静态方法不能被重写,但是可以在子类中定义与父类相同的静态方法实现隐藏。

五,多态

提供了“接口与实现的分离”,即将方法名与方法体分离。

在类的继承体系中,多态可以弱化子类之间的区别,将它们都当成父类对象统一对待,这样一段代码就可以同时作用于不同的子类对象,而子类对象的区别可以通过方法实现上的差异来体现。

Java提供动态绑定可以在程序运行时自动调用不同子类的不同方法体,实现子类的区分。

(1)向上转型

子类对象也能作为父类的对象使用,子类对象即属于子类类型也属于父类类型。因此从父类派生出的各种子类都可作为同一类型即父类的类型。将子类对象的引用转换为父类对象的引用或父类对象引用指向其任一子类对象,就称为向上转型。将子类对象赋给父类对象引用是自下而上的转换。

当父类对象引用指向子类对象时,子类对象要当成父类对象使用,这是一个变量从少到多的转换,肯定是安全的。

class HourlyEmployee extends Employee;
Employee e;
HourlyEmployee he = new HourlyEmployee();
e=he;   //父类对象引用e指向其子类对象he,即e就是he的向上转型对象 

(2)向下转型

也称为类的强制类型转换,是将父类对象的引用强制转换成子类类型。只有将父类对象引用强制转换为子类类型,才能通过该对象引用访问子类特有的成员。

在进行对象强制类型转换时,为了保证转换能够成功,一般要先用Java提供的Instanceof运算符测试当前要转换的对象的类型。

对象  instanceof 类;   当对象属于类时返回true。

只有向上转型对象才能执行向下转型。

(3)运行时多态

Java中的类可以自动进行向上转型,所以子类对象可以当成父类对象使用。即父类对象的引用可能指向一个父类对象,也可能指向一个子类对象。

同一个父类派生出的多个子类可被当做同一类型对待。

在Java中,绑定分为动态绑定和静态绑定,Java中除了final,static,private和构造方法是前期绑定外,其他的方法全部为动态绑定。

猜你喜欢

转载自blog.csdn.net/shen_zhu/article/details/80228060