摘要:本文简单介绍了面向对象的编程方式,以及与之有关的一些基本定义。

面向对象

什么是面向对象

面向对象编程是一种对现实世界建立计算机模型的一种编程方法。简称OOP(Object Oriented Programming)。

面向对象是一种编程思想,是一种思考问题的思维方式。

在现实世界中,当我们提到动物这个概念,实际上它是一个抽象的概念,而具体动物是指老虎,狮子,大象等等。

在对应的计算机模型中,我们把动物这种抽象的概念称之为Class,也就是类。而那些具体的对象称之为实例,并且用不同变量标识不同的实例。

面向对象和面向过程

面向过程与面向对象都是我们编程中,编写程序的一种思维方式。

面向过程的程序设计方式,是遇到一件事时,先做什么,再做什么,然后一步步实现的过程。

面向对象的程序设计方式,是遇到一件事时,先思考有哪些类和对象,然后思考类和对象里有哪些属性和方法,然后分析类和类之间的关系,最后一群对象合力能把事就好。

类和对象

定义

类是一组具有相同特征的对象的集合,是一个抽象的概念。类中定义了这一类对象所具有的静态属性(属性)和动态属性(方法)。

对象是一个类具体的某一个实例,是看得见摸得着的东西。世间存在的一切都可以看做是对象。

语法

定义类:

 1 public class 类名 {
 2     属性类型 属性名 = 属性值;
 3     ...
 4     public void 方法名(int i) {
 5         方法体;
 6     }
 7     ...
 8     public static void main(String[] args) {
 9         主函数方法体;
10     }
11 }

定义对象:

1 类名 对象名 = new 类名();

this

说明:

为了解决全局变量和局部变量重名的问题,为了区分开全局变量和局部变量。

this代表的是当前类的对象,可以访问属性、访问访问方法、构造方法。

语法:

1 this.属性名;// 访问属性
2 this.方法名();// 访问方法
3 this(参数);// 访问构造方法

访问构造方法时,必须放在构造方法中,而且必须放在构造方法的第一句。

在一个构造方法中,不能多次调用其他构造方法。

super

说明:

表示子类中拿到的父类的引用(不是父类的对象)。

语法:

1 super.属性名;// 访问父类属性
2 super.方法名();// 访问父类方法
3 super(参数);// 访问父类构造方法

访问构造方法时,必须放在构造方法中,而且必须放在构造方法的第一句,在一个构造方法中只能有一个。

只能不能this一起出现。

类的加载机制

从父到子,静态先行。

父类的静态代码块,父类的代码块,父类的构造器,子类的静态代码块,子类的代码块,子类的构造器。

创建子类的顺序

先调用子类的构造方法。

子类中调用父类的构造方法。如果没有显式说明调用父类的哪个构造,则默认是调用父类的无参构造。如果显式说明了,则调用指定的父类的构造。

依次向上递推,一直到最上级。

方法

定义

方法就是用来完成解决某件事情或实现某个功能的办法。

在Java中,声明一个方法的具体语法格式如下:

1 修饰符 返回值类型 方法名(参数类型 参数名, 参数类型 参数名, ... , 参数类型 参数名) {
2     执行语句;
3     return 返回值;
4 }

修饰符:

方法的修饰符比较多,有对访问权限进行限定的,有静态修饰符static,还有最终修饰符final等,这些修饰符在后面的学习过程中会逐步介绍。

返回值类型:

用于限定方法返回值的数据类型,返回给调用方,返回类型可以是任意类型。

如果不需要返回值,则写void,也不需要写return和返回值。如果需要返回值,则需要写一个返回类型,并且return后的返回值需要和返回类型一致。

方法名:

功能块的名字,命名规则和变量命名规则一样。

参数类型和参数名:

参数类型用于限定调用方法时传入参数的数据类型,可以为任意类型。参数类型和返回类型没有任何关系。

参数名是一个变量,用于接收调用方法时传入的数据。

参数:

参数类型和参数名组成参数。

参数可以有多个,中间用逗号隔开。

