OOP
1. 封装encapsulation
a)形式上:将对象的数据和行为组合在一个类中,对对象的使用者隐藏了数据的实现方式
b)关键:绝对不能让类中的方法直接访问其它类的数据。程序仅通过对象的方法与对象数据进行交互。
c)作用:赋予对象“黑盒”的特征,提高了对象的可重用性和可靠性。意味着哪怕一个类全面改变存储数据的方式,只要仍旧使用相同的方法操作数据,其他对象就不会知道或介意所发生的变化。
2. 对象的三个主要特性:行为behavior,状态state,标识identity
对象的状态并不能完全描述一个对象,每个对象都有一个唯一的标识???
3. 类之间的关系
n 依赖use-a:
一个类的方法操纵另一个类的对象,即一个类依赖于另一个类。
从软件工程的角度看,应该要让类之间的耦合度最小
n 聚合/关联has-a:
类A的对象包含类B的对象
n 继承:is-a:
n UML
4. 并不是所有的类都具有OOP特征,例如Math类
5. 为什么要用类描述时间,而不是使用一个内置built-in类型?普适与灵活性的矛盾
6. Java类库设计者将保存时间与时间点命名(日历)分开,Date类和Calendar类,体现了解耦的设计思想。
7. 在Java中,任何一个对象变量的值都是对存储在另一个地方的对象的引用。
new操作符的返回值也是一个引用
8. 局部变量不会自动的初始化为null,需要调用new或者将它们设置为null进行初始化
9. 构造器总是伴随着new操作符一起使用。
构造器咩有返回值
对一个已经存在的对象调用构造器会产生编译错误
不要在构造器中定义与实例域重名的局部变量,会屏蔽掉同名的实例域,且这些变量只能在构造器内部访问
所有的方法都不要命名与实例域同名的局部变量
10. 隐式参数与显式参数
1. 在每一个方法中,关键字this表示隐式参数,引用本类
2. 明显的列在方法声明中的是显式参数
11. 基于类的访问权限
方法可以访问所属类的所有对象的私有数据:other.name
12. 不要编写返回引用可变对象的访问器getter。如果需要返回一个可变对象的引用,先对其进行克隆clone
13. final实例域
n 构建对象时必须初始化final实例域。之后不可修改,即没有setter
n final修饰符大多应用于基本类型域或者不可变类的域(不可变类,例如String类)
n 当final修饰符应用于可变类的对象变量,例如:privatefinal Date hireDay;仅仅意味着hireDay变量的对象引用在对象初始化后不能改变,但任何方法都可以对hireDay引用的对象调用setTime方法
14. 静态域
每个对象对于类的实例域都有自己的一份拷贝,唯独共享了static实例域。
静态域,内存中独此一份,哪怕没有对象被创建,依然存在
所以,它属于类,不属于任何对象,也被称为类域
15. 静态常量
/* 因为有final修饰符,所以用public修饰没问题*/
public static final double PI = 2.1415926;//静态常量
public final double PI = 3.1415926;//常量
public static final PrintStream out = …;//System类的实例域
16. 静态方法
静态方法不能操作对象,因此不能访问对象的实例域,但可以访问自身类的静态域,可以认为静态方法是没有this参数的方法,使用类名来调用静态方法( 尽管对象名也可以,但容易混淆概念,因为静态方法的执行和具体对象没半毛钱关系)
以下2种情况使用静态方法:
n 一个方法只需访问类域;
n 一个方法不需要访问对象状态,其所需参数都是通过显式参数提供。例如Math.pow(double x, int a);
17. static
n 含义:属于类不属于类对象
n 说明:static关键字是从其他语言继承过来的,其实已经偏离了它本身的语义:静态的。在Java中,建议将其理解为“属于类的”。
18. 工厂方法:静态方法的神运用
含义:利用工厂方法构造不同风格的格式对象
为什么构造对象不是用构造器而是用工厂方法?
1. 构造器无法命名。我们希望能见名知意
2. 使用构造器,无法改变所构造的对象类型
19. main方法
main方法就是一个很典型的静态方法。在启动程序时,还没有任何一个对象,我们就需要依靠执行main方法来创建所需要的对象。
应用:每一个类都该有一个main方法以便执行单元测试。
20. 方法参数
n Java:call by value
n 但是,当方法参数是对象引用,而不是基本数据类型,就等价于call by reference
1. 方法参数employee的值被初始化为harry值的一个拷贝,这里是一个对象的引用
2. 方法作用于employee,employee和harry同时引用的那个Employee对象薪资*3
3. 方法结束,参数变量employee不再使用。对象变量harry仍然指向那个Employee对象
n 反例:
n 总之记住:Java:call byvalue
21. 重载overloading;重载解析overloadingresolution:参数类型-值类型匹配,编译器负责;方法签名signature;构造器中的默认域初始化:数值0,布尔值false,对象引用null,不提倡,万一对空引用执行操作了呢?;实例域和局部变量在默认域初始化这一块有区别,强调局部变量一定要显示初始化;编写类时:1没有写构造器,系统提供无参数构造器,执行默认域初始化2编写了,但没写无参数构造器,不能调用无参数构造器;显示域初始化,包括声明赋值(直接对实例域赋值或者调用函数赋值)和块初始化;构造器参数名会屏蔽实例域(若同名),用this隐式参数;构造器中出现this(…);表示调用同一个类的另一个构造器,优点是构造器的公共代码只用编写一次;初始化块,很坑,大实话,只要构造类的对象,这些块就会执行,且在构造函数执行之前先执行,由于一些比较复杂的原因,建议将其放在实例域定义之后(静态初始化块用于初始化静态域);调用构造器的具体处理步骤:1所有数据域被初始化为默认值(0,false,null)2按照在类声明中的出现次序,依次执行所有域初始语句和初始化块,若构造器调用了this(…);则先去this(…);再执行构造器的剩余代码;赠一段装X代码:
22. 静态导入
import …;//导入类
import static …;//导入类的实例域和方法
23. JavaDoc
n 域注释:公有域
n 通用注释:
@author Reese |
@version 1.0.0 |
@since version 1.0.0 |
@deprecated Use <code> set(true) </code> instead |
@see 引用(package.class#label或<a href=”..”>URL</a>或”text”) |
{@link package.class#label} |
n 包注释:独立的注释文件;package.html或者package-info.html
n 概述性注释:
n 注释的抽取
详见官方文档:http://docs.oracle.com/javase/1.5.0/docs/guide/javadoc/index.html
24. 类的设计技巧
1. 数据私有
2. 数据初始化
3. 数据类型封装
4. 不是所有的域都需要setter和getter
有的信息保密或不支持修改,例如身份证号码和雇佣期
5. 类的功能要单一,不要太复杂