大家好,我叫何先振。这期接着给大家讲Java的面向对象内容,本期是建立在上讲的基础上,对Java面向对象做基础串讲。如果没有看上期的内容,建议先看上期的内容。
一.方法的重载
1.什么是方法的重载:
在同一个类中,允许存在一个以上的同名方法,只要它们的参数个数或者参数类型不同即可。如图:这个Student类中可以指定两个相同的方法,形参数列表不同,可以叫方法的重载。
2.方法重载的作用:
可以让同一个方法兼容不同的形参列表,实现相同的功能。比如Arrays工具类,提供了sort排序的方法,可以对byte类型排序,也可以对int类型排序,就是因为他们方法名相同,形参列表的数据类型或者个数不同。
3.如何判断是否是方法的重载?
两同一不同:同一个类,相同方法名。参数列表不同:可以包括参数个数不同,参数类型按顺序来不同。
跟方法的权限修饰符、返回值类型、形参变量名、方法体都没有关系。
有了重载之后,我们在通过对象调用方法时,如何确定某个指定的方法?
可以先看方法名,如果有相同方法名,看形参列表。(因为有重载,所以单看方法名无法确定唯一的方法,必须方法名和形参列表一起看,才能确定指定的方法)。
二.可变形参的方法
从jdk5.0开始,当一个方法的形参列表的参数个数不确定时,我们可以使用可变个数形参的写法。可变个数形参的的格式:"数据类型 ... 变量名"。
当调用可变个数形参的方法时,传入的参数个数可以是:0个,1个,多个。但是要求必须都是可变个数形参所指定的数据类型。如图:必须都是传String类型。
可变个数形参的方法也可以与本类中方法名相同、形参列表不同的方法,构成重载。如图:
可变个数形参的方法与本类中方法名相同、形参列表个数相同但形参类型是数组的方法不能构成重载,二者都是一样,不能共存。
可变个数形参,在方法的形参列表中,必须声明在末尾。
如果放在前面,编译器识别不了你前面的实参,是给可变个数形参,还是给后面的形参,就会报错。
可变个数形参在方法的形参中,最多只能够声明一个,并且多个形参时,必须放在最后。
三.方法参数的值传递机制
1.关于变量的赋值
如果变量是基本数据类型,此时赋值的是变量所保存的数据值。
如果变量是引用数据类型,此时赋值的是对象所保存数据的地址值。如图:stu1和stu2赋值后有相同的地址值,这两个变量共同指向同一个对象。对象属性变了,两个变量都可以访问到改变后的对象属性。
这两种不同的赋值特点,是如何在方法中提现的。下面我们就开始讲。
2.方法中的值传递机制
形参:方法定义时,声明小括号内的参数。
实参:方法调用时,实际给方法中形参传递的数据。
如果参数是基本数据类型,此时实参赋给形参的是实参真实存储的数据值。
如果参数是引用数据类型,此时实参赋给形参的是实参所保存的数据的地址值。
四.递归方法
1.什么是递归:
一个方法体内调用自身方法。
方法的递归包含了一个隐式的循环,它会重复的执行某段代码,但是这种循环执行起来,无须循环控制。
递归一定要向已知的方向递归,否则这种递归就变成了无穷递归,类似于死循环。
2.递归的例子:
例如求1-100之和,前n位数的和,等于n-1位数的和+n。也就是f(n)=f(n-1)+n。
例如求斐波那契数列时第n位的值,斐波那契数列数列的第n位等于后两位的和。也就是f(n)=f(n-1)+f(n-2)。
3.递归的总结:
当n前面的数跟n位数有某种关系时,我们可以使用递归。使用递归必须要有递归的结束条件。否则就是无穷递归。
五.封装与隐藏
面向对象的特征之一,就是可以封装和隐藏。
什么是封装?我们在洗衣机的时候,只需要把衣服丢进去,按下按钮,就可以开始帮你洗衣服。我们没必要知道洗衣机的结构。我们程序设计也一样,要追求高内聚,低耦合。
高内聚:类的内部数据操作细节自己完成,不需要外部干预。低耦合:只对外暴露少量的方法使用。
隐藏对象内部的复杂性,就像洗衣机的内部结构很复杂,怎么洗我们的衣服外部是看不到的。
对象只提供公开简单的接口,便于外界调用。就像洗衣机提供了按钮,只需要把衣服丢进去,按下开始按钮,就可以完成洗衣服的操作。
总的来讲,就是把我这个对象的功能实现细节全部隐藏起来,只暴露简单的可以实现这个功能的入口给外界。这样我实现这个功能的细节,跟外界没有关系,达到了低耦合,同时内部全是我实现的细节,这也就是高聚合,这就是封装的设计思想。
如下图,现在是外界可以随意修改一个对象中的属性,并且把属性的值修改了不合理的负数,而且外界可以通过"对象.属性"的方式来获取对象的属性。这就违背了我们封装和隐藏的设计理念。
在实际问题中,我们外界给对象赋值属性,对象需要限制外界输入属性值的合理性。比如动物类年龄不可能是负数,腿的个数不能也是负数。因此我们需要把我们的属性隐藏起来,Java提供了关键字可以隐藏我们的属性。
如图:加上private私有的,这个属性只能在我内部被访问,外部没有权限访问,如果访问的话就会报错。
然后我们对象提供设置属性的方法,将给对象属性赋值的过程封装在方法里面。
让外部去调用方法进行设置属性,运行程序打印对象的属性赋值结果。
以上就是属性的封装,将对象的属性赋值过程封装到对象内部,外界只需要调用属性赋值的方法就可以了。这样可以大大提高程序的扩展性,可维护性。如果需要扩展功能,加上限制属性的值合理,我们只需要在方法中加代码,封装成一个方法,方便管理,提高了可维护性。
六.封装的体现
我们将类的属性私有化(private),同时,提供公共的(public)方法来设置(set)属性,或者获取(get)属性,这种就是封装的一种体现。
除了这种属性的封装体现,还有方法的封装体现,我们也可以在方法上加private,提供一些对象内部才能使用的方法,给公共的方法使用。
七.权限修饰符
上面讲的封装性体现,都需要使用到权限修饰符。Java规定的四种权限,从小到大排列:private、缺省(什么也不写)、protected、public。
1.四种权限的范围:
private,只限类内部可以访问。
缺省,同一个包下(不包括子类包)都可以访问。
protected,同一个包下和不同的子类包。
public,同一个工程下都可以访问。
2.权限修饰符的作用:
可以用来修饰类以及类的内部结构:属性、类的方法、构造器、内部类。
具体的四种权限,都可以用来修饰类的内部结构:方法、属性、构造器、内部类。如果修饰类的话,只能用public、缺省。同包不同类可以访问缺省、public、protected三种。
不同包下,只有公共的可以,protected后面我们讲了子类再讲。
八.构造器constructor
1.作用:
创建对象:“new+构造器”的写法。初始化对象的属性。
2.用法:
如果没有显式的定义类的构造器的话,则系统默认提供一个默认空参的构造器,提供的默认构造器的权限修饰符跟类的权限修饰符相同,如果你的类是缺省的,那么系统默认提供的也是缺省的。
定义构造器的格式:权限修饰符 类名(形参列表){}
类中可以定义多个构造器,彼此构成重载。
一旦我们显式的定义了类的构造器之后,系统就不再提供默认的空参构造器。如图:我们把构造器注释掉之后,因为我们还定义了其他构造器,所以系统不提供默认的空参构造器,所以上面就报错了。
因此我们知道,一个类中至少会有一个构造器。
九.属性赋值的顺序
1.默认初始化
2.显式初始化
3.构造器初始化
4.set方法赋值,可以反复执行
一个对象的属性取值多少主要是从后往前看,先看有没有set赋值,然后构造初始化赋值、在看显式初始化赋值、最后默认初始化赋值。
十.JavaBean的使用
1.什么是JavaBean:
用Java语言写的可重用的组件。
2.特点:
一个public公共的类;至少有一个无参数的构造器;有属性,且有对应的get和set 方法。
3.例子:
Customer客户类,包含了属性、构造器、属性对应的get和set方法。
JavaBean的功能就是可以存数据并且复用这些数据,以后我们会讲JavaWeb的时候,数据库中的数据如何展示到页面,就是通过将数据库中的数据存到JavaBean中,然后给别人调用,展示到页面。从而用户可以在网页上看到数据。这个以后我们会讲到。
十一.UML类图的介绍
banking包名,+代表public,-代表private,#Protected,属性的写法:-/+ 属性名:属性的类型,方法的写法:+/- 方法名(形参名:形参类型):返回值类型。
程序设计时,我们会通过UML类图,提前设计好类的成员。这样我们开发时,就按照设计的类图来进行开发。大大提高我们的开发效率。
十二.关键字this的使用
this可以用来修饰属性、方法、构造器。
1.修饰属性、方法
this理解为当前对象。
在类的方法中,我们可以使用this.属性或者this.方法,来调用当前对象的属性和方法,通常情况下我们都选择省略this. ,但是如果方法的形参和属性同名了,我们必须使用this.变量的方式,表名此变量是属性,而非形参。
如图:形参也为name,属性也为name,为了解决冲突,所以用this.name来表明这是个属性。
如图:当this.sleep()方法,代表调用当前对象的方法,通常可以省略this,直接写sleep()。
2.修饰构造器
this可以理解为当前正在创建的对象。
在类的构造器中,我们可以使用this.属性或者this.方法,来调用当前正在创建对象的属性和方法,通常情况下我们都选择省略this. ,但是如果构造器的形参和属性同名了,我们必须使用this.变量的方式,表名此变量是属性,而非形参。
如图:有参构造器,形参列表和属性同名,所以需要用this.age表明是属性,而非形参。
如图:如果在构造器中调用了方法,this.sleep()表示调用当前正在创建对象的方法。也可以省略this。
this调用构造器,我们在类的构造中,可以显式的使用"this(形参列表)",调用本类中指定的其他构造器。这样就可以调用其他构造器的逻辑代码了。避免了要写其他构造器存在的代码。
构造器中不能通过"this(形参列表)"调用自己。这样就形成了递归,类似死循环。
如果一个类中有n个构造器,最多有n-1个构造器使用了"this(形参列表)",因为最后一个如果调用了任何一个,就形成了一个环,也会出现递归,类似死循环。如图:不能互相调用。
如图:3个构造器,最多只能用2次这种方式。
规定,"this(形参列表)"必须声明在当前构造器的首行。如果不放在首行就会报错。如图:放在第二行就会报错,必须在首行。
构造器内部,最多只能声明一个"this(形参列表)",用来调用其他的构造器。如图:构造器2不能又调构造器1和构造器2,因为调用其他构造器必须放在首行,第二行就会报错,只能调一个。
十三.关键字package的使用
1.作用和用法:
为了更好的实现项目中类的管理,提供了包的概念。使用package声明类或者接口所属的包,声明在源文件的首行。
包属于标识符,需要遵循标识符的命名规则、规范(xxxyyyzzz)、“见名知意”。每"."一次,就代表一层文件目录。
补充:同一个包下,不能命名同名的接口、类。不同的包下,可以命名同名的接口、类。
2.Java中的JDK提供了一些主要的包:
Java.lang包,包含了一些Java语言的核心类:如String、Math、Integer、System和Thread提供常用功能。
java.net包,包含执行与网络相关的操作的类和接口。
java.io包,包含能提供多种输入和输出功能的类。
java.util包,包含了一些工具类,如定义系统特性、接口的集合框架类、使用与日期日历相关的函数。
java.text包,包含了一些Java格式相关的类。
java.sql包,包含了一些Java进行JDBKC的数据库编程的相关类/接口。
java.awt包,包含了抽象窗口的工具集的多个类,这些类被用来构建和管理应用程序的图形用户界面(UGI)。B/S模式,C/S模式都有。
十四.MVC设计模式
MVC是常用的设计模式之一,将整个程序分为了三个层次:视图模型层、控制器模型层、数据模型层。
1.M模型层 model主要处理数据,通常会定义如下的包:
数据对象封装:model.bean/domain。数据库操作类:model.dao。数据库:model.db。
2.C控制层 controller 处理业务逻辑,通常会定义如下的包:
应用界面相关 controller.activtiy。存放fragment controller.fragment。显示列表的适配器 controller.adapter。服务相关的controller.service。抽取的基类 controller.base。
3.V视图层 view 显示数据,通常会定义如下的包:
相关工具类:view.utils 自定义view:view.ui
每一层都有各自的用途,也有各自的包的命名,暂时不理解这种设计模式没有关系,后面我们都会讲到。这里我们先知道会有这种MVC的设计模式就行。
十五.关键字import的使用
import:导入
在源文件中显式的使用import结构,必须导入指定包下的类、接口。
位置:声明在package包的声明和类的声明之间。
如果需要导入多个结构,则并列写出即可。
也可以使用"xxx.*"的方式,表示可以导入xxx包下的所有结构。
如果使用的类和接口是Java.lang包定义的,则可以省略import结构。比如System、String。
如果使用的类或者接口是本包下定义的,也可以省略import结构。
如果在源文件中,使用了不同包下的同名的类,则必修至少有一个类需要以全类名的方式显示。
如果我们使用"xxx.*"的方式表明可以调用xxx包下的所有结构,但是如果使用的是xxx子包下的结构,则仍需要用import结构,显式导入。如图:Person就在test05的子包下t1,需要重新声明。
import static :导入指定类或接口的静态结构:属性或者方法。如图:导入System类的所有静态资源。这时候就可以直接用out.println()。不需要使用"System."出来
以上就是我们这期内容的介绍,学习更多Java知识请点击关注。我们用Eclipse工具,用了也有这么久了,下期让我们总结下Eclipse的快捷键,给大家使用,提高大家的开发效率。