方法定义时参数称为形式参数,简称形参。方法调用时参数称为实际参数,简称实参。

形参和实参的类型、个数、顺序必须一致,名字没有要求。

执行语句:

里面可以写任何逻辑语句,表示的是此方法的具体功能。

return和返回值:

return用于结束方法以及返回方法指定类型的值。

返回值是被return语句返回的值,该值会返回给调用者。

调用

方法的调用可以通过如下方式调用:

1 类型 变量名 = 对象实例.方法名(参数);

但是在不同的情况下又有不同的区分,有的可以不写或者不能写。

是否有参数

如果有参数,那么需要在括号中填写参数,多个参数用逗号分隔: 类型 变量名 = 对象实例.方法名(参数, 参数); 。

如果没有,则不需要填写参数: 类型 变量名 = 对象实例.方法名(); 。

是否有返回值

如果方法有返回值,那么需要用接收返回值,也可以不接收,但建议用对象接收: 类型 变量名 = 对象实例.方法名(参数); 。

如果没有返回值,则不需要接收返回值: 对象实例.方法名(参数); 。

是否在当前类中使用

如果在当前类中使用,则可以直接调用,不需要通过对象实例调用: 类型 变量名 = 方法名(参数); 。

如果在其他类中使用,则需要通过对象实例调用: 类型 变量名 = 对象实例.方法名(参数); 。

如果是被statis修饰的方法,则可以通过类名调用: 类型 变量名 = 类名.方法名(参数); 。

参数传递

参数传递是指,调用方法时,将实参的值传递给形参过程。

定义方法时,参数列表中的变量,我们称为形式参数。调用方法时,传入给方法的数值,我们称为实际参数。

当调用方法时,如果传入的数值为基本数据类型(包含String类型),形式参数的改变对实际参数不影响。

当调用方法时,如果传入的数值为引用数据类型(String类型除外),形式参数的改变对实际参数有影响。

重载

同一个类中,方法名相同,参数列表不同,这种现象称为方法重载(overload)。

所谓的参数不一样,主要有两点,第一是参数的个数不一样,第二是参数的类型不一样。只要这两方面有其中的一方面不一样就可以构成方法的重载了。

重写(覆盖)

方法覆盖是说子类重新定义了父类的方法,是在两个类中,必须有相同的方法名,相同的参数列表,相同的返回类型。

被重写的方法不能拥有比父类的方法更严格的访问控制权限。

构造方法不能被继承,因此不能被重写,在子类中只能通过super关键字调用父类的构造方法。

类的构造方法(构造器)

构造方法是类用于创建对象的 一个特殊的方法,当类创建对象时,就会调用类的构造方法。

语法:

1 修饰符 类名(参数列表) {
2     方法体;
3 }

说明:

构造方法没有返回类型,也不能使用void关键字。

构造方法的方法名必须和类名一致。

如果在类中没有定义构造方法,那么编译器会提供默认的构造方法,默认的构造方法没有参数列表,也没有方法体。

如果在类中定义了构造方法,那么编译器就不会提供默认的构造方法。

构造方法必须使用new关键字进行调用: new 类名(); 或 new 类名(参数); 。

初始化块

说明

初始化块分为静态初始化块和动态初始化块,优先于构造方法执行,经常执行初始化信息。

静态初始化块和普通初始化块都可以有多个,都可以写任何逻辑语句,不能定义方法。

执行顺序

静态成员变量初始化和静态初始化块的执行顺序由定义位置决定,从上往下执行。

成员变量初始化和初始化块的执行顺序由定义的位置决定,从上往下执行。

最后执行构造方法。

普通初始化块和静态初始化块对比

相同点:

默认执行顺序都是从上往下,都可以有多个。

不同点:

普通初始化块能执行多次,静态初始化块只执行一次。

普通初始化块实在对象创建后执行,静态初始化块是在类加载时执行。

普通初始化块可以访问普通成员和静态成员,静态成员初始化块只能访问静态成员。

接口

说明

接口可以理解成一种特殊的抽象类,里面全是抽象方法,它比抽象类层级更靠上。

