静态域与静态方法
(一)静态域
如果将域定义为static,每个类只有一个这样的域。而每个对象对于所有的实例域都有自己的一份拷贝。给Employee类添加一个实例域id和一个静态域nextId:
class Employee
{
private static int nextId=1;
private int id;
}
现在,每个对象都有一个自己的id域,但这个类的所有实例将共享一个nextId域。也就是说如果有1000个Employee类的对象,则有1000个实例域,但是只有一个静态域。即使没有一个雇员对象,静态域nextId也存在。它属于类,而不属于任何对象。
(二)静态常量
静态变量使用得比较少,但是静态常量却使用得比较多。例如在Math类中定义了一个静态常量:
public class Math{
...
public static final double PI = 3.14159265358979323846;
...
}
在程序中,可以采用Math.PI的形式获得这个常量。如果关键字static省略,那么就需要通过创建一个Math类的对象来访问PI,换言之就是静态常量可以直接通过(类名.静态常量名)的形式来访问。
(三)静态方法
静态方法时一种不能向对象实施操作的方法。也就是说静态方法中是没有this参数的方法,也就表明静态方法中没有隐式参数。例如之前所提到的,静态方法不能访问Employee类的实例域,因为它不能操作对象。但是静态方法可以访问自身类中的静态域。
public static int getNextId()
{
return nextId;
}
可以通过类名调用这个方法:
int n = Employee.getNextId();
也可以使用对象来调用静态方法,但是容易造成混淆,所以不建议使用对象来调用静态方法。在下面两种情况下使用静态方法:
①一个方法不需要访问对象状态,其所需参数都是通过显示参数提供。
②一个方法只需要访问类的静态域
(四)工厂方法
静态方法还有另外一种常见的用途,类似LocalDate和NumberFormat类使用静态工厂方法来构造对象。接下来看一段代码:
NumberFormat currencyFormatter = NumberFormat.getCurrencyInstance();
NumberFormat percentFormatter = NumberFormat.getPercentInstance();
double x = 0.1;
System.out.println(currencyFormatter.format(x));
System.out.println(percentFomatter.format(x));
为什么NumberFormat类不利用构造器完成这些操作?这主要有两个原因:
①无法命名构造器。构造器的名字必须与类名相同。但是,这里希望得到的货币实例和百分比实例采用不同的名字
②当使用构造器时,无法改变所构造的类型。但是工厂方法有时可以改变所得到的类型。
(五)main方法
需要注意,静态方法部分需要使用对象调用。main方法也是一个静态方法,它不对任何对象进行操作。事实上,在启动程序时,还没有任何一个对象。
package CoreJava;
/**
* This program demonstrates static method;
*
*/
public class StaticTest {
public static void main(String[] args) {
Employee2[] staff = new Employee2[3];
staff[0] = new Employee2("Tom",40000);
staff[1] = new Employee2("Dick",60000);
staff[2] = new Employee2("Harry",65000);
for(Employee2 e : staff) {
e.setId();
System.out.println("name="+e.getName()+",id="+e.getId()+",salary="+
e.getSalary());
}
int n = Employee2.getNextId();
System.out.println("Next available id = "+n);
}
}
class Employee2{
private static int nextId = 1;
private String name;
private double salary;
private int id;
public Employee2(String n,double s) {
this.name=n;
this.salary = s;
id=0;
}
public String getName() {
return name;
}
public double getSalary() {
return salary;
}
public int getId() {
return id;
}
public void setId() {
id=nextId;
nextId++;
}
public static int getNextId() {
return nextId;
}
}