文章接上一篇粗略谈用户自定义类的一些注意事项1
6、final实例域
可以将实例域定义为final,这样,在每一个构造器执行之后,这个域的值被设置,并且在之后的操作中,是不能对它进行修改的。例如将Employee
类中的name
域声明为final
,在对象被创建后,这个值将不会被修改,也即没有setName
方法。
class Employee
{
private final String name;
...
}
final
修饰符大都引用于基本类型域,或者不可变类
的域(也即类中的每个方法都不会改变其对象,这种类就是不可变的类。例如String
类)。
注意事项:
private final StringBuilder evaluations;
这个例子中,Employee
构造器会初始化为
evaluations = new StringBuilder();
final
关键字只是表示存储在evaluations
变量中的对象引用不会再指示其它StringBuilder
对象,但这个对象是可以更改的:
public void giveGoldStar()
{
evaluations.append(LocalDate.now() + ":Gold star!\n")';
}
7、静态域和静态方法
7.1静态域
若一个域定义为static
,每个类中只有这样一个域。比如
class Employee
{
private static int nextId = 1;
private int id;
...
}
每一个雇员对象都有一个自己的id
域,但是这个类的所有实例都将共享一个nextId
静态域。如果有1000个Employee
类的对象,就有1000个实例域id
。但是只有一个静态域nextId
。即使没有一个雇员对象 ,静态域nextId
也存在。它属于类,不属于任何独立的对象。
7.2静态常量
public class Math
{
...
public static final double PI = 3.141592675358979323846;
...
}
在程序中,可以用Math.PI
的形式获得这个常量。
若关键字static
被省略,PI就会变成Math
类的一个实例域。需要通过Math
类的对象访问PI,并且每一个Math
对象都有一个它自己的PI拷贝(p.s.每一个对象对于所有的实例域都有自己的一个拷贝)
另外,前面说过最好不要讲域设计为public
,但是,公有常量(即final
域)却没有问题。
如:
public static final PrintStream out = ...;
7.3静态方法
静态方法是一种不能向对象实施操作的方法。比如Math
类的pow
方法就是一个静态方法。表达式
Math.pow(x,a)
计算幂
X
a
X^a
Xa。在计算过程中,并未使用Math
对象。也即它没有隐式的对象。
可以认为静态方法是没有this
的方法。Empolyee
类的静态方法不能访问Id
实例域,因为它不能操作对象,但是它可以访问自身类中的静态域。如下:
public static int getNextId()
{
return nextId; //返回静态域
}
可以通过类名调用这个方法:
int n = Employee.getNextId();
这个方法需要通过类来调用,也可以使用一个对象来调用。如harry.getNextId()
来代替Employee.getNextId()
,但是其实这个方法与harry
这个对象没有关系,所以建议使用类名。
需要使用静态方法的两种情况:
1、一个方法不需要访问对象状态,其所需参数都是通过显示参数提供的(如上面的Math.pow()
)
2、一个方法只需要访问类中的静态域(如Employee.getNextId()
)