面向对象程序设计概述:
面向对象程序设计:OOP
算法+数据结构=程序,在面向过程的程序中,算法是第一位的,数据结构是第二位的。但在OOP中,将数据放在第一位,然后再考虑操作数据的算法。
对于一些规模较小的问题,将其分解为面向过程的开发方式比较理想,OOP适合解决规模更多的问题。
类:
类介绍:
类是构造对象的模板,由类构造(construct)对象的过程称为创建类的实例(instance)。
封装:
从形式上看,封装就是将数据和行为组合在一个包中,并对对象的使用者隐藏具体的实现方式。
对象中的数据称为实例字段,操作数据的过程称为方法。
实现封装的关键在于不能让类中的方法直接访问其他类的实例字段。程序只能通过对象的方法与对象数据进行交互。封装给对象赋予了黑盒特征,这是提高重用性和可靠性的关键。
继承:
可以通过拓展其他类来构建新类。在拓展一个已有的类时,这个拓展后的新类具有被拓展的类的全部属性和方法。只需要在新类中提供使用与这个新类的新方法和数据字段即可。
类之间的关系:
依赖:
最常见的关系。如果一个类的方法使用或操纵另一个类的对象,就说一个类依赖于另一个类。
应当尽可能地将相互依赖的类减至最少。
原理:如果类A不知道类B的存在,那么它就不会关心B的任何改变(即B的改变对A没有影响)。
即尽可能减少类之间的耦合。
聚合:has-a。类A的对象包含类B 的对象
继承:is-a。
例:使用Data类
用户自定义类:
关键字private确保只有Employee类自身的方法能够访问这些实例字段,如果将字段标记为public,完全破坏了封装。
构造器:
构造器的重载:
重载:多个方法有相同的名字,不同的参数。java允许重载任何方法。
当有方法重载时,编译器会方法首部的参数类型与方法调用中的值类型进行匹配,来选出正确的方法。
因为重载的方法函数名相同,所以如果要描述一个方法,需要指定方法名以及参数类型,这叫做方法的签名。
返回类型不是方法签名的一部分,不能有两个名字相同,参数类型也相同却有不同返回类型的方法。
默认字段初始化:
如果在构造器中没有显示地为字段设置初值,那么就会被自动赋为默认值:数值为0,布尔值为false,对象引用为null。(不推荐使用)
与字段不同,方法中的局部变量必须明确初始化。
无参构造器:
由无参数的构造器创建对象时,对象的状态会设置为适当的默认值
如果一个类没有编写构造器,就会提供一个无参构造器,将所有字段设为默认值。
如果类中提供了至少一个构造器,就不会提供无参构造器。如果想用无参构造器,就必须重写一个。
显示字段初始化:
可以在类定义中直接为任何字段赋值
如果一个类的所有构造器都希望把某个特定的实例字段设置为同一个值,这个语法就很有用。
可以使用方法调用初始化一个字段:
构造方法的参数命名:
调用另一个构造器:
如果构造器的第一个语句形如this(...),这个构造器将调用同一个类的另一个构造器。
这样公共的构造器只需要编写一次即可。
var声明局部变量:
如果可以从变量的初始值推导它们的类型,那么可以用var关键字声明局部变量,而无须指定类型。
不过不会对数值类型使用var
使用null引用:
对象变量可以是一个对象的引用,也可以是null,表示没有引用任何变量。
如果对null值的对象变量使用方法,会产生一个NullPointerException异常
解决方法:
把null参数转换为一个适当的非null值。
拒绝null参数:
API:
隐式参数:
封装的优点:
封装指的是将数据字段设为私有,外部不可以访问,然后定义一个公共的字段访问器和更改器方法,外部只能通过调用方法接口来访问这个类。
这样可以:如果改变内部的数据字段,除了该类的方法的之外,不会影响到其他代码(减少依赖,减少耦合性)
基于类的访问权限:
(1)方法可以访问调用这个方法的对象的私有数据
(2)方法可以访问所属类的所有对象的私有数据
私有方法:
如果将功能A的方法分解为若干个独立的辅助方法,通常这些辅助方法不应该成为公共接口的一部分。可以将这样的方法设为私有。
final字段:
可以将实例字段定义为final,这样的字段必须在构造对象时初始化,即确保在每一个构造器之后,这个字段的值已经设置,并且以后不能再修改这个字段。
final修饰基本类型的变量后就是常量。
final修饰一个类后类就变为不可变的类。(如果类中的所有方法都不会改变其对象,这样的对象就是不可变类)
final关键字只是表示存储在evaluations变量中的对象引用不会再指示一个另一个不同的对象。但是这个对象还是可以改变的。
常量基本类型值不可变
???
静态字段
将一个字段定义为static,这样的字段叫静态字段,定义静态字段后每个类只有一个静态字段,即所有类的实例共享一个字段。静态字段属于类,不属于任何单个对象。
静态常量:
静态方法:
静态方法是不在对象上执行的方法,即静态方法没有隐式参数this。
静态方法只能访问类的静态字段,不能访问非静态字段。
可以使用对象调用静态方法,但是推荐使用类名调用静态方法,因为静态方法和对象毫无关系。
使用静态方法的两种情况:
(1)方法不需要访问对象字段,方法所有参数都通过显示参数提供。
(2)方法只需要访问类的静态字段。
静态工厂方法:
使用静态工厂方法可以构造对象。
静态工厂方法:不通过 new,而是用一个静态方法来对外提供类实例的方法
main方法:
main方法是一个静态方法。main方法不对任何对象进行操作,main方法常用于测试。
方法参数:
java中方法接受的是调用者的值(按值调用),而不是变量地址(按引用调用)。
对用按值调用的理解:
对于java不是按引用调用的理解:
结论:java传入的的是参数的值而不是参数的地址(按值调用而不是按引用调用)
总结:
方法不能修改基本类型的参数
方法可以改变对象参数的状态
方法不能让对象参数引用一个新的对象
初始化块:
前面讲过两种初始化数据字段:构造器和显示赋值。
java还有第三种机制,称为初始化块。在一个类的声明中,可以包含任意多个代码块。只要构造对象,这些块就会被执行。(这种机制不常见)
首先运行初始化块,然后才运行构造器的主体部分。
调用构造器的具体处理步骤:
如果构造器的第一行调用了另一个构造器,则基于所提供的参数执行第二个构造器。
否则,所有数据字段初始化为默认值并按照在类声明中出现的顺序,执行所有字段初始化方法和初始化块。
然后,执行构造器主体代码。
初始化静态字段,可以用显示赋值的方式
如果类的静态字段需要很复杂的初始化代码,那么可以使用静态初始化块
在类第一次加载的时候,将会进行静态字段的初始化。如果没有显示设置为其他值,那么使用默认值。所有静态字段的初始化方法以及静态初始化块都将依照类声明中出现的顺序执行。
对象析构:
c++中有显示的析构器方法,放置一些当对象不再使用时需要执行的清理代码。
java会完成自动的垃圾回收,不需要人工回收内存,所以java不支持析构器。
如果对象使用了内存之外的其他资源,当资源不再需要时,应当提供一个close方法完成必要的清理工作。
包:
java允许使用包(package)将类组织在一个集合中。
包名:
使用包的主要原因是确保类名的唯一性。两个同名的类放在不同的包中不会产生冲突。
为了保证包名的绝对唯一性,用一个因特网域名以逆序形式作为包名。
从编译器角度来看,嵌套的包之间没有任何关系,如java.util与java.util.jar毫无关系。每一个包都是独立的类集合。
类的导入:
静态导入:
import static xxx运行导入静态方法和静态字段。
在包中增加类:
如果想要将类放入包中,就必须将包的名字放在源文件的开头,即放在定义这个包各个类的代码之前。
包访问访问权限:
标记为public的部分可用由任意类使用,标记为private的部分只能由定义它们的类使用,如果没有指定public或private,可用被同一个包中的所有方法访问。
Jar文件:
一个jar文件既可以包含类文件,也可以包含如图像和声音等其他类型的文件。
jar文件是压缩的,使用zip压缩格式。
文档注释:
javadoc文档是由源文件生成一个html文档,以/**开始的注释可以生成该文档。
优点:这样将代码和注释放在一个地方,由于文档注释和源代码在同一个文件中,在修改源代码的同时,重新运行javadoc,就可以保持两者的一致性。