第二部分 类与对象
众所周知,“xxx是一门面向对象的编程语言”这句话折磨了许多初学面向对象的同学们(总之包括而我),因此,虽然这个说法非常不负责并且非常有问题,但是我需要直接了当的说:面向对象不就是结构体+函数吗(当然不是)
I 面向对象中java与C++的区别
事实上,Java作为一个摒弃了指针的语言来讲,面向对象这部分与C++有着显著的不同,比如说在对象实例化的部分:
1 | Date birthday; // java:实例化一个Date对象,对象名称为birthday |
并不只是面向对象这部分,Java中的变量并没有进行赋值,而是一个变量指向了一个数据,由此可见,与其说Java是摒弃了指针的语言,不如说是全程都在用(简化版的)指针的语言(真香啊
在面向对象的程序中,应该尽量避免一个方法能够修改对象属性,甚至是直接访问对象属性,这都是不安全的,因此java类的设计通常有以下指定功能的方法:
- 构造器:最朴实无华的构造器,简单粗暴的new一个新对象,传统中的传统
- 静态工厂的构造器:不使用传统的构造器构造对象,而是使用这种特殊的方法(接口)构造一个新对象并且作为返回值可以赋值给对象变量
- 更改器:看似是修改了对象的属性,其实是返回了一个属性不一样的新对象
- 访问器:只访问对象而不修改对象的方法被称为访问器
听起来似乎花里胡哨,但本质上他们都是一个类/对象的方法罢了,只不过是人们根据他们的功能或特性起了一个(听起来很高端的)新名字,下面这个程序案例可以充分展示上述中三个新方法的使用:
1 | package MyJava; |
使用这些类,接口和方法,可以轻松处理日历的很麻烦的问题(尤其是不用考虑一大堆边界条件,因为大犇们已经提前造好轮子了),
II 用户自定义类
与c++结构类似,其区别第一在于java的各种属性与方法有着很长的前缀,其二在于java在声明方法的时候定义方法。不过,前者只是将C++的访问权限展开罗列,后者将每个类定义在一个java文件中,所以综上所述java的自定义类和C++结构依然相似。
1 | //一个最简单的java类定义 |
为了防止域值(对象的属性)出错或者随意修改,应该在针对一个属性拥有以下三个内容:
- 一个私有的数据域
- 一个公有的域访问器的方法
- 一个公有的域更改器的方法
这样有很多好处,一是内部实现不会影响其他代码,二是更改其可以执行错误检查
同时为了防止数据域的出错,在需要返回一个可变对象的时候需要进行克隆:
1 | class OutPut |
III 静态域与静态方法
静态前缀修饰符static即将变量的作用域设置为静态,这个修饰符可以作用于以下内容:
- 静态域:
将成员属性设置为静态,即类中所有对象都公用一个的属性,在其他面向对象的语言中也会将其称为“类域”,对于静态域的使用有以下经典用法:
1 | class Employee |
- 静态常量
即在常量中用static修饰,最经典的例子就是在Math类中的静态常量PI。
静态常量因为不能被修改,所以设置成公有也是没有问题的。
- 静态方法
静态方法是一种不能对对象实施操作的方法,也就是没有this参数的方法,例如,Math终端pow方法,在使用时不许呀哦任何Math对象。
虽然静态方法不能访问实例域,但是可以访问静态域,也可以通过类名待用这个方法。
- 静态工厂
类似LocalDate和NumberFormat的类使用静态工厂方法来构建对象,以NumberFormat为例,不使用构造器有以下两点原因:
一方面构造器的名字必须与类名相同,而实际希望将得到两种不同的名字
另一方面使用构造器时无法改变所构造的对象类型,而Factory方法将返回一个DecimalFormat类的对象,也就是NumberFormat的子类。
- main方法
调用静态方法不需要对象,同理。main方法也是一个静态方法,main函数不需要对任何对象进行操作。
事实上,程序启动的时候没有任何一个对象,静态的main方法将执行并创建程序所需要的对象。
注: 每一个类都可以有一个main方法,常用于对类进行单元测试
- 声明时赋值与初始化块
虽然java可以使用常规的构造器初始化数据域,与C++不同,java可以在类声明属性的时候就对其进行初始化,除此之华还有“初始化块”这个第三种机制,只要构造类的对象,这些块就会被执行,对于静态域进行初始化的初始化块可以在花括号前单独加一个static前缀
类中调用构造器的顺序为:
数据域初始化为默认值 -> 按照声明中出现的次序执行初始化块 -> 若构造器中有其他构造器,先执行内部构造器,再执行外部构造器
IV 包
包是java中管理类的容器,一个类可以使用所属包中的所有类,以及其他包中的公有类,我们可以有两种方法访问其他包中的类:
1 | //第一种方法 显然比较繁琐 |
如果在包的目录中没有对应的类,也可以进行编译,但是最终程序无法正常运行,因此需要先将所有类文件移到正确的位置上。
除此之外,类文件也可以存储在JAR文件中,JAR文件可以理解为Java归档的ZIP格式组织文件,JDK提供了许多JAR文件的类库,同时JAR文件也方便其他第三方库的使用。