static 关键词
static 关键词主要用来修饰类的内部成员,如成员变量、成员方法、内部类和语句块等。它的功能就是限定这些成员只属于类,而与类的具体对象实例无关。
1.静态变量
用 static 修饰的成员变量成为静态变量或类变量。静态变量只有在系统加载类时,进行一次空间分配和初始化。创建该类的对象实例时,不再为静态变量分配空间,实例内仅存放指向静态变量的引用,即所有该类的对象共享同一个类变量空间。使用静态变量时,可以用类名也可以用对象名来引用,它们都是对这个共享空间的操作。
例如(银行账户类):
class Account{
private String AccountNumber;
private String AccountName;
private double balance;
static double interest = 0.1;
//显示的初始化年利率的值
public Account(String number,String name){
AccountNumber = number;
AccountName = name;
balance = 0.0;
}
public void print(){
System.out.println("账号:"+AccountNumber);
System.out.println("账户名:"+AccountName);
System.out.println("年利率:"+interest);
}
}
public class TestAccount{
public static void main(String[] args){
Account a = new Account("3454523314","张三");
Account b = new Account("3454524315","李四");
a.print();
b.print();
Account.interest = 0.9;
//此处用a.interest = 0.9 或者用b.interest = 0.9 结果是一样的。
System.out.println("修改年利率后:");
a.print;
b.print;
}
}
银行账号类 Account 有四个成员变量,其中账号、账户名和账户余额是非静态的实例变量,每个对象实例的这些变量要单独占用一块内存空间,而年利率是静态变量,它是类变量,仅有一个存储空间,两个 Account 类对象 a 和 b 共享这一空间。
2.静态方法
用 static 修饰的成员方法称为静态方法或类方法。类方法仅仅属于类,使用是通过类名引用,也可以通过对象名引用,表示调用该对象所属类的静态方法。静态方法一般用来处理类的静态变量或做一些与对象实例无关的操作,例如工具类中的求随机数方法、求绝对值方法等。
静态方法在定义和使用时应该注意下面几个问题:
(1)类的静态方法只能访问类的静态成员,不能访问非静态的对象成员。类的静态方法属于类,它不依赖与任何对象,也就是无法访问任何对象的对象成员。所以说,静态方法可以访问静态变量、静态方法、自身的参数变量和局部变量。
(2)静态方法只能继承,不能重写。子类中可以定义与父类相同的静态方法,此时只是将父类的方法隐藏,而不是覆盖它。此外,父类中的静态方法不能重写为非静态方法,非静态方法也不能重写静态方法。静态方法属于类,非静态方法属于对象,所以在方法重写时,二者不能混淆。
(3)静态方法中不能使用 this、super 关键词。静态方法是类方法,不能访问非静态成员,而 this 和 super 作为特殊对象名是用来引用非静态成员的,所以在静态方法中不能用 this 和 super 关键词。
(4)main() 作为程序的入口是一个特殊的静态方法。它可以使JVM不创建主类的对象实例而直接运行 main() 中的代码。但是,如果在 main() 中要访问主类的非静态成员,那么就必须创建一个主类对象,通过对象去访问,否则会出现编译错误。
静态方法示例:
class SuperClass{
public static void method1(){
System.out.println("这里调用的是:父类的静态方法 method1");
}
public static void method2(){
System.out.println("这里调用的是:父类的静态方法 method2");
}
}
class SubClass extends SuperClass{
public static void method1(){
//此处要是不写 static,将静态方法重写成非静态的会出现编译错误。
System.out.println("这里调用的时:子类的静态方法 method1");
}
public void method2(){
//此处要是写 static,将非静态方法重写为静态的会出现编译错误。
System.out.println("这里调用的时:子类的静态方法 method2");
}
}
public class TestStaticMethod{
int x = 10;
public static void main(String[] arge){
SubClass sub = new SubClass();
SuperClass Sup;
sup =sub;
sup.method1();
sub.method1();
sup.method2();
sub.method2();
TestStaticMethod mc = new TestStaticMethod();
System.out.println("mc.x = "+mc.x);
}
}
例子中子类 SubClass 定义了两个与父类相同的方法 method1 和 method2,其中method1 是静态方法,它将继承自父类的静态方法 method1 隐藏了,而非静态方法 method2 则是覆盖了继承来自父类的非静态方法 method2 方法。
所以在子类中有两个 method1 静态方法,只有一个 method2 非静态方法。
在 main 方法中定义了一个父类 SuperClass 的引用 sup,它指向子类对象 sub,此时 sub 对象可以当成父类对象使用。
如果要在静态 main() 主程序中访问主类的非静态变量 x,必须实例化一个类对象mc,然后通过对象名 mc 来引用 x,否则就会出现编译错误。
3.静态语句块
在类体内不属于任何方法体并且用 static 修饰的语句块称为静态语句块。静态语句块通常用来对静态变量进行初始化,所以也称为静态初始化程序块。静态语句块仅在类加载是运行一次。如果一个类定义了多个静态语句块,这些语句块按其定义的顺序运行。
定义格式:
static{
...
}
例如给银行账户的 Account 类添加一个静态语句块,完成年利率的初始化。
class Account{
...
static{
interset = 0.72;
System.out.println("年利率的初值:"+interest);
}
}
调用静态语句块后 interest 的值为 0.72,把显示赋值的0.1覆盖了。