(转载)为什么不能从static方法调用非static的方法或变量?

http://blog.csdn.net/zhouwubin123/article/details/6623308

Java开发人员一定遇到过,在eclipse开发环境中,在包括main方法在内的static方法中调用某非静态变量,会编译出错。

public class StaticDemo {
	int x;
	void fun() {
		System.out.println("this is fun()");
	}
	public static void main(String[] args) {
		x = 5;		//	报错,不能被访问
		fun();		//	报错,不能被访问
	}
}

在static方法中调用非静态变量x和非静态方法fun()的出错信息如下图所示:



究其原因,我们来做如下分析:

任何程序最终都是在内存中执行的,变量只有在内存中占有一席之地时才能被访问,不在内存中的变量就不能被访问。类的静态成员(变量和方法)都属于类本身,在类加载的时候就会分配内存,可以通过类名直接访问;

非静态成员(变量和方法)属于类的对象,所以只有在类的对象产生(创建类的实例)时才会分配内存,然后通过类的对象(实例)去访问。

public class StaticDemo {
	static int x;
	static void fun() {
		System.out.println("this is fun()");
	}

	public static void main(String[] args) {
		StaticDemo.x = 5;		//	可以用类名直接访问静态成员
		fun();				//	在类体内也可以直接访问
	}
}

由于静态成员在类加载的时候就会被分配内存,而非静态成员则不会。因此,在一个类的静态成员中去访问其非静态成员会出错,是因为在类的非静态成员不存在的时候,类的静态成员就已经存在了,访问一个内存中不存在的东西当然会出错。

而类又是在什么时候加载的呢?核心类(比如String类)在 JVM 启动时(main 方法开始执行前)就会被加载,其它类在使用前(实例化对象、调用其静态方法、访问静态域等前)会被动态加载。

需注意:子类被加载前,它的所有超类要根据由父到子的顺序被逐一加载。

如下例子:

class A1 {
	public static int a = 5;
}

class B1 extends A1 {
	public static int a = 8;

	void print() {
		System.out.println(super.a);
		System.out.println(a);
	}
}

使用一个测试类:

public class TestStatic {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		System.out.println("b.a="+B1.a);
                System.out.println("b.a="+A1.a);
                new B1().print();
	}
}

最终的运行结果如下:

b.a=8
b.a=5
5
8
代码解析: 
当你在dos环境下输入:java TestStatic时, 

(1)JVM会首先加载TestStatic类,此时JVM会先看看TestStatic类是否存在static字段,没有,直接执行main方法; 

(2)main方法第一句是打印B1.a, JVM便会去找类B1,找到B1时,发现B1的父类是A1,于是父亲A1被优先加载;

(3)在加载A1时,会扫描A1中是否存在static的成员(静态变量、静态方法),发现存在静态变量a(static int a = 5) ,先加载,当把所有static的字段加载完,一个类就加载完成了,以后就无需再加载了; 

(4)父亲加载完成了,才轮到子类B1的加载,同样先扫描B1中是否存在static的字段,发现存在静态变量a(static int a = 8),加载a,此时B1也加载完毕了; 

第一条print语句到此时也执行完毕了。 

轮到下一条print语句了(new B1().print()),当执行这句时,会发生动态绑定,此时会有一个代表B1对象的this对象传递给print()方法,所以print()方法中的 System.out.println(a); 其实是System.out.println(this.a),会打印出一个8。至于super.a就是打印父类中的a,结果是5。
到此,main()方法执行完,整个程序退出。
  • 12
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值