文章目录
- 第四章 对象与类
- 使用预定义类
- 对象与对象变量
- Java库中的LocalDate类
- 更改器方法和访问器方法
- ==用户自定义类==
- 用`var`声明局部变量
- 使用`null`引用
- 隐式参数与显示参数
- 基于类的访问权限
- 私有方法
- `final`实例字段
- 静态字段与静态方法
- 静态字段
- 静态常量
- 静态方法
- 工厂方法
- `main`方法
- 方法参数
- 对象构造
- 重载
- 默认字段初始化
- 无参数构造器
- 显式字段初始化
- 参数名
- 调用另一个构造器
- 初始化块
- 包
- 包名
- 类的导入
- 静态导入
- 包访问
- 文档注释
- 注释的插入
- 类注释
- 方法注释
- 字段注释
- 通用注释
- 包注释
- 类设计技巧
第四章 对象与类
- 面向对象程序设计: (OOP)先考虑数据, 再考虑算法
- 类:
Java
b编写的所有代码都位于某个类中,以便于描述应用程序所对应问题领域中的对象 -
- 封装(数据隐藏): 将数据和行为组合在一个包中, 对对象使用者隐藏具体实现方法
- 实例字段: 对象中的数据
- 方法:操作对象的过程
- 状态: 一组特定实例字段值的集合
- 继承:通过扩展一个类来建立另一个类的过程
- 对象: 对象的行为(方法), 对象的状态, 对象的标识
- 类与类之间的关系:依赖, 聚合, 继承
使用预定义类
对象与对象变量
-
==构造器(构造函数):==构造新实例, 一种特殊的方法, 用来构造并且初始化对象
-
Date birthday = new Date(); birthday 引用新构造的对象
-
Date deadline; 对象变量deadline可以引用Date类型的对象, 但是其本身不是一个对象, 不能使用任何Date方法
-
初始化
deadline
, r让他引用一个新构造的对象deadline = new Date(); 或者 deadline = birthday;
-
**注意:**对象变量没有实际包含一个对象, 只是包含一个对象的引用
-
deadline = null;
Java库中的LocalDate类
-
不要使用构造器来构造
LocalDate
类, 用静态工厂方法 -
LocalDate date = LocalDate.of(2001, 12, 26); int year = date.getYear();//2001 int month = date.getMonthValue();//12 int day = date.getDayOfMonth();//26
更改器方法和访问器方法
getMonthValue()
为访问器方法- 更改器方法会改变原始对象的状态
用户自定义类
- 格式
class ClassName
{field1;field2;constructor1;constructor2;...method1;method2;
}
- 实例:
-
private
: 表示只有Employee自身可以访问public
: 表示任何方法都可以调用这些方法name
本身就是String
对象,hireDay
同理
class Employee
{private String name;private double salary;private LocalDate hireDay;// 构造器, 与类名同名, 初始化实例字段// 每个类可以有一个以上的构造器, 每个构造器可以有0+个参数,构造器没有返回值// 构造器总是伴随着`new`操作符一起调用public Employee(String name, double salary, int year, int month, int day) {this.name = name;this.salary = salary;hireDay = LocalDate.of(year, month, day);}//下面三个是字段访问器public String getName() {return name;}public double getSalary() {return salary;}public LocalDate getHireDay() {return hireDay;}//不要编写返回可变对象类型的访问器方法, 这里的LocalDate就是不可变的//返回一个可变对象类型的副本应该用clone//e.g.: return (Date) hireDay.clone();public void raiseSalary(double byPercent) {double raise = salary * byPercent / 100;salary += raise;}
}
- 一个源文件中只能有一个公共类,非公共类无限制
用var
声明局部变量
- 如果从变量的初始值可以推导出它们的类型就用
var
关键字声明局部变量
使用null
引用
-
LocalDate birthday = null; String s = birthday.toString();//NUllPointerException
-
拒绝
null
参数
public Employee(String name, double salary, int year, int month, int day) {this.name = Objects.requireNoNull(name, "The name can't be null.");this.salary = salary;hireDay = LocalDate.of(year, month, day);}
隐式参数与显示参数
this
: 每一个方法中指示隐式参数- 方法名后面括号里的为显示参数
基于类的访问权限
- 一个方法可以访问所属类的所有对象的私有数据
私有方法
- 作为辅助代码,可以方便的删除
final
实例字段
- 一般用于基本类型或者不可变类的字段
- 必须在构造对象时候初始化
静态字段与静态方法
静态字段
static
: 每个类只有一个这样的字段,属于类,不属于某一个单个对象- 对于非静态的实例字段,每个对象都有一个自己的副本
- 静态字段不是不可变的,也可以
++
静态常量
System.out
:就是静态常量- 最好不要有公共字段但是比如公共常量
final
就可以的
静态方法
-
静态方法: 不在对象上执行的方法,没有隐式参数, 指示属于类而不属于任何对象的变量和函数
-
e.g.:
Math.pow()
-
静态方法不可以访问实例字段, 但是可以访问静态字段
-
public static int getNextId(){return nextId;// returns static field }//使用类名来调用这个方法 int n = Employee.getNextId();
工厂方法
- e.g.:
LocalDate.of(xxx)
- 使用工厂方法的条件:
- 无法命名构造器
- 使用构造器时, 无法改变所构造对象的类型
main
方法
- 一个静态方法
- 主要可以用于对类进行单元测试
方法参数
- 将参数传递给函数的方法: 按值调用, 按引用调用
Java
程序设计语言总是按值调用- 实际上对象引用是按值传递的
- 方法参数不能修改基本数据类型的参数(数值型,布尔型)
- 方法参数可以改变对象参数的状态
- 方法不能让一个对象参数引用一个新的对象
对象构造
重载
- 定义: 多个方法有相同的名字和不同的参数
签名
: 完整描述一个方法需要指定方法名和参数类型
默认字段初始化
- 构造器没有显式的为字段赋初始值,那么自动默认赋值 数值0, 布尔false, 对象引用null
- 方法中的局部变量必须显式进行初始化
无参数构造器
- 类中没有构造器就会提供无参数构造器
- 如果类中提供了构造器但是没有无参数构造器,那么构造对象无参数就是不合法的
显式字段初始化
- 可以在类定义中为任何字段赋值
calss Employee
{private String name = "";
}
参数名
- 单个字母作为参数名
public Emloyee(String n, double s)
{name = n;salary = s;
}
- 参数前面加上前缀
a
public Emloyee(String aName, double aSalary)
{name = aName;salary = aSalary;
}
- 参数变量会遮蔽同名的实例字段
public Emloyee(String name, double salary)
{this.name = name;this.salary = salary;
}
调用另一个构造器
- 构造器的第一个语句
this(xxx)
将调用另一个构造器
初始化块
- 初始化数据字段的方法: 构造器中设置值, 声明中赋值, 初始化块
- 只要构造这个类对象初始化块一定会被执行
- 通常将初始化块放在构造器中
package chapter4_object_and_class;import java.util.Random;public class constructor_test {public static void main(String[] args){// fill the staff array with three Employee objectsvar staff = new Employee_2[3];staff[0] = new Employee_2("Harry", 40000);staff[1] = new Employee_2(60000);staff[2] = new Employee_2();// print out information about all Employee objectsfor (Employee_2 e : staff)System.out.println("name=" + e.getName() + ",id=" + e.getId() + ",salary="+ e.getSalary());}
}class Employee_2
{private static int nextId;private int id;private String name = ""; // instance field initialization 实例字段初始化private double salary;// static initialization block 静态代码块初始化static{var generator = new Random();// set nextId to a random number between 0 and 9999nextId = generator.nextInt(10000);}// object initialization block 对象初始化块{id = nextId;nextId++;}// three overloaded constructors 三个重载的构造器(构造函数)public Employee_2(String n, double s){name = n;salary = s;}public Employee_2(double s){// calls the Employee(String, double) constructor 调用第一个构造器/* 调用 */this("Employee #" + nextId, s);}// the default constructor 无参数构造器public Employee_2(){// name initialized to ""--see above// salary not explicitly set--initialized to 0// id initialized in initialization block}public String getName(){return name;}public double getSalary(){return salary;}public int getId(){return id;}
}
包
- 将类组织到一个集合中
包名
- 使用包原因: 确保类名唯一性
- 用url逆序书写作为包名
- 嵌套的包之间没有任何关系
类的导入
- 一个类可以使用包中的所有类以及其他包中的公共类
import java.util.*;
静态导入
-
允许导入静态方法和静态字段
-
import java.lang.System.*; out.println("cdsj"); exit(0)
包访问
- 如果没有指定
public, private
, 那么这个部分(类, 方法,变量)可以被一个包中所有方法访问
文档注释
注释的插入
- 每个
/* **/
文档注释包含标记以及之后紧跟者的自由格式文本 - 标记以
@
开始 - 自由格式文本第一句应该是一个概要性的句子
javadoc
工具将这些句子抽取出来生成概要页
类注释
- 类注释放在
import
后, 类定义之前
/**
*A cbsbudjcka
*cdnskvdls
*/
方法注释
- 必须放在所描述方法之前
- 标记
@param variable description
@return description
@throws class descirption
字段注释
- 对公共字段(静态常量)建立文档
/**
* A "words" has 5 letters
*/
public static final int WORDS = 5;
通用注释
@since text 引入这个版本的描述
@auther name
@version text 当前版本的描述
@see, @link 超链接, 连接到javadoc文档或者外部文档-->P51
包注释
-
包目录中添加单独文件
-
- 提供
package-info.java
- 提供
package.html
文件, 抽取
<body>xxx </body>
- 提供
类设计技巧
- 保证数据私有(封装性)
- 一定对数据进行初始化
- 不要在类中过多使用基本类型
- 不是所有的字段都需要单独的字段访问器和字段更改器
- 分解有过多职责的类
- 类名和方法名都要能够体现他的职责
-
- 访问器用
get
开头, 更改器用set
开头
- 访问器用
- 优先使用不可变类