网上看到的几个有关静态方法与非静态方法的问题,有些地方我也不太懂,望高手指教.如下:
1.是不是静态方法和非静态方法都会在程序被装入内存时,载入程序段(或者说静态方法和非静态方法都有一个内存拷贝)?
2.是不是静态方法在被调用时调用相同的那段预先载入的代码,而非静态方法,在每次初始化一个实例时都会重新创建一个该方法的拷贝到程序段?
3.一个类的静态成员、静态方法、非静态成员、非静态方法在该类被装入内存时,哪些有内存分配,分别存放在哪里,各自的生命周期是怎样的?在初始化一个类时,又是什么状况呢?
4.数据段和全局区有什么区别?
问题挺多的,呵呵,俺没多少分数了,请见谅。

解决方案 »

  1.   

    类的静态成员是放在Java虚拟机的方法区,而类生成的对象是放在堆中。方法区和堆中的信息都是所有线程共享的,因此必须设计为线程安全的。我在我的博客中写了一篇原创文章,《认识Java虚拟机的内部体系结构》,相信对你理解这些有帮助。
      

  2.   

    不管静态还是动态方法,都只有一份. 只不过动态方法调用的时候其实会把this指针传过去. 因为Class对象只有一份.而Object可以有多份.
      

  3.   

    所有的方法本质上都是“静态”的,只不过非静态方法有一个隐藏参数“this”罢了。
      

  4.   

    静态(变量、方法)是类的所有对象共有的,内存中只有一份拷贝,不单独属于某一个具体的对象,所以用 类名 静态变量名(或静态方法名),或 对象名.静态变量名(或静态方法名)来访问。非静态(变量方法)则是每一个对象都有自己的一份,所以用 对象名.非静态变量(或非静态方法名)来访问。可以看看北京尚学堂的JAVA教学视频,里面有讲到内存分析,可以看看,挺有帮助的。
      

  5.   


    赞同,但一直不知道其具体内存分配。 当年有个同事说一个内中重要是没有应用到类的field的方法都应该static,说是方法就只有一个copy,节约内存空间。当时我说这违反面向对象原则,但是没有很好驳倒他。
      

  6.   

    静态方法有啥不好理解的!
    在编译期就已经生成地址了,在使用时直接用[call 地址]来实现函数的调用(或者类似的指令)
    由于一些非静态方法在编译期不能确定,所以就需要动态地根据对象的地址+VMT表的形式来计算出函数的地址,而后再进行call
      

  7.   

    静态块,非静态块,构造函数三者在jvm中的运行顺序请先看下面一段代码(此时,main方法中没有创建对象)class TT{
        {
            System.out.println("feijingtaisuper");
        }
        static{
            System.out.println("jingtaisuper");
        }
        
        public TT(){
            System.out.println("gouzaosuper");
        }
    }
    public class TestBlaock extends TT {
        
        {
            
            System.out.println("feijingtai");
        }
        
        
        static{
            
            System.out.println("jingtai");
            
        }
        
        public TestBlaock(){
            System.out.println("gaozao");
        }    public static void main(String[] args){
            
        }
    }
    该段代码运行结果如下:
    jingtaisuper
    jingtai
    结果说明:static块是在类加载的时候最先执行的代码块,因为static是和类相关,而不是和对象相关的,所以即使没有创建对象,只要jvm加载这个类,就一定要先去执行static块;(并且是先执行父类的,再执行子类的,如果object类中有static代码块,那么任何类一定先去执行object类中得static代码块)
    下面在main函数中增加下面一段代码:  new TestBlaock();
    则其运行结果如下:
    jingtaisuper
    jingtai
    feijingtaisuper
    gouzaosuper
    feijingtai
    gaozao结果解释:因为我们这次创建了一个对象,所以非静态块,构造函数也同时执行了;
    运行顺序:父类静态块,子类静态块,父类非静态块,父类构造函数,子类非静态块,子类构造函数;
    问题1:为什么一旦创建了对象,非静态块才得以执行:因为非静态块没有static修饰,那么他即是和非静态成员变量一样,是和对象相关的,他属于具体的一个对象,而不是整个类,所以当没有对象时,是不会执行非静态块的;
    问题2:既然静态块是先执行父类的,接着立马去执行子类的静态块,那为什么不是按照执行完父类的非静态块,接着立马去执行子类的非静态块呢,反而是执行完父类的非静态块,接着去执行父类的构造函数去了呢?
    回答:因为当jvm要创建子类的一个对象时,必须要先创建父类的对象,之后才可以有子类的对象,这也符合自然法则(现有父亲,才有儿子)。而当执行完了父类的非静态块后,如果不执行父类的构造函数,却仅接着就去执行子类的非静态块的话,那么父类的对象还没有创建完成(因为父类的构造方法没有执行呢),子类的对象就不能得以创建,而子类的对象都还没有存在,当然不能去执行与子类对象相关联的子类非静态块了。
      

  8.   

    方法只有一个copy,不只是节约空间,也体现了面向对象的原则。对象有共通的行为,这也是对象的重要特征之一,难道你不认为这也很好体现了面向对象的原则吗?