所谓"类不占用内存空间,其生成的对象才占用内存空间"主要指编译层面的说法还是运行层面的说法?意思是这个内存是以产生代码得其说还是以代码调到内存运行时得其说?多谢赐教!

解决方案 »

  1.   

    1.运行层面的说法,编译仅仅是将源文件转化为.class文件的过程 
    2.以代码调到内存运行时得其说
      

  2.   

    我想类怎能不占用空间呢?只是说是java 虚拟机为类分配了特定的空间专门存放类信息:如常量,属性,方法信息等。当创建对象是虚拟机读取类信息,然后为对象分配特定大小的内存。只是这些是虚拟机
    幕后为我们做的。 
      详细请参考《java虚拟机》 了解虚拟机还是很不错的。 
      呵呵 
      

  3.   

    针对Great_qiang说的我想问的是编译后的java程序 .class文件还是类吗?我原初也以为是,但后来感觉应该不是,而已算做对象了,起码是已被分配了内存布局的实际代码了。这是我的看法也不知对否,请说你的看法吧。
      

  4.   

    编译后的java程序   .class文件已经被类装载器装载了,已经存储到内存中的一个内存区了啊。
    对象有对象的布局区,类也有类的布局区。
    我是这样理解的,不知对否
      

  5.   

    看来人还是要象孔子说的三人行,我俩都行不通,得请第三者了。不过我的理解还是认为那些被装载的 .class文件本身就是具有真实代码的对象体了,当然是基于java字节码的对象体。不过实在我也还感觉模糊,有请第三者出场了!
      

  6.   

    做了一个实验 大家有兴趣的看看
     //Data.java
    public class Data {
     private  static int  i = 1;
      public Data () {  
      System.out.println("creat:" + i);
      i++;  
      }
    }
     //Data2.java
    public class Data2 {
      public Data2 () {
      System.out.println("creat Data2;");
      }
    }//Text.java
     import  java.io.*;
    public class Text {
     private static BufferedReader  stdIn =
    new  BufferedReader(new  InputStreamReader(System.in));
      public static void main(String[] args) throws IOException {
      Data first  = new Data();
      System.out.println("first");
      String a = stdIn.readLine(); // 运行到这一行是将磁盘中的文件删掉  程序仍继续运行
      Data secend  = new Data();   //运行
     
              Data2 third  = new Data2();  // 此处发生错误 NoClassDefFoundError   说明前面每用到的类
                                           // 没有装载到内存中                     }
    }
    也就是说类的信息在内存中,其中的方法在方法区中。
    当用到使才装载。
        
      

  7.   

    源程序中一个文件名为A.java的类 class   A{...}   被编译成   A.class文件,我想问的是谁才是类模板,是A.java还是A.class?还是两个都是? 并且在删除A.java文件情况下,我们还可以在主程序中进行 A aa=new A(),还可以class B extends A(){} ,也就是说此时是A.class在起作用啊,看得出A.class很象类啊。
      

  8.   

    我个人认为,:A.class已经编译完成了,而你要是把A.java 删了,也不影响A.class的运行了,  而你要是还继续
    调用A.class,来用做以后的类的编译也和 A.java 没关系了,  所以说,A.class不是类~  是模板。 
      

  9.   

    谢谢!哪位再说说呢?先谢谢!,我的主要意思是编译后的.class类文件好象跟编译前的源文件中的类具有一样功能啊,是这样吗?如果真是这样,那么它们就有换汤不换药的意思啊,对吧?意思也就是不过用英文替代中文表达而已.
      

  10.   

    我觉得这句话有点问题,JVM的内存是分4块管理的,其中类在用到的时候是由类加载器加载到文本段上的,所以类不占用内存的说法……,不过在一个应用中,一个类只加载一次,然后无论产生多少这个类的对象,都是对象本身占用的空间(在堆上分配),不会再消耗文本段的内存
      

  11.   

    18楼的回答有点中肯,言语中包含着这样的意思:编译后的java程序还带着一个独立的类文件群(.class形式),而且认为些类文件就是作为所谓的类模板来提供运行时new成对象的,对吧?
      

  12.   

    呵呵!我注意到这个帖子了,这个问题也不是Java特有的,C++中也是这样的。在C++中,类编译之后生成代码,当程序开始运行时,这些代码是和其他代码部分,例如main函数和其他外部函数编译之后的代码,一起放在程序所占内存空间的代码区的。而对象产生之后,它是在程序的栈区里申请一个空间,该空间大小等于所有成员变量所需空间制和,例如,如果类有4个成员变量,每个占4个字节,则对象的空间就是16个字节。注意了,在对象的空间里,并没有成员函数的位置。注意,程序还有一个堆区,是用来存放动态申请的变量的。在Java中,每一个类都会生成代码,分别放在该类的class文件里,但是,它们并不会一次性全部进入内存,而是根据程序的需要依次加载的,例如,你的主类是A类,程序运行时从A类的main方法开始,所以,A类的代码会首先被加载入程序所占内存空间的代码区,当运行到某一条语句,需要使用B类时,该类的代码才被加载,同样进入程序的栈区。
    当某个类的对象被创建时,因为Java的对象都是动态产生的,所以,在程序的堆区里为这个对象分配空间,
    同样的,对象空间中也仅仅存放成员变量,和方法无关。
      

  13.   

    OOP的典型问题了。
    对于OOP编译出来的都是类,而此问题是指对类及其引用对象的操作,所以,当然应该是运行层面的。
    而老一些的面向结构的编程编译出来的是应用程序,便不会产生这个问题了,但变量在内存中的使用分配问题依然是以运行层面的。
      

  14.   

    想继续问lixkyx的是怎么展开来理解"Java的对象都是动态产生的"这句话,我意思是假如类A有16字节的变量,那么在类A被生成对象之前这16字节的变量存在哪里.我的理解应该是保存在编译后的程序里,也就是在这个对象生成之前实际它是存在硬盘等存储介质上的.意思是诸如A aa =new A()的语句在编译时就在编译后的目标程序里占据16字节的空间,而所谓对象生成是在程序执行到需要这些变量时才把它调入内存,意思是这些对象空间在编译时就产生了,只是没被调入内存而已.是这么理解吗?
      

  15.   

    而Java与C++的区别,在于:
    C++中,一个对象一旦声明,就意味着创建了它,会在内存中分配空间给它;
    Java中,声明一个对象并不意味着创建,只有当你使用 new+构造方法 才会创建它,为它分配空间。
      

  16.   

    当然,还有另一方面的区别:
    C++中,一个对象一旦产生,就会存在到它所在的函数调用结束,如果它是在main函数里声明的,那就是存在到程序运行结束;
    Java中,一个对象产生之后,如果它从某条语句以后不再用到,那么Java的垃圾处理器会自动删除它。
      

  17.   

    这个问题还真有意思:
      现在就是说,java类 和 该类生成的对象 之间,哪个占用内存? 小弟认为:类是虚拟的一个概念,对象才是现实的程序中调用的,要占用物理内存的。至于,类在java里怎么动态加载,是jvm的工作。可能是在.class里有类的编译后的调用代码,只要你在程序里要调用该类的对象,那么这个时候,类是不占用内存,占用物理内存的 应该是该类的对象.
     
      我是这么认为的.不要笑话我....
      

  18.   

    我知道程序调入内存就是一个具有真实调用关系的物理内存布局了.描述代码可能是这样一些指令串:"在这个地方安排16字节内存空间,并把她引用到某某函数",我这么比方有点道理吧?
    还有你说的编译后的程序(即.exe或.class等文件)并非真实的变量和函数调用关系的存储空间布局,而只是一些描述这些布局的指令串是吧,都是这样吗,是编译大致都是采用这样的方法吗? 另想问的是com组件是类还是对象?
      

  19.   

    另:有请lixkyx先生到 http://topic.csdn.net/u/20071206/23/84c48843-afeb-4447-980c-125d09518cb4.html
    看我在11楼的回应是否说的有点道理?
      

  20.   

    "我知道程序调入内存就是一个具有真实调用关系的物理内存布局了.描述代码可能是这样一些指令串:"在这个地方安排16字节内存空间,并把她引用到某某函数",我这么比方有点道理吧? "没错,就是这样。“还有你说的编译后的程序(即.exe或.class等文件)并非真实的变量和函数调用关系的存储空间布局,而只是一些描述这些布局的指令串是吧,都是这样吗,是编译大致都是采用这样的方法吗?  ”编译都是这样的,编译之后的每一条指令,都是计算机硬件上工作的机器指令,整个指令流的顺序执行构成了
    整个程序的运行。程序的逻辑结构、逻辑顺序等性质,包括变量和函数等概念,在可执行的机器代码里,并不存在严格的对应物。“另想问的是com组件是类还是对象?”
    com组件是对象。
      

  21.   

    一、我知道编译后肯定都是可在硬件上工作的指令,但是不是说这些指令还不是可以直接布局到内存上运行的指令,而只是操作系统用来把程序进一步布局到内存上的中间文稿,或称之程序布局规划书等。是这样理解吗?
    二、com组件根据我所查阅的资料结合我本人的理解它应该是类,是一种基于二进制代码的可重复使用的类模块,诸如Windows环境中的各类控件实际应该是一种类,比如按钮、文本框等是可以作为一种类摸板提供编程的。com组件好象可以对应java的bean组件。我是这么理解的,请你说说你的看法。
      

  22.   

    "一、我知道编译后肯定都是可在硬件上工作的指令,但是不是说这些指令还不是可以直接布局到内存上运行的指令,而只是操作系统用来把程序进一步布局到内存上的中间文稿,或称之程序布局规划书等。是这样理解吗? "不是。对于C++,编译之后的文件就是机器码文件,可以直接在机器上运行的,只不过,它的运行效果依赖于操作系统的支持你才能看到。对于Java,编译之后的文件是在Java虚拟机上执行的代码文件,其地位完全等同于在硬件上运行的C++可执行文件。“com组件根据我所查阅的资料结合我本人的理解它应该是类,是一种基于二进制代码的可重复使用的类模块,诸如Windows环境中的各类控件实际应该是一种类,比如按钮、文本框等是可以作为一种类摸板提供编程的。com组件好象可以对应java的bean组件。我是这么理解的,请你说说你的看法。”com组件我不太熟悉,这个问题还是留给个中高手来回答吧。