参考自–《Java核心技术卷1》
1 预定义类
1.1 对象和对象变量
要想使用对象,就必须首先构造对象,并指定其初始状态。然后,对对象应用方法。
在 Java 中,通过构造器构造新实例。构造器是一种特殊的方法,用来构造并初始化对象。
如下:
在标准 Java 库中包含一个 Date 类,它的对象将描述一个时间点,如:Mon Apr 13 16:37:31 CST 2020。构造器的名字应该与类名相同,因此 Date 类的构造器名为 Date。想要构造一个 Date 对象,需要在构造器前面加上 new 操作符:
new Date();
这个表达式构造了一个新对象,这个对象被初始化为当前的日期和时间。可以将对象存放在一个变量中:
Date birthday = new Date();
如图,新构造的对象变量birthday
对象变量在没有初始化之前(仅仅是定义阶段),即 Date deadline
可以引用 Date 类型的对象,但是,变量 deadline 此时不是一个对象,也没有引用对象,它不能使用任何 Date 的方法。
对象变量的初始化:引用新构造的对象或引用一个已存在的对象
deadline = new Date(); //引用新构造的对象
//或
deadline = birthday; //引用一个已存在的对象
若引用一个已存在的对象,则这两个变量指向同一个对象实例
注:一个对象变量并没有实际包含一个对象,而仅仅是引用一个对象。
任何对象变量的值都是对存储在另一个地方的一个对象的引用。new 操作符的返回值也是一个引用:
Date date = new Date();
上述语句分两部分:new Date()
构造一个 Date 类型的对象;并且它的值是对新创建对象的引用,这个引用存储在变量 date 中。
可以显示地将对象变量设置为 null,表明这个对象变量目前没有引用任何对象。此时这个对象变量也不能使用对象的任何方法。
局部变量不会自动地初始化为null,而必须通过调用 new 或者将它们设置为 null 进行初始化。
注:对于时间日期的描述,还有一个日历表示法的 LocalDate 类(Date类表示的是时间点)。
简述 LocalDate 类:
1.不要使用构造器构造LocalDate类的对象,应当使用静态工厂方法代表用户调用构造器,LocalDate.now()
会构造一个新对象,表示构造这个对象时的日期。
2.可提供年、月、日构造对应一个特定日期的对象,LocalDate.of(2020,12,31)
3.LocalDate 封装了实例域来维护所设置的日期。(plusDays()
方法)
1.2 对象的方法:更改器方法与访问器方法
更改器方法:经调用后对象的状态发生了变化的方法。
访问器方法:只访问对象而不修改对象的方法即为访问器方法。
在 Java 中,更改器方法与访问器方法在语法上没有明显区别。
附: LocalDate 类的常用api
static LocalTime now()
构造一个表示当前日期的对象static LocalTime of(int year,int month,int day)
构造一个表示给定日期的对象int getYear()
int getMonthValue()
int getDayOfMonth()
得到当前日期的年、月、日DayOfWeek getDayOfWeek()
得到当前日期是星期几,作为DayOfWeek
类的一个实例返回。调用getValue()
来得到 1~7之间的一个数,表示星期几,1表示星期一,7表示星期日LocalDate plusDays(int n)
LocalDate minusDays(int n)
生成当前日期之后或之前n天的日期
2 自定义类
在一个源文件中,只能有一个公有类,但可以有任意数目的非公有类。
2.1 用户自定义类的构造
-
实例域:一般标记为 private (封装性)
-
实例方法:一般标记为 public ,任何类的任何方法都可以调用这些方法
私有数据域+公有的域访问器方法(访问器方法)+公有的域更改器方法(更改器方法)
-
构造器:构造器与类同名;每个类可以有一个以上的构造器;构造器可以有0个、1个或多个参数;构造器没有返回值;构造器总是伴随着 new 操作一起调用,将实例域初始化为所希望的状态(所有的Java对象都是在堆中构造的)
2.2 隐式参数和显式参数
如下:
//raiseSalary是自定义对象Employee的一个方法,salary为该对象的一个实例域
public void raiseSalary(double percent){
double raise = salary * percent / 100;
salary += raise;
}
调用:
//在主源文件中调用这个方法,number007是一个实例化的Employee对象
number007.raiseSalary(5);
//上述调用等价于
double raise = number007.salary * 5 /100;
number007.salary += raise;
实际上,raiseSalary
方法有两个参数。第一个参数称为隐式参数,是出现在方法名前的 Employee 类对象(即 number007),隐式参数并没有出现在方法的声明中;第二个参数即位于方法名后括号中的 percent 数值,这是一个显示参数。(有些人把隐式参数称为方法调用的目标或接收者)
在每一个方法中,关键字 this 表示隐式参数,如 raiseSalary
方法可以写为:
public void raiseSalary(double percent){
double raise = this.salary * percent / 100;
this.salary += raise;
}
这样可以将实例域与局部变量明显地区分开。
2.3 可变对象的访问器方法(尽量不要使用)
Employee 类:
class Employee{
private Date hireDay;
...
public Date getHireDay(){
return hireDay; //不好
}
}
调用:
Employee harry = ...;
Date d = harry.getHireDay();
double tenYearsInMilliseconds = 10 * 365 * 24 * 60 * 60 *1000; //10年的毫秒数
d.setTime(d.getTime() - (long)tenYearsInMilliseconds);
//在d的基础上减少十年
此时,d 和 harry.hireDay
引用的是同一个对象。对 d 调用更改器(非域更改器)方法就可以随意改变这个对象的私有状态。
如果需要返回一个可变对象的引用,应该首先对它进行克隆(clone)。对象 clone 是指存放在另一个位置上的该对象副本。修改后 raiseSalary
如下:
class Employee{
private Date hireDay;
...
public Date getHireDay(){
return(Date)hireDay.clone(); //ok
}
}
同样,如果需要返回一个可变数据域的拷贝,就应该使用 clone。
3 类设计技巧
1)一定要保证数据私有
这是最重要的,绝对不能破坏封装性
2)一定要对数据初始化
Java 不对局部变量初始化,但是会对对象的实例域进行初始化。最好还是不要依赖于系统的默认值,而是应该显式地初始化所有的数据,具体的初始化方式可以是提供默认值,也可以在构造器中设置默认值。
3)不要在类中使用过多的基本类型
如果类中的基本类型使用(即数据定义的特别多)过多,就会显得混乱;可以使用其他的类代替多个相关的基本类型的使用,这样会使类更加易于理解且易于修改。如:
public Employee{ ... private String street; private String city; private String state; private int zip; ... } //可以增加一个 Address 的新的类替换上述写出来的实例域(即建立实体存储数据)
4)不是所有的域都需要独立的域访问器和域更改器(get/set 方法)
5)将职责过多的类进行分解
“过多”随每个人的看法而定,但,如果明显可以将一个复杂的类分解为两个更简单的类,就应该将其分解
6)类名和方法名要能够体现它们的职责
7)优先使用不可变的类
类中没有方法能改变类实例化对象的状态 – 即为不可变类
转载:https://blog.csdn.net/qq_42964349/article/details/105935384