第4章:面向对象编程(上)
1、面向过程与面向对象
面向过程编程(POP,Procedure Oriented Programming):强调的是功能行为,以函数为最小单位,考虑怎么去做。
面向对象编程(OOP,Object Oriented Programming):强调具备了功能的对象,以类/对象为最小单位,考虑谁去做。
举例:人将大象装入到冰箱中去
面向过程编程:
(1)把冰箱门打开
(2)抬起大象,塞进冰箱
(3)把冰箱门关闭
面向对象编程:
可以分为三个对象,分别是冰箱,大象,人。
人{
//类中的方法
打开(冰箱){
//调用冰箱类的方法
冰箱.开开();
}
抬起(大象){
大象.进入(冰箱);
}
关闭(冰箱){
冰箱.闭合();
}
}
冰箱{
开开(){开开的细节};
闭合(){闭合的细节};
}
大象{
进入(){进入的细节};
}
面向过程的语音和面向对象的语言的区别解析:
从设计思想来看,面向对象高于面向过程,更有利于后续的扩展(只需要对某个对象增加新的功能即可)。程序员从面向过程的执行者转化成了面向对象的指挥者。
面向过程的语言:只需要将一件事的过程用程序化的语言描述出来就可以了,第一部怎么做,第二步怎么做,没有拓展性。
面向对象的语言:描述的并不是过程,是哪一个对象可以做这件事,调用这个对象的方式实现这个过程,后期需要扩展完全可以在这个对象中添加相应的功能,具有良好的扩展性。真正的面向对象,任何的函数和变量都是以类封装去起来的。
对于面向过程的语言具有开发效率慢,但执行效率快的特点,对于面向对象的语言则是开发效率快,但执行效率慢的特点。
面向对象分析方法分析问题的思路和步骤:
a、根据问题需要,选择问题所针对的现实世界中的实体。
b、从从实体中寻找解决问题相关的属性和功能,这些属性和功能就形成了概念世界中的类。
c、把抽象的实体用计算机语言进行描述,形成计算机世界中类的定义。即借助某种程序语言,把类 构造成计算机能够识别和处理的数据结构。
d、将类实例化成计算机世界中的对象。对象是计算机世界中解决问题的最终工具。
2、Java基本元素:类和对象
类(class):是对一类事物的描述,是抽象的,概念上的定义。

对象(object):是实际存在的该类事物的每个个体,因而也称为实例(instance)
对于面向对象程序设计的重点是类的设计,类的设计,其实就是类的成员的设计。
理解万事万物皆对象:
1、在Java语言范畴中,我们都将功能、结构等都封装到类中,然后通过类的实例化来调用具 体的功能结构。
2、涉及到Java语言与前端Html、后端的数据库交互时,前后端的结构在Java层面交互时都体 现为类、对象。
3、对象的创建和使用
属性(Field):对应类中的成员变量,也被叫为域或属性。(静态)
方法(Method):对应类中的成员方法,也被叫为函数。(动态)
创建类的对象(类的实例化,实例化类):类名 对象名 = new 类名();
调用对象的属性:对象名.属性名
调用对象的方法:对象名.方法名(参数);
对象的创建以及使用的整个过程:
a、创建类、设计类的成员(属性和方法)
b、创建类的对象
c、调用对象的结构
注:如果创建了一个类的多个对象,则每个对象都独立拥有一套类的属性(非static关键字修饰),即 如果我们修改一个对象的属性a,则不影响另外一个对象属性a的值。
内存解析:

堆(Heap):内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在堆分配内存。在Java虚拟机中描述是:所有对象实例以及数组都要在堆上分配。
栈(Stack):指虚拟机栈。虚拟机栈用于存储局部变量等。局部变量表存放了编译期可知长度的各种基本数据类型(boolean、byte、char、short、int、float、long、double)、对象引用(reference类型,它不等同于对象本身,是对象在堆中的首地址,即从栈中指向堆中的实体)。方法执行完,自动进行释放。
方法区(Method Area):用于存储已经被虚拟机加载的类的信息、常量、静态变量、即是编译器变异后的代码等数据。
我们在这里只要从堆和栈的角度信息分析:

