众所周知,Java对象的创建,通常使用new操作符来实现这一目的。new关键字的意思是“给我一个新的对象”。而创建的过程是怎样的,以下面的实例说明。
在此之前,我们首先要了解内存是怎么分配的,即我们创建的对象是怎么放置安排的。这对理解一个对象是如何创建的有很大帮助。有五个不同的地方可以存储数据:寄存器、堆栈、堆、常量存储和非RAM存储。
堆栈:对象引用就存储于堆栈中。
栈:用于存放所有的Java对象。当程序执行创建对象的语句时,会自动在堆里进行存储分配。
上实例:
class IntClass{
int value;
}
public class MyFirstJava {
public static void modifyValue(IntClass s,int val) { //2
s.value = val;
}
public static void main(String args[]) {
IntClass a = new IntClass(); //对象的创建 1
modifyValue(a,8); //2
System.out.println(a.value); //3
}
} //运行结果为 8
程序的执行过程:
从main方法入口,装载所在的类MyFirstJava,并初始化其数据成员(这段程序中没有)赋初值为0。然后就遇到了这句:
-
IntClass a = new IntClass();
意思是声明一个类型为IntClass的对象引用为a,储存在栈中,并用new关键字创建了一个IntClass的对象,在堆中开辟存储空间。把这个对象的地址赋值给栈中的a。从此对象引用a就与这个对象相关联,可以通过a来操纵这个对象。 -
调用modifyValue()这个方法。首先开辟modifyValue方法栈,里面有IntClass类型的s与int类型的val的内存空间。然后给它传参,参数分别为IntClass类型的a和int类型的值为8,对应分别赋值给形参s与val。此时s的值与a相同,为对象的地址,即也可以通过s来操纵这个IntClass类型的对象。
s.value = val;
使得对象中的value属性值为8。 -
输出a所指IntClass类型的对象的value属性值,结果为8。
对象与对象引用的关系与区别:
可以将这一情形想象成用遥控器(引用)来操纵电视(对象)。只要握住这个遥控器,就能保持与电视机的连接,当有人想改变频道或者减少音量时,实际操控的是遥控器(引用),再由遥控器来调控电视机(对象)。如下图:
a与s都是这个对象的引用
对象的创建与C++的区别
两种语言里都含有 new 操作符,但它们的含义大不相同,这与它俩的变量管理方式有关。
Java:
只有当你使用 new 操作符时,才会真正在内存中申请一块空间,创建一个新对象,并将该对象绑定到你所定义的变量名上。其它情况下,要么是将已有对象绑定到某个变量名上,要么就是定义的变量名是个空引用,没有绑定任何对象。
也就是说,定义变量名,如IntClass a;
只是创建了一个新的标识符,跟创建对象没有关系,创建对象必须通过 new 来完成,只有创建对象时才会申请内存空间。
C++ :
当你定义了一个变量 s 时,即使你没有给它赋值,也意味着你不但创建了一个新的标识符,同时还在栈中申请了对应的内存空间。
因此,C++ 中定义的变量名不仅仅是个标识符,还自动关联着栈中的一块内存空间。
而 C++ 中的 new 操作符表示的是在堆中申请内存,因为栈中的内存在运行时期大小是固定且有限的,因此需要动态内存分配的时候就需要用 new 来实现。这类似于 C 里面的 malloc 函数,只不过 new 操作符还封装了其它的操作。
总结而言,Java 中的变量名仅仅是一个用于引用内存中实际对象的标识符,如果你没给它关联对象,它就为空引用。而 C++ 中的变量名(非指针类型),虽然也是标识符,但却始终关联着实际的内存空间,当我们看到一个变量(非指针类型)时,就知道它代表着一块实际的内存空间。