1)static表示静态的意思,表明一个被其修饰的成员变量(类成员)或者是成员方法(类方法)可以在没有所属类的实例变量的情况下被访问。
2)Java中不可以重写static方法,因为重写Override是基于运行时动态绑定的,而static方法是编译时静态绑定的。static方法跟类的任何实例都不相关,所以不可以重写static方法。
PS:Java中也不可以重写一个private方法,因为private方法只能在当前类中被访问,被private修饰的父类方法在子类中是不可见的。
关于Java中的static关键字
static 可以修饰:
- 变量(所谓 class variable)
- 方法(所谓 class method)
- 代码块(所谓 block)
- 内部类(所谓 nested class)
凡是被 static 修饰的这四种元素,都属于class的元素,即类的,而不是类的实例的。
1)静态变量
- 静态变量适合用在该变量被该类的所有实例所共享的时候。
- 静态变量在类被加载的时候初始化,且仅分配一次内存。好处是内存利用率高。
class Student {
int id;
String name;
String school = "XiYou";
假设西安邮电大学有999999名学生,那么每一个学生创建的时候,都会初始化学号、姓名、学校,那么这些学生的学号、姓名各不相同,但是学校“XiYou”都是一样的,如果每次都初始化一遍,就比较消耗内存。所以school是被该类的所有实例所共享的,因此可以将它声明为static。
还有一个栗子:
Counter类中声明了一个count变量,在构造函数中对其进行++操作,因为实例变量在对象被创建的时候分配内存,所以每一个对象都有一份自己count副本,每个对象各自count的++操作不会反应到其他对象上。
class Counter {
int count = 0;
Counter() {
count++;
System.out.println(count);
}
public static void main(String[] args) {
Counter c1 = new Counter();
Counter c2 = new COunter();
Counter c3 = new Counter();
}
}
Output:1
1
1
因为静态变量仅仅在类加载的时候分配一次内存,所以如果将count修饰为static,那么该类的所有对象都会共享该变量,每一个对象对count的操作都会反应到其他对象上。
class Counter2 {
static int count = 0;
Counter2() {
count++;
System.out.println(count);
}
public static void main(String[] args) {
Counter c1 = new Counter2();
Counter c2 = new COunter2();
Counter c3 = new Counter2();
}
}
Output:1
2
3
2)静态方法
- 静态方法属于类而不是对象。
- 静态方法可以直接通过类名调用,而不需要创建类的对象。
- 静态方法可以修改静态变量,而非静态方法不可以。
一个静态方法的栗子:
class Student2 {
int id;
String name;
static String school = "XiYou";
static void change() {
school = "XY";
}
Student2(int i, String n) {
id = i;
name = n;
}
void display() {
System.out.println(id + " " + name + " " + school);
}
public static void main(String[] args) {
Student2.change();
Student2 s1 = new Student2(4161074, "longer");
Student2 s2 = new Student2(4161075, "daner");
Student2 s3 = new Student2(4161076, "yaer");
s1.display();
s2.display();
s3.display();
}
}
第二个栗子:
public class Calculate {
static int cube(int x) {
return x*x*x;
}
public static void main(String[] args) {
int result = Calculate.cube(5);
System.out.println(result);
}
}
Output:125
静态方法的两个注意点:
- 静态方法不能操作非静态变量,也不能调用非静态方法(可以这样理解,静态方法属于类,直接通过类名就可以调用,而此时可能没有任何实例,就谈不上操作实例变量和调用实例方法了)。
- 静态方法中不能使用this和super关键字。
比如这个栗子就是编译错误的:
class A {
int a = 40;
public static void main(String[] args) {
System.out.println(a);
}
问题来了,那么为什么Java的main方法是static的?
答:为了使得在调用main方法之前不需要创建任何实例对象。
3)静态代码块
- 用来初始化静态变量。
- 在类加载时,在执行main方法前执行相关操作。
栗子:
class A2 {
static {
System.out.println("static block is invoked");
}
public static void main(String[] args) {
System.out.println("Hello main");
}
Output:static block is invoked
Hello main
4)静态内部类(被static修饰的类,并且处于某个类的内部)
- 可以访问外部类的静态成员,包括private成员
- 不能访问外部类的非静态成员