栈中用来存放声明的局部变量对象名,对象名p1、p2、p3用来存放在堆中对象实体(new出来的)结构的首地址值(一个十六进制值)。
Person p1 = new Person():即声明一个Person类的对象实体,我们先将局部变量(main方法中的变量,方法中的变量都是局部变量)p1放入到栈中,然后在堆中创建一个Person类的对象实体,并且赋予一个首地址值,并将首地址值赋值给p1,并将对象实体中的各个属性值初始化。
p1.name = “Tom”:通过栈中存放的局部变量p1存放的首地址值找到其指向的在堆中存放的对象实体,然后修改其属性值name为Tom。
Person p3 = p1:将p1的首地址值赋值给p3的首地址值,即p3指向p1所指向的对象实体。
匿名对象的使用:
理解:
字面意思,即对象没有名称,new一个对象后,没有将其赋给某个变量。
new 变量名();
没new一次,都是新创建一个对象实体,我们可以直接调用该类中的方法
new 变量名().方法名();
特征:只能调用一次。
内存解析:在堆中有对象实体,且有首地址值,但在栈中没有遍历存放该首地址值。
4、类的成员之一:属性
属性:描述类具有的特征。
属性(成员变量) 和 局部变量:
1.相同点:
1.1 定义变量的格式是一样的:(权限修饰符) 数据类型 变量名 = 变量值;
1.2 先声明后使用
1.3 变量都有其对应的作用域(超过作用域范围就被回收,失效)
2.不同点:
2.1 在类中的声明的位置不同:
属性:直接定义在类的一对{}内,方法体外,内体内。
局部变量:声明在方法内、方法形参、代码块内、构造器形参、构造器内部的变量
2.2 关于权限修饰符的不同:
属性:可以在声明属性时,使用权限修饰符指明其权限。
局部变量:不可以使用权限修饰符的。
常用的权限修饰符:private、public、protected、缺省(即不加)
2.3 默认初始化值的情况
属性:类的属性,根据其类型,都有默认初始化值。
整型(byte、short、int、long):0
浮点型(float、double):0.0
字符序(char):0(或\u0000)
布尔型(boolean):false
引用数组类型(类、数组、接口):null
局部变量:没有默认初始化值,即我们在调用局部变量时,必须要显示赋值。
特殊的,对于形参在调用时,我们赋值即可。
2.4 在内存中加载的位置
属性:加载到堆空间中(非static)
局部变量:加载到栈空间

5、类的成员之二:方法
方法:描述类应该具有的功能。
方法的声明:

说明:
1.权限修饰符:
Java规定的4中权限修饰符:private、public、缺省、protected
2.返回值:
有返回值和没有返回值的区别:
2.1如果方法有返回值,则必须在方法声明时,指定返回值的类型,需要使用return关键字返回指定类型的变量或常量。
2.2 如果方法没有返回值,则方法声明时,使用void表示。通常,没有返回值的方法中,就不需要使用return了,但是如果使用,只能return;表示结束次方法。
3.方法名:属于标识符,遵循标识符的规则和规范,且见名知意。
4.形参列表:方法可以声明0个,1个,或多个形参。
4.1格式:数据类型1 形参1 ,数据类型2 形参2 ……
5.方法体:方法功能的实现。
6.renturn关键字:
6.1.使用范围:使用在方法体中。
6.2.作用:结束方法(无返回值);针对于有返回值类型的方法(有返回值)。
6.3 注:return关键字后面不可以声明执行语句。
7.注: 方法的使用中,可以调用当前类的属性或方法。特殊的,方法a中又调用方法a(递归)
方法的分类:根据有无返回值、有无形参

