Java核心技术 读书笔记:
第四章 对象与类
对象的理解:
每个对象包含对用户公开的特定功能部分和隐藏的实现部分。从根本上来说,只要对象能够满足要求,就不必关心其功能到底如何实现!
此外,每个对象都保存着描述当前状况的信息——对象的状态。对象状态的改变必须通过调用方法实现(如果不经过调用就可以改变对象状态,只能说明破坏了封装性!)
对象引用:
对象的创建通过对象提前写好的构造函数(无参 有参),new+构造才能够创建出一个新的对象
1 | Date s = new Date() |
实际上,k和s引用的是同一对象(new的Date的对象),指向相同!
所有的Java对象都存储在堆中,当一个对象包含另一个对象变量时,它只是包含着另一个堆对象的指针!
类:
三种关系:
- 依赖(uses-a)如Order类使用Account类,是因为Order对象需要访问Account对象查看信用状态!——我们应该尽可能减少相互依赖:减少类之间的耦合!
- 聚合(has-a)包含关系
- 继承(is-a)
公共类和非公共类(是否带public)
- 源文件名必须与public类的名字相匹配,在一个源文件中,只能有一个公共类,但可以有任意数目的非公共类。
- 一般习惯将类单独命名为xxx.java
类中的public方法:
public意味着任何类的任何方法都可以调用这些方法(一共有4个级别,后面介绍)
构造器:
- 与类同名
- 可以有一个以上的构造器
- 构造器可以有任意数目的参数
- 构造器没有返回值
- 总是伴随new一起调用!
var声明局部变量:
Java10中,如果可以从变量的初始值推导出它们的类型,可用var关键字声明局部变量,无须指定类型。
1 | Employee harry = new Employee("Harry",5000,1989,10,1); |
两者等效
隐式参数和显式参数:
如:
1 | public viod raiseSalary(double byPercent) { |
其结果是将number007.salary字段新增5%(设置为了一个新值)
raiseSalary有两个参数,其一是前面的Employee类的对象,第二则是括号中的参数
关键词this指示隐式参数,可以改写:(强烈推荐)
1 | public viod raiseSalary(double byPercent) { |
可以将实例字段和局部变量明显区分出来
警告!(初探对象封装性)
不要编写返回可变对象引用的访问器方法。
例如:
1 | class Employee |
其中的Date类有更改器方法setTime,也就是说Date对象是可变的,这就破坏了封装性!
1 | Employee harry = ...; |
d和harry.hareDay引用的是同一个对象,对d调用更改器方法就可以自动地改变这个Employee对象的私有状态!
如果要返回一个可变对象的引用,首先应该对它进行克隆!对象克隆指放在另一个新位置上的对象副本。
1 | class Employee |
谈谈私有方法和公共方法
由于公共数据非常危险,应该将数据字段设置为私有的字段(很好理解),对于方法来说,尽管大部分都是公共的,但有些情况下用私有会更好:如,数据的表示发生了变化,这个方法可能会变得难以实现,或者不再需要,这并不重要,重要的是,只要它是私有方法,类的设计者就可以确信它不会在别处使用没所以可以将其删去,如果一个方法是公共的,就不能简单的删除,因为有可能在别处依赖!
final实例字段
一旦设置,以后就不再修改这个字段,如Employee类中的name字段设置为final,因为在对象构造后,值不会改变,即没有setName方法。
对于基本类型或者不可变类的字段尤其有用:
对于可变的类,可能混乱:
1
private final StringBuilder evaluations;
它在Employee中初始化为:
1
evaluations = new StringBuilder();
final关键字只是表示存储在evaluations变量中的对象引用不会再指向另一个不同的StringBuilder对象。不过这个对象依旧是可以更改的!!也就是地址不变而已
静态字段与静态方法
静态字段:属于类,不属于对象!例如,要给每个员工一个唯一的标识码,这里给Employee类添加一个实例字段id和一个静态字段nextId;
1 | class Employee |
当新增员工时,其id是在整个员工nextId基础之上的!也就是说,这个nextId是公共调用的!
静态常量用的更多,比如Math类下的PI值
以下两种情况下可以使用静态方法:
- 方法不需要访问对象的状态,因为它需要的所有参数都通过显式参数提供,如Math.pow
- 方法只需要访问类的静态字,如Employee.getNextId





