在Java中,没有类就没法做任何事情,然而并不是所有的类都具有面向对象特征。例如,Math 类。在程序中,可以使用 Math 类的方法, 如 Math.random, 并只需要知道方法名和参数(如果有的话),而不必了解它的具体实现过程。
对象与对象变量
要想使用对象,就必须首先构造对象,并指定其初始状态。然后,对对象应用方法。在Java程序设计语言中,使用构造器构造新实例。构造器是一种特殊的方法,用来构造并初始化对象。下面看一个例子。 构造器的名字应该与类名相同。因此Date类的构造器名为Date。要想构造一个Date对象,需要在构造器前面加上new操作符,如下所示
new Date()
这个表达式构造了一个新对象。这个对象被初始化为当前的日期和时间。如果需要的话, 也可以将这个对象传递给一个方法:
System.out.printTn(new DateO);
或者, 也可以将一个方法应用于刚刚创建的对象。Date 类中有一个 toString 方法。这个方法将返回日期的字符串描述。下面的语句可以说明如何将 toString 方法应用于新构造的Date 对象上。
String s = new Date().toString();
在这两个例子中, 构造的对象仅使用了一次。通常, 希望构造的对象可以多次使用, 因 此,需要将对象存放在一个变量中:
Date birthday = new Date();
在对象与对象变量之间存在着一个重要的区别。例如, 语句
Date deadline; // deadline doesn't refer to any object
定义了一个对象变量 deadline, 它 可 以 引 用 Date 类型的对象。但是,一定要认识到: 变量deadline 不是一个对象, 实际上也没有引用对象。此时,不能将任何 Date 方法应用于这个变量上。下面的语句将产生编译错误。
s = deadline.toString();
必须首先初始化变量 deadline, 这里有两个选择。当然,可以用新构造的对象初始化这个变量:
deadline = new Date();
也让这个变量引用一个已存在的对象:
deadline = birthday;
一定要认识到: 一个对象变量并没有实际包含一个对象,而仅仅引用一个对象。 在 Java 中,任何对象变量的值都是对存储在另外一个地方的一个对象的引用。new 操作符的返回值也是一个引用。下列语句:
Date deadline = new Date();
有两个部分。表达式 new Date() 构造了一个 Date 类型的对象, 并且它的值是对新创建对象的引用。这个引用存储在变量 deadline 中。
可以显式地将对象变量设置为 null,表明这个对象变量目前没有引用任何对象。
deadline = null;
if (deadline != null)
System.out.println(deadline);
如果将一个方法应用于一个值为 null 的对象上,那么就会在运行时产生错误。
birthday = null;
String s = birthday.toString(); // runtime error!
局部变量不会自动地初始化为 null,而必须通过调用 new 或将它们设置为 null 进行初始化。
Java类库中的LocalDate类
标准 Java 类库分别包含了两个类:一个是用来表示时间点的 Date 类;另一个是用来表示大家熟悉的日历表示法的 LocalDate 类。将时间与日历分开是一种很好的面向对象设计。通常,最好使用不同的类表示不同的概念。
不要使用构造器来构造 LocalDate 类的对象。实际上,应当使用静态工厂方法 (factory method) 代替调用构造器。
Local Date.now()
会构造一个新对象,表示构造这个对象时的日期。也可以提供年、 月和日来构造对应一个特定日期的对象:
LocalDate newYearsEve = Local Date.of(1999, 12, 31);
一旦有了一个 LocalDate 对象, 可以用方法 getYear、 getMonthValue 和 getDayOfMonth 得到年、月和日,看起来这似乎没有多大的意义, 因为这正是构造对象时使用的那些值。不过,有时可能某个日期是计算得到的,你希望调用这些方法来得到更多信息。例如, plusDays 方法会得到一个新的 LocalDate, 如果把应用这个方法的对象称为当前对象,这个新日期对象则是距当前对象指定天数的一个新日期:
LocalDate aThousandDaysLater = newYearsEve.plusDays(1000):
year = aThousandDaysLater.getYear();// 2002
month = aThousandDaysLater.getMonthValue(); // 09
day = aThousandDaysLater.getDayOfMonth(); // 26
更改器方法与访问器方法
再来看上一节中的 plusDays 方法调用:
LocalDate aThousandDaysLater = newYearsEve.plusDays(1000);
调用之后 ,newYearsEve并没有发生变化。plusDays 方法会生成一个新的 LocalDate 对象,然后把这个新对象赋给 aThousandDaysLater变量。原来的对象不做任何改动。Java 库的一个较早版本曾经有另一个类来处理日历,名为 GregorianCalendar。为这个类表示的一个日期增加 1000 天 代码如下:
GregorianCalendar someDay = new CregorianCalendar(1999, 11, 31);
//Odd feature of that class: month numbers go from 0 to 11
someDay.add(Calendar.DAY_0F_M0NTH, 1000);
与 LocalDate.plusDays 方法不同,GregorianCalendar.add 方法是一个更改器方法 ( mutator method ), 调用这个方法后,someDay 对象的状态会改变。可以如下査看新状态:
year = someDay.get(Calendar.YEAR); // 2002
month = someDay.get(Calendar.MONTH)+ 1; // 09
day = someDay.get(Ca1endar.DAY_0F_M0NTH); // 26
正是因为这个原因,我们将变量命名为 someDay 而不是 newYearsEve 。调用这个更改器方法之后,它不再是新年前夜。相 反, 只访问对象而不修改对象的方法称为访问器方法, 例 如,LocalDate.getYear 和 GregorianCalendar.get 就是访问器方法