6、再谈方法
6.1 方法的重载(overload):
6.1.1 概念:在同一类中,允许存在一个以上的同名方法,只要他们的参数个数或者参数类型 不同即可。
6.1.2 重载的特点:与方法的权限修饰符、返回值类型、形参名无关,只看参数列表,且参数列表必须不同。调用的时候, 根据方法的参数列表的不同来进行区分。可以概括为:“两同一不同”:同一个类、相同方法 名,参数列表不同(参数个数不同,参数类型不同,参数排列顺序不同)。
6.1.3 确定指定的方法:先看方法名,再看参数列表。
6.2 可变形参的方法
6.2.1 概念:JavaSE 5.0中提供了Varargs(variable number of arguments)机制,允许直 接定义能和多个实参相匹配的形参。从而,可以用一种更简单的方式,来传递个数可变的形参。
6.2.2 语法格式:数据类型 ... 变量名
6.2.3 作用:当调用可变个数形参的方法时,传入的参数个数可以是:0个,1个,2个……
6.2.4 注:
(1)可变个数形参的方法与本类中方法名相同,形参不同的方法之间构成重载。如String s和String ... s 构成重载
(2)可变个数形参的方法与本类中方法名相同,形参类型也相同的数组之前不构成重载。如String[] s(使用实参new String[]{内容})和String ... s(因为在JDK5.0之前想要表示多个形参使用的就是数组的方式,其实两者是一样的,尤其是遍历可变形参的时候和遍历数组是一样的方式)。
(3)可变个数形参在方法的形参中,必须声明在末尾
(4)可变个数形参在方法的形参中,最多只能声明一个可变形参。
6.3 方法参数的值传递机制:
6.3.1 关于变量的赋值:
如果变量是基本数据类型,此时赋值的是变量所保存的数据值。
如果变量是引用数据类型,此时赋值的是变量所保存的数据的地址值。
6.3.2 概念:
形参:方法定义时,声明的小括号内的参数
实参:方法调用时,实际传递给形参的数据
6.3.3 值传递机制:
如果参数是基本数据类型,此时实参赋给形参的是实参真实存储的数据值。
如果参数是引用数据类型,此时实参赋给形参的是实参存储数据的地址值。
6.4 递归方法:
6.4.1 递归(recursion)概念:一个方法体内调用自身,形成一种有限制的循环。方法递归包 含一种隐式的循环,它会重复执行某段代码,但这种重复执行无须循环控制。递归一定要向已 知方向递归,否则这种递归就变成了无穷递归,类似于死循环。
7、OOP特征一:封装与隐藏
7.1程序设计追求“高内聚,低耦合”:
高内聚:类的内部数据操作细节自己完成,不允许外部干涉。
低耦合:仅对外暴露少量的方法用于使用。
7.2 引入: 当我们创建一个类的对象以后,可以通过对象.属性的方式,对该对象属性进行赋值。这 里,赋值操作要受到属性的数据类型和存储范围的制约。除此之外,没有其他制约条件。但在实际问 题中,我们往往要给属性赋值加入额外的限制条件。这个条件不能在属性声明中体现,只能通过方法 进行限制条件的添加。同时,我们要避免用户再使用通过对象.属性的方式对属性进行赋值,则需要 将该属性声明为私有的(private)。此时针对于属性,就体现了封装性。
对引入的举例:我们此时有一个类,为动物类。里面有姓名属性,和脚属性。如果我们按照之前 的思路,用户能够直接通过对象.属性的方式对姓名和脚属性进行赋值。那么用户可能会出现对脚赋 值的时候出现负数的情况,那么这肯定是不合理的。因此,为了避免这种情况,我们要对脚属性进行 封装,我们建立一个方法,用户通过该方法对脚属性进行赋值。如果赋值的脚小于0,则抛出异常, 反之,则将用户输入的值赋值给脚属性,并且,我们将脚属性的权限修饰符设定为private,使得用 户无法直接对其进行赋值,将其私有化,这样就实现了对脚属性的封装。
代码: public void setLegs(int x)legs = x;
7.3 封装性的体现: 我们将类私有化(private),同时,提供公共的(public)方法来获取(getXxx) 和设置(setXxx)此属性的方法。(封装线体现之一,不等同于封装线本身)
扩展:1、如上 2、不对外暴露的私有的方法 3、单例模式
7.4 权限修饰符(封装线的体现,需要权限修饰符来配合)
7.4.1 Java规定的4种权限(从小到大排序):
private、缺省(default)、protected、public

