A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 鲍亚坤 中级黑马   /  2012-3-26 21:17  /  1680 人查看  /  4 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

为什么不能从一个静态方法内对非静态方法的调用?

4 个回复

倒序浏览
程序最终都将在内存中执行,变量只有在内存中占有一席之地时才能被访问。

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

在一个类的静态成员中去访问其非静态成员之所以会出错是因为在类的非静态成员不存在的时候类的静态成员就已经存在了,访问一个内存中不存在的东西当然会出错
回复 使用道具 举报
程序最终都将在内存中执行,变量只有在内存中占有一席之地时才能被访问。

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

在一个类的静态成员中去访问其非静态成员之所以会出错是因为在类的非静态成员不存在的时候类的静态成员就已经存在了,访问一个内存中不存在的东西当然会出错:

而类又是在什么时候加载的呢?

    由引导类加载器负责加载的核心类比如 String 类在 JVM 启动时(main 方法开始执行前)就会被加载,其它类在使用前(new 它对象或调用其静态方法访问静态域等等前)会被动态加载,要注意的是子类被加载前它的所有超类要根据由父到子的顺序被逐一加载。

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[])
    {
        System.out.println("b.a="+B1.a);
        System.out.println("b.a="+A1.a);
        new B1().print();
    }
}

就这段代码说一下.

就你上面的代码说一下:
当你在doc环境下输入:
java TestStatic时,
虚拟机会先加载TestStatic类,此时虚拟机会先看看TestStatic类有没有静态的字段,
没有,直接执行main方法。
main方法中第一句代码是打印B1.a,
虚拟机便会去找类B1,找到类B1时,虚拟机发现B1的父亲是A1,
于是父亲优先,先加载A1,
同样,在加载A1时,会看看A1中有什么静态的东西,有,
static int a = 5;
a是静态的,先加载,当把静态的字段加载完后,一个类就算加载完了,
所以A1已经加载完毕,以后不用在加载了。
父亲加载完了,轮到B1了,同样先看看里面有什么静态的字段,有,
static int a = 8;
此时B1也加载完毕了。
第一条打印语句到此时也执行完毕了,
轮到第二条打印语句了。
当执行new B1().print();这句时,
会发生动态绑定,
此时会有一个代表B1对象的this对象传递给print()方法,
所以print()方法中的
System.out.println(a);
其实是,
System.out.println(this.a);
会打印出一个8出来。
至于super.a就简单了,
打印父类中的a,
结果是5.
到此,main()方法执行完,整个程序退出
回复 使用道具 举报
静态方法是属于类的,于是在类加载进代码区的时候就初始化了;
而非静态方法是属于对象,而对象是通过new在变量区的堆中开辟内存
这个时候没有对象,是没有办法调用非静态方法的。
回复 使用道具 举报
被static修饰的方法是随着类的加载而加载的,也就是说static方法先加载了,而非static方法有可能还没有被加载,所以在它的内部调用非static方法逻辑上是说不通的。
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马