Java中的引用与C中的指针
在整理Java时,感觉Java的引用和C的指针很类似,都是保存地址。然后在掘金的文章 java中的应用于c中的指针中,找到了一个比较合理的解释,特此码住。注意,本文仅为转载、记录,仅供个人学习引用。
【补充】:
Java的参数传递是按值传递(call by value
)
可以给出一个反例,说明Java不是按引用传递:
public static void swap(Employee x, Employee y) {
Employee temp = x;
x = y;
y = temp;
}
Employee a = new Employee("Alice", ...); // new a instance
Employee b = new Employee("Bob", ...);
swap(a, b);
// Do you think a would now reference to Bob? No
解释如下,Java参数传递的仍然是a
和b
的一份拷贝(copy),所以x
和y
分别指向a
和b
所引用的对象。但是在swap
方法中只是交换了x
和y
,也就是x
现在指向Bob
,而y
指向Alice
。最后离开方法,x
和y
被丢弃,而a
和b
仍然指向本身。
所以,按值传递是拷贝它的值传递给参数,而按引用传递,则是将它的地址传递给参数。
指针
首先要弄清楚指针和c中的指针是不一样的,前者是概念,后者是具体实例。
换句话说,C中的指针只是指针中的一种,其他语言也有指针,比如C++。但是我们同别人交流的时候,大都不会从概念上去交流,一般会选择其中一个实例去说,这个实例大部分时候都是C中的指针。久而久之,概念和实例被模糊化,C中的指针也成为了指针本身。
在这里我还是有必要给自己的大脑提个醒,不要将概念和实例混为一谈,要分清两者的界限。
指针定义
既然这么多语言都有自己的指针,那么这个指针到底是什么有没有一个明确的定义。
这是维基百科上的解释。
一句话解释就是指针就是一个值,而这个值是某块内存的地址,通过这个值,就可以找到这块内存。
C语言中的指针
C语言的指针具有以下特点:
- C语言的指针可以指向内存的任何地方。
- C语言的指针可以参与数值运算,加法、减法。
- C语言的指针还可以指向指针,以及指向指向指针的指针(因为指针就是一个值,也要存在内存中,所以它也有一个内存地址)
以上特点反映了指针寻地址的特性。
另外,指针这个东西,只关心内存的地址,不关心内存存的是什么东西,如果该地址中的对象被搬走了,指针不会自动改变指向。
Java中的引用
在了解引用之前,首先让我们先了解一下,java的引用类型。
在JAVA中数据可以简单分为两种类型,基本类型和引用类型。继续细分的话基本类型又可以分为四种整数型 byte、short、int、long 两种浮点型float、double 一种字符类型char 一种布尔型 boolean。引用类型可以说有无数种,包括String、数组、object等等。
在java种只有引用类型才有引用
基本类型内存分配
在基本类型中,你定义变量 int i = 0; 那么它在内存里的分配是这样的:内存里分配了一块空间,这块空间的名字是i,里面的内容是0
当你使用i的时候就可以访问这块空间里的内容。
引用类型内存分配
与基本类型内存分配不同,引用类型在内存分配时,会分配两块内存,一块存储引用,一块存储值。
比如在定义String s; 或者String s = null; 时。系统会分配一块内存用来引用值(在本例中装的是空值null,也就是什么也没有装)
至于具体这个s(引用)分配在哪,要看他被声明的位置。如果s被声明为局部变量,那s(引用)就在栈空间。如果不是局部变量,那就不在栈上分配。
当你为s赋值的时候,s = new String(“wqlm”);
情况发生了改变,引用有了一个明确的指向位置,引用的值也不再是空值。
从上例可以看到在定义变量时,引用没有实体,不占空间,只有在变量赋值时,引用才有实际值
Java引用的实质
从上面可以看出,java的引用和c的指针很相似
java的引用也是一个值,但是这个值不是某块内存的地址,而是某个值所在内存的地址。他关注的是值,当值搬家后,引用也会跟着改──内存碎片整理
其实引用就是一个封装过的指针,它屏蔽了指针的复杂性,在编译器的实现中,引用最后还是会被转成指针
java的引用与c的指针的区别:
- java的引用是某个值所在内存的地址。
- c的指针是某块内存的地址。
- c的指针的值可以认为是个int类型,长度一般是计算机字长。
- java的引用,声明变量时(不赋值),不占空间。(原因见引用类型内存分配)
- java的引用初始值为 null。c的指针是int,如不初始化指针,那它的值就不是固定的了。
- java的引用不可以计算。c的指针是int,他可以计算,如++或–,所以经常用指针来代替数组下标。
番外 Java的引用传递
java的方法在传递参数时,一般有两种情况
– 参数是基本类型,直接将基本类型的值传递过来
– 参数是引用类型,将参数的引用值copy一份传递过来
因此,也可以说java只有值传递,所谓的引用传递,传递的是引用的值