接口相当于定义了一组规范。接口体现了程序设计的多态和高内聚低偶合的设计思想。

接口的定义使用interface关键字。

接口不能实例化。

好处

允许多继承、多实现,解决了前面Java中单继承缺陷。

灵活,解耦性高。

成员

没有构造方法。

没有普通的成员变量和成员方法,里面全是常量和抽象方法。

常量的修饰符默认是并且只能是(public static final)。

方法的修饰符默认是并且只能是(public abstract)。

类对接口的实现

类对接口的实现使用implement关键字完成,而且一个类可以实现多个接口。

语法: class A implements B, C { ... } 。

普通类必须实现里面所有的抽象方法,抽象类不用实现里面所有抽象方法。

重写接口的抽象方法,修饰符只能是public。

接口对接口的继承

接口对接口的继承使用extends关键字,而且一个接口可以继承多个接口。

语法: interface A extends B, C { ... } 。

包可以对程序员编写的代码文件进行目录层次的管理,解决了同一个项目中类名重复的问题。

在不同的包下的两个名字相同的两个类,会被编译器看做是不同的两个类。

命名规则

小圆点、数字、下划线、美元符,不能数字开头,不能是关键字。

一般由小写字母和小圆点组成,采用域名倒置的写法。

声明规则

必须在代码的第一行对包进行声明。

使用package关键字进行声明,语法是: package 包名; 。

如果没有声明包,则表示无包名。

一个Java文件中最多只能有一个包的声明。

导入规则

建议在包的声明下面导入包,实际上是导入包中的某个用到的类。

使用import关键字对包进行导入,语法是: import 包名.类名; 。

如果没有导入在当前类用到的类,那么在使用的时候需要写明用到的类所在的包名和类名,导入之后便可以只写类名。

一个Java文件中可以有多个导入。

比较重要的几个包

java.lang:包含一些Java语言的核心类,如String、Math、Integer、System和Thread,提供常用功能。

java.net:包含执行与网络相关的操作的类和接口。

java.io:包含能提供多种输入/输出功能的类。

java.util:包含一些实用工具类,如定义系统特性、接口的集合框架类、使用与日期日历相关的函数。

java.text:包含了一些Java格式化相关的类。

java.sql:包含了Java进行JDBC数据库编程相关的类。

java.awt:包含了构成抽象窗口工具集(abstract window toolkits)的多个类,这些类被用来构建和管理应用程序的图形用户界面(GUI)。

java.applet:包含applet运行所需的一些类。

修饰符

访问修饰符

Java语言采用访问控制修饰符来控制类及类的方法和变量的访问权限,从而向使用者暴露接口,但隐藏实现细节。

访问的意思是,其他类通过创建对象,可以调用。

Java提供了四种访问控制级别:

◆ public

public可以修饰类、方法、构造方法和接口。

父类中声明为public的方法在子类中也必须为public。

被public修饰的能够被任何其他类访问,如果不在同一个包中,则需要导入所在的包。

如果一个类使用public修饰,那该类的类名必须与他所在的源文件名相同。一个Java源文件中有且只有一个public类。

◆ protected

protected不能修饰类和接口。

父类中声明为protected的方法在子类中要么声明为protected,要么声明为public。不能声明为private。

◆ 默认的

不使用任何修饰符声明的类、属性和方法,对同一个包内的类是可见的。接口里默认情况下访问权限为public。

父类中默认修饰符声明的方法,不能在子类中声明为private。

◆ private

被声明为private的变量、方法、构造方法和内部类只能被所属类访问,并且类和接口不能声明为private。

static

修饰类的成员(属性、方法、初始化块、内部类),但不能修饰构造方法。

被修饰的类的成员,称为静态成员,如(类)静态属性、(类)静态方法、静态初始化块、静态内部类。

用static修饰的成员,可以直接通过类名调用,比较简单。

用static修饰的方法,里面只能访问静态成员,不能访问非静态成员。

静态成员随着类的加载而加载,静态成员优先于普通成员而加载。只加载一次,普通成员随着对象创建而加载,可以加载多次。