4种结构可以用来修饰类及类的内部结构:属性、方法、构造器、内部类。
4种权限都可以用来修饰类的内部结构。
只能使用缺省和public修饰一个类。
7.5 总结封装性:Java提供了4种权限修饰符来修饰类及类的内部结构,体现类及类的内部结构在 被调用时的可见性的大小。
8、类的成员之三:构造器(构造方法,constructor)
8.1构造器的作用:1、创建对象,创建类的对象:new + 构造器; 2、初始化对象的信息;
8.2说明:
8.2.1:如果没有显示的定义类的构造器的话,则系统默认提供一个空参的构造器。
8.2.2:定义构造器的格式:权限修饰符 类名(形参类别){}
8.2.3:一个类中定义的多个构造器,彼此构成重载。
8.2.4:一旦我们显示的定义类的构造器之后,系统不再提供默认的空参构造器。
8.2.5:一个类中,至少会有一个构造器。
8.3特征:
它具有与类相同的名称
它不声明返回值类型。(与声明为void不同)
不能被static、final、synchronized、abstract、native修饰,不能有
return语句返回值
8.4 属性赋值的过程:
1、默认初始化
2、显示初始化
3、构造器中初始化
4、通过对象.方法或对象.属性的方式赋值
以上操作的先后顺序:1、2、3、4
1、2、3在对象实例化之前进行,只执行一次,4在对象实例化后,可以执行多次。
8.5 JavaBean:
8.5.1 概念:JavaBean是一种java语言写成的可重用的组件。
8.5.2 符合条件:
是一个类,且类是公共的(public)
有一个无参的公共的构造器
有属性,且有对应的get、set方法。
8.5.3 作用:
用户可以使用JavaBean将功能、处理、值、数据库访问和其他任何可以用Java代码创造的对象进行打包,并且其他的开发者可以通过内部的JSP页面、Servlet、其他JavaBean、applet程序或者应用来使用这些对象。用户可以认为JavaBean提供了一种随时随地的复制和粘贴的功能,而不用关心任何改变。
8.5.4 UML图:

9、关键字:this
9.1 作用:可以用来修饰、调用:属性、方法、构造器
9.2 this 修饰属性和方法:
this理解为:当前实例化的对象,或当前正在创建的对象。
在类的方法中,我们可以使用this.属性和this.方法的方式,调用当前对象属性和方法。但是通常情况下,我们都省略this.。特殊的,如果,方法的形参和类的属性同名时,我们必须显式地使用“this.变量”的方式,表明此变量是属性,而非形参。
在类的构造器中,我们可以使用this.属性和this.方法的方式,调用当前正在创建的对象属性和方法。但是通常情况下,我们都省略this.。特殊的,如果,构造器的形参和类的属性同名时,我们必须显式地使用“this.变量”的方式,表明此变量是属性,而非形参。
9.3 this调用构造器:
9.3.1 我们在类的构造器中,可以显示地使用“this(形参列表)”方式,调用指定的类的其 他构造器。
9.3.2 构造器中不能通过“this(形参列表)”的方式调用自己,这样会出现递归死循环。
9.3.3 如果一个类中有n个构造器,则最多有n-1个构造器中使用了“this(形参列表)”, 否则会出现闭环,造成死循环。
9.3.4规定:“this(形参列表)”必须声明在当前构造器中的首行。
9.3.5构造器内部,最多只能声明一个“this(形参列表)”的方式去调用其他构造器。
10、关键字:package、import
10.1 package关键字:
10.1.1 引入:为了更好的实现项目中类的管理,提供了包的概念。package语句作为Java源文 件的第一条语句,指明该文件中定义的类所在的包。(若缺省该语句,则指定为无名包)
10.1.2 格式: package 顶层包名.子包名;
10.1.3 使用说明:
(1)使用package声明类或接口所属的包,声明在源文件的首行。
(2)包,属于标识符,遵循标识符命名规则、规范(小写单词标识,xxxyyyzzz),且要见名 知意。
(3)每“ .”一次,就代表一层文件目录,通过”.”指明包(目录)的层次。
10.1.4 作用:
(1)包帮助管理大型软件系统:将功能相近的类划分到同一个包中。比如:MVC的设计模式
(2)包可以包含类和子包,划分项目层次,便于管理
(3)解决类命名冲突的问题
(4)控制访问权限
10.1.5 补充:
(1)同一个包下,不能命名同名的接口和类;不同的包下,可以命名同名的接口、类。
10.1.6 一些包的举例:

10.2 MVC设计模式:


10.3 import关键字:
10.3.1 import(导入)作用:
(1)在源文件中显示地使用import结构,导入指定包下的类、接口。
(2)声明位置:声明在包的声明和类的声明之间。
(3)如果需要导入多个接口满则并列写出即可。
(4)可以使用”xxx.”的方式表示可以导入xxx包下的所有结构
(5)如果使用的类或接口是java.lang包下定义的或是本包下定义的,则可以省略import 结构。
(6)如果在源文件中,使用了不同包下的同名的类,则必须至少有一个类需要以全类名 的方式进行显示(包名.类名)
(7)使用”xxx.”的方式表示可以导入xxx包下的所有结构,但是如果使用的xxx子包 下的结构,则仍需要显示导入。
(9)import static xxx.*:导入指定类或接口中的静态结构:属性或方法。

浙公网安备 33010602011771号