一、Java对象与Java对象引用的区别
- 创建对象:
new IntClass();
对象分配在堆上。 - 声明一个对象引用:
IntClass ic;
对象引用分配在栈上。 - 初始化对象引用:
ic = new IntClass();
例1:
对象内存空间分布:
IntClass ic = new IntClass();
实质是将创建的IntClass对象的地址赋给对象引用ic,从此ic与该对象关联,通过ic即可操纵该对象。
例2:
对象作为参数的特点:
普通数据类型作为参数传递是值传递,而对象是引用传递。
public class Test{
private static int a;
public static void main(String [] args){
modify(a);
System.out.println(a);
}
public static void modify(int a){
a++;
}
}
输出:
本程序输出为0,因为a++是对形式参数进行自增,而不是类属性 a进行自增。
例3:
对象的引用传递举例:
对象是引用传递,当对象作为参数传递时,传递的是对象的地址。
class IntClass{
int value;
}
public class test {
private static int a;
public static void main(String [] args){
IntClass a = new IntClass();
modify(a,8);
System.out.println(a.value);
}
public static void modify(IntClass s, int val){
s.value = val;
}
}
输出:
二、java对象的创建与C++对象创建的区别
Java
在 Java 中,我们可以通过如下方式定义变量:
Dog dog;//定义标识符s,没有实际空间
Dog dog = new Dog(); //定义dog,并绑定到新创建的对象
JVM在进行内存管理时,首先会在栈中给dog分配一个空间,当new Dog()后会在堆中开辟对象的实际空间,然后将dog指向堆中的空间。
C++:
在C++中,变量也可以同上来定义,但含义不同:
Dog dog; //定义标识符dog,并在栈中申请空间(第一种方法)
Dog * dog = new Dog(); //定义dog,并在堆中申请空间,过后需手动释放内存(第二种方法)
第一种方式:
dog是被存储在栈中的,占用的大小是Dog类中成员变量占用内存的和,此处不包括成员方法,因为成员方法是存放在公共存储区以便所有该类的对象都可以访问的。
第二种方法:
该方式使用了指针,在定义dog时在栈中开辟一个4字节的空间,new Dog()时在堆中开辟一块空间,然后将该空间的首地址赋值给dog,这样,通过*dog就可以找到对象在堆中的任何成员方法了。
区别总结:
两种语言里都含有 new 操作符,但它们的含义不相同。
Java :只有当你使用 new 操作符时,才会真正在内存中申请一块空间,创建一个新对象,并将该对象绑定到你所定义的变量名上。其它情况下,要么是将已有对象绑定到某个变量名上,要么就是定义的变量名是个空引用,没有绑定任何对象。
也就是说,定义变量名只是创建了一个新的标识符,跟创建对象没有关系,创建对象必须通过 new 来完成,只有创建对象时才会申请内存空间。
C++ :当你定义了一个变量 s 时,即使你没有给它赋值,也意味着你不但创建了一个新的标识符,同时还在栈中申请了对应的内存空间。
因此,C++ 中定义的变量名不仅仅是个标识符,还自动关联着栈中的一块内存空间。
而 C++ 中的 new 操作符表示的是在堆中申请内存,因为栈中的内存在运行时期大小是固定且有限的,因此需要动态内存分配的时候就需要用 new 来实现。这类似于 C 里面的 malloc 函数,只不过 new 操作符还封装了其它的操作。
总结而言,Java 中的变量名仅仅是一个用于引用内存中实际对象的标识符,如果你没给它关联对象,它就为空引用。而 C++ 中的变量名(非指针类型),虽然也是标识符,但却始终关联着实际的内存空间,当我们看到一个变量(非指针类型)时,就知道它代表着一块实际的内存空间。