所有对象都共享静态成员。

static修饰的方法中不能使用this或super。

final

可以修饰数据、方法、类。

修饰类,不能被继承,也称为太监类、最终类,比如String类就是最终类。

修饰方法,不能被重写,但可以被继承。

饰局部变量和全局变量,都称为常量,一旦赋值,不能更改,保存在常量池。修饰的全局变量声明时必须赋值,要么在声明时,要么在所有构造方法,要么在初始化块。

如果常量类型为引用类型,指引用的对象不能更改,但对象的属性可以更改。

final往往和static搭配使用。

static和final的比较

相同:修饰的方法都只能在本类中被重载,不能被子类重写。

不同:

含义不同:static表示该成员要随类加载而加载。final表示该成员不可被修改。

修饰范围不同:static可修饰属性、方法、初始化块、静态内部类,不可修饰外部类、构造方法、非静态内部类。final可修饰属性、方法、类,不可修饰初始化块、构造方法。

abstract

可以修饰类和方法,但不能用来修饰属性,也不能修饰构造方法,也不能同final和static连接使用,也不能和private连用。

抽象类中可以没有抽象方法,但包含了抽象方法的类必须被定义为抽象类。 如果子类没有实现父类中所有的抽象方法,那么子类也必须被定义为抽象类。

抽象类中可以有构造方法,创建子类的实例时可能会调用这些构造方法。

抽象方法不能被static修饰符修饰。因为static修饰的方法随类的加载而加载,而此时抽象类没有方法体。

抽象类及抽象方法不能被final修饰符修饰。因为抽象类允许创建其子类实现抽象方法,而用final修饰的类不允许拥有子类。

UML类图

简介

在UML中,类使用包含类名、属性和操作且带有分隔线的长方形来表示,类图分为三层。

第一层是类的名称,如果是抽象类或接口,就用斜体表示,其中接口名称的上部会用<<interface>>修饰。

第二层是类的成员变量,通常是字段和属性。表示方式为: 可见性 名称:类型 [ = 缺省值 ] 。

第三层是类的成员方法。表示方式为: 可见性 名称(参数列表) [ : 返回类型] 。

类的成员变量和成员方法的修饰符分为+、#、-,分别表示public、protected、private。

类之间的关系

类之间的关系有实现(Realize),泛化(Generalize),关联(Associate),聚合(Aggregate),组合(Compose),依赖(Dependency)。

其中,聚合(Aggregate),组合(Compose)属于关联(Associate),是特殊的关联(Associate)关系。

关系强度(耦合度)由高到低为:泛化=实现>组合>聚合>关联>依赖。

实现(Realize)

关系:用来表示类与接口、抽象类与接口之间的关系。

箭头:用空心三角形+虚线表示,箭头指向接口。

泛化(Generalize)

关系:泛化是一种继承关系,用来表示类与类、类与抽象类、抽象类与抽象类、接口与接口之间的关系。

箭头:用空心三角形+实线表示,箭头指向父类或父接口。

关联(Associate)

关系:关联可以是双向的,也可以是单向的;关联关系可以进一步划分为聚合及组合关系。

箭头:用实线箭头表示,双向的关联可以有两个箭头或者没有箭头,单向的关联有一个箭头。

聚合(Aggregate)

关系:聚合用来表示整体与部分的关系,是一种弱的关联关系,体现为A可以包含B,但B不一定是A的一部分。

箭头:用空心的菱形+实线箭头表示,菱形指向整体。

组合(Compose)

关系:组合用来表示整体与部分的关系,是一种强的关联关系,体现了严格的整体和部分的关系,整体和部分的生命周期一样。

箭头:用实心的菱形+实线箭头表示,菱形指向整体。

依赖(Dependency)

关系:依赖用来表示两者之间的依从关系。

箭线:用虚线箭头表示,箭头指向被依赖的对象。

完整的关系图

内容来源于网络如有侵权请私信删除
你还没有登录,请先登录注册
  • 还没有人评论,欢迎说说您的想法!

相关课程