小言_互联网的博客

8.预定义类和自定义类【Java温故系列】

365人阅读  评论(0)

参考自–《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();

如图,新构造的对象变量birthdayimage-20200413164534361

对象变量在没有初始化之前(仅仅是定义阶段),即 Date deadline 可以引用 Date 类型的对象,但是,变量 deadline 此时不是一个对象,也没有引用对象,它不能使用任何 Date 的方法。

对象变量的初始化:引用新构造的对象或引用一个已存在的对象

deadline = new Date();   //引用新构造的对象
//或
deadline = birthday;     //引用一个已存在的对象

若引用一个已存在的对象,则这两个变量指向同一个对象实例image-20200413165221722

:一个对象变量并没有实际包含一个对象,而仅仅是引用一个对象。

任何对象变量的值都是对存储在另一个地方的一个对象的引用。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 调用更改器(非域更改器)方法就可以随意改变这个对象的私有状态。

image-20200416163629684

如果需要返回一个可变对象的引用,应该首先对它进行克隆(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
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场