前言
在学习Java中变量的数据类型时,发现其分为2大类:基本数据类型、引用数据类型。
其中,属于“引用数据类型”的有:String、数组、类、接口。
相比C语言,Java中的“引用数据类型”,和C语言中的“指针”比较相似,所以这里将两者进行对比分析。
1. Java中“基本数据类型”和“引用数据类型”变量在内存分配时的不同
- 对于“基本数据类型”的变量:当你定义变量
int i = 0;
那么它在内存里的分配是这样的:内存里分配了一块空间,这块空间的名字是i,里面的内容是0。当你使用i的时候就可以访问这块空间里的内容。
- 对于“引用数据类型”的变量:引用类型的变量,在内存分配时,会分配两块内存,一块存储引用,一块存储值。进一步,如果是通过new来创建引用变量,则两块内存分别是栈(来存储引用变量)和堆(来存储引用变量所指向的值);如果不用new,则两块内存都在栈中。
例如:
不同方式定义字符串时堆和栈的变化:(参考:深入解析Java new运算符)
public class Test {
public static void main(String[] args) {
String a = "C语言中文网";
String b = new String("C语言中文网");
String c = "C语言中文网";
String d = new String("C语言中文网");
System.out.println(a == b);
System.out.println(a == c);
System.out.println(d == b);
System.out.println(a);
a = "Java";
System.out.println(a);
}
}
输出结果:
false
true
false
C语言中文网
Java
解析:
-
String a;
只是在栈中创建了一个 String 类的对象引用变量 a。
-
String a = "C语言中文网";
在栈中创建一个 String 类的对象引用变量 a,然后查找栈中有没有存放“C语言中文网”,如果有则直接指向“C语言中文网",如果没有,则将”C语言中文网“存放进栈,再指向。
-
String a = new String("C语言中文网");
不仅在栈中创建一个 String 类的对象引用变量 a,同时也在堆中开辟一块空间存放新建的 String 对象“C语言中文网”,变量 a 指向堆中的新建的 String 对象”C语言中文网“。
==
用来比较两个对象在堆区存放的地址是否相同。根据上面的输出结果,我们可以看出:
- 使用 new 运算符创建的 String 对象进行
==
操作时,两个地址是不同的。这就说明,每次对象进行 new 操作后,系统都为我们开辟堆区空间,虽然值是一样,但是地址却是不一样的。所以第三个输出为false。
- 当我们没有使用 new 运算符的时候,系统会默认将这个变量保存在内存的栈区。如果变量的值存放在栈中,使用
==
比较时,比较的是具体的值。如果变量的值存放在堆中,使用==
比较时,比较的是值所在的地址。因此在变量 a 与变量 c 进行==操作的时候,返回 true,因为变量 a 和变量 c 比较的是具体的值,即“C语言中文网”。
- 在改变引用变量 a 的值后(如 a = “Java”),再次输出时,我们发现输出的结果是”Java“。事实上原来的那个“C语言中文网”在内存中并没有清除掉,而是在栈区的地址发生了改变,这次指向的是”Java“所在的地址。
- 如果需要比较两个使用 new 创建的对象具体的值,则需要通过“equal()”方法去实现,这样才是比较引用类型变量具体值的正确方式。
2. C中“指针”的特点
- C语言的指针可以指向内存的任何地方。
- C语言的指针可以参与数值运算,加法、减法。
- C语言的指针还可以指向指针,以及指向“指向指针”的指针(因为指针本身也是一个变量,也要存在内存中,所以它也有一个内存地址)
- 指针,只关心其所指向内存的地址,不关心内存存的是什么东西,如果该地址中的数据被搬走了,指针不会自动改变指向。
3. Java中“引用”的特点
- java的引用是某个值所在内存的地址。其关注的是对应值的本身,而不是该值在内存中的地址,当值搬家后,引用也会自动跟着改。(这一点和指针不同)
- java的引用,声明一个引用变量时(不赋值),不占空间。
- java的引用初始值为 NULL。(C中指针的值如果不初始化,其值不确定,会变为野指针,很危险)
- java的引用本身不可以参与计算。(C的指针的数据类型是int,其可以参与计算,如++或–,所以经常用指针来代替数组下标)
4. Java的参数传递
java的方法在传递参数时,一般有两种情况:
- 参数是基本数据类型,就直接将基本类型的值传递过来。
- 参数是引用数据类型,将参数的引用值copy一份传递过来。
所以可以说java只有值传递,所谓的引用传递,传递的是引用的值。
5.参考
java中的引用与c中的指针