一、静态成员先于实例成员存在
类被加载到内存时,静态变量分配内存空间,静态方法分配入口地址
只有创建对象之后,实例变量分配内存空间,实例方法分配入口地址
当再创建对象时,实例方法不再分配入口地址,方法入口地址被所有对象共享
class A {
static {
System.out.println("class A static...");
}
}
public class B {
public static void main(String[] args) {
A a = new A(); // 创建对象
}
static {
System.out.println("class B static...");
}
}
二、推荐使用类名访问静态成员
静态成员与类相关联,可以通过类名访问,也可以通过对象访问
实例成员与相应的对象关联,只能通过对象访问,不能通过类名访问
class A {
static int numberA = 100;
}
class B {
static int numberB = 200;
public static void main(String[] args) {
A a = new A();
System.out.println(a.numberA);
B b = new B();
System.out.println(b.numberB);
}
/**
* 编译之后的字节码文件 B.class
* 使用对象访问静态成员,javac编译成“类名.静态成员”
* class B {
* static int numberB = 200;
*
* B() { }
*
* public static void main(String[] args) {
* A a = new A();
* System.out.println(A.numberA); // javac编译成“类名.静态成员”
* B b = new B();
* System.out.println(numberB); // 本类中访问静态成员,省略类名
* }
* }
*/
}
三、对象共享静态变量,对象独占实例变量
分配给不同对象的实例变量占有不同的内存空间,改变其中一个对象的实例变量不会影响其他对象的实例变量
分配给不同对象的类变量占有相同的一处内存,改变其中一个对象的这个类变量会影响其他对象的这个类变量
class B {
int n; // 实例变量
static int sum = 0; // 静态变量
public void setN(int n) {
this.n = n;
}
int getSum() {
for (int i = 1; i <= n; i++) {
sum += i;
}
return sum;
}
}
public class Test {
public static void main(String[] args) {
B b1 = new B();
b1.setN(3);
B b2 = new B();
b2.setN(5);
System.out.println("b1-sum:" + b1.getSum()); // 1+2+3=6
System.out.println("b2-sum:" + b2.getSum()); // 6+1+2+3+4+5=21
}
}
四、静态不能访问实例,实例可以访问静态
静态方法只能操作静态变量,调用静态方法
实例方法可以操作实例变量、静态变量,调用实例方法、静态方法
class A {
private String str; // 实例变量
public static int num = 10; // 静态变量
public static void method() {
// 静态不能【直接】访问实例
// 在静态方法中创建对象,用对象访问实例成员
new A().str = "hello";
System.out.println("num = " + num);
}
}