java设计者的意图是想使程序员不要去关心对象的内存表示,这样才能使java更容易使用,但我们了解一些存储的细节和原理会有助于我们设计出更合理的代码。
例类:
* class A{
* private int x;
* private static int y;
* private void f(){...}
* private void g(int k){...}
* private static void h(){...}
* }
* ...
* new A();//实例化
A类中有数据有方法,有静态的和非静态的,我们拿该类创建对象,内存中的对象将有哪些内容呢?这将涉及到A类型对象占用多大内存。
我们逐行的来看A类中定义的数据和方法是保存在内存中的什么位置。
private int x; //存放在堆区的A类型对象中
private static int y; //存放在静态数据区
public void f(){...} //存放在方法区
private void g(int k){...} //存放在方法区
private static void h(){...} //存放在方法区
在java中有一个专门的内存空间是全局的称为 静态数据区,用来存储所有类的静态数据(该区不包含方法)。
在java中还有一个专门的内存空间叫 方法区也是全局的,所有类的所有方法都存在方法区中,包含 普通方法和静态方法都存在方法区.
综合上述我们知道A类型的对象是很小的,在我们这个例子中A类型对象只包含了int x;可见对象并不会占用很多的内存。
为什么 static int y;不包含在对象中呢?
因为y是静态数据,静态数据全局只有一份,一个类只对应一个y变量,将来无论有多少个A的实例y变量都只有一份,既然这样就没必要让y跟随对象存储.
为什么方法不存储在对象中呢?
我们创建了两个对象可以看出这两个对象中都有一个int x;这个值可以是不同的,比如一个对象中的可以是5另一个可以是6,但方法就是要执行的代码,这个代码必然是相同的,不管我们有多少个对象都不能够改变方法的代码,方法的代码在整个程序的运行过程中是不变的,既然方法是不变的就没必要为每个对象都存储一份方法这样就太浪费内存。
那么 逻辑上我们可以认为对象是数据加上方法的复合体,可以说数据和方法共同组成了对象,这仅仅是在逻辑上的一种认识 ,真正的存储我们没有必要这样做,只要保证逻辑上的效果就可以了。
下面看一下有继承情况下对象是如何存储的。
* class A{
* private int x;
* }
* class B extends A{
* private int x;
* public int y;
* }
* class C extends B{
* private int z;
* }
以上C类从B类继承,B类从A类继承,A类好像没有继承任何类,实际上它是从一个叫作Object的类继承的, java中任何类都要有一个继承类,如果我们 不写默认都是从Object类继承的。
那么在这种情况下我们来创建C类型对象,我们来看C类型对象会包含哪些数据。
显然根据前面的分析C类型的对象应该包含C类中所定义的非静态数据也就是int z;,因为继承了B类那么同时也要包含在B类中的非静态数据,不仅仅 包含public的数据也包含private的数据,还要包含祖先类的非静态数据,所以这里会产生了两个int x;,java自己是有办法区分哪个x属于哪个类的这里我们先不管,除了这些还有Object类也有数据,那么也会包含从Object类继承来的东西。
所以各类实例的对象将包含的数据是:
C类 -> B类 -> A类 -> Object类
Object数据 Object数据 Object数据
int x; int x; int x;
int x; int x;
int y; int y;
int z;
这里有一个现象,假如我们只看以上类的继承的部份数据,我们可以把C类对象当作B类型对象对待或当作A类型的对象看待,由此可见一个 对象可以被当作任何它的祖先类型来对待。正是因为这个特点才很方便的支持了多态效果,就如我们知道可以把苹果当作水果或当作食物来看待一样,这在逻辑上是非常合理的。
例类:
* class A{
* private int x;
* private static int y;
* private void f(){...}
* private void g(int k){...}
* private static void h(){...}
* }
* ...
* new A();//实例化
A类中有数据有方法,有静态的和非静态的,我们拿该类创建对象,内存中的对象将有哪些内容呢?这将涉及到A类型对象占用多大内存。
我们逐行的来看A类中定义的数据和方法是保存在内存中的什么位置。
private int x; //存放在堆区的A类型对象中
private static int y; //存放在静态数据区
public void f(){...} //存放在方法区
private void g(int k){...} //存放在方法区
private static void h(){...} //存放在方法区
在java中有一个专门的内存空间是全局的称为 静态数据区,用来存储所有类的静态数据(该区不包含方法)。
在java中还有一个专门的内存空间叫 方法区也是全局的,所有类的所有方法都存在方法区中,包含 普通方法和静态方法都存在方法区.
综合上述我们知道A类型的对象是很小的,在我们这个例子中A类型对象只包含了int x;可见对象并不会占用很多的内存。
为什么 static int y;不包含在对象中呢?
因为y是静态数据,静态数据全局只有一份,一个类只对应一个y变量,将来无论有多少个A的实例y变量都只有一份,既然这样就没必要让y跟随对象存储.
为什么方法不存储在对象中呢?
我们创建了两个对象可以看出这两个对象中都有一个int x;这个值可以是不同的,比如一个对象中的可以是5另一个可以是6,但方法就是要执行的代码,这个代码必然是相同的,不管我们有多少个对象都不能够改变方法的代码,方法的代码在整个程序的运行过程中是不变的,既然方法是不变的就没必要为每个对象都存储一份方法这样就太浪费内存。
那么 逻辑上我们可以认为对象是数据加上方法的复合体,可以说数据和方法共同组成了对象,这仅仅是在逻辑上的一种认识 ,真正的存储我们没有必要这样做,只要保证逻辑上的效果就可以了。
下面看一下有继承情况下对象是如何存储的。
* class A{
* private int x;
* }
* class B extends A{
* private int x;
* public int y;
* }
* class C extends B{
* private int z;
* }
以上C类从B类继承,B类从A类继承,A类好像没有继承任何类,实际上它是从一个叫作Object的类继承的, java中任何类都要有一个继承类,如果我们 不写默认都是从Object类继承的。
那么在这种情况下我们来创建C类型对象,我们来看C类型对象会包含哪些数据。
显然根据前面的分析C类型的对象应该包含C类中所定义的非静态数据也就是int z;,因为继承了B类那么同时也要包含在B类中的非静态数据,不仅仅 包含public的数据也包含private的数据,还要包含祖先类的非静态数据,所以这里会产生了两个int x;,java自己是有办法区分哪个x属于哪个类的这里我们先不管,除了这些还有Object类也有数据,那么也会包含从Object类继承来的东西。
所以各类实例的对象将包含的数据是:
C类 -> B类 -> A类 -> Object类
Object数据 Object数据 Object数据
int x; int x; int x;
int x; int x;
int y; int y;
int z;
这里有一个现象,假如我们只看以上类的继承的部份数据,我们可以把C类对象当作B类型对象对待或当作A类型的对象看待,由此可见一个 对象可以被当作任何它的祖先类型来对待。正是因为这个特点才很方便的支持了多态效果,就如我们知道可以把苹果当作水果或当作食物来看待一样,这在逻辑上是非常合理的。