Java中的对象类型像引用还是指针,谁是谁非?
作者:海枫
地址:http://blog.csdn.net/linyt
作为一名程序员,我们应该对新知识和新技术刨根问底,而不应泛泛而谈。我未曾接触到Java的时候,我想听得最多的东西还是关于Java中不存在指针的问题。此时,我会不断地想:如果Java不存在指针的话,那么是如何实现复杂的数据结构?这样的语言与VB有什么差别?如果一个静态过程式或面向对象语言,如果不存在指针的话,那它如何会得到程序员的喜爱呢?功能是何其的有限?幸好有机会和一位师弟在交流C#,当时我也没有接触过C#,不过从他的观点令我看清楚了一些问题。我还是很清楚地记得他说了一句:C#中同样有指针,不过是有限制的指针,因此在C#中把它称为引用(references)。经过对Java的学习后,我非常赞同他的那句话。即是Java中也存在指针,不过是限制的指针,因此在Java语言的规范说明里把它称为引用。下在从C++中的对象类型为依据,谈谈Java语言中的引用到底与C++中的哪种对象类型更类似。
Java的对象类型
在这里,我不泛谈程序语言原理方面的知识,如何为引用,何为指针。只以C++的对象类型为蓝本,讨论C++中对象类型与Java对象类型的异同。
C++的对象类型分为三种:对象变量,对象指针和对象引用(这里特指是C++的引用)。对象变量,与基本数据类型变量一样,分配在栈中,对象在栈的生命空间结束后,系统会自动释放对象所占用的空间;对象指针,与C语言中的指针一样,都是一个地址,它指向栈中或堆中的一个对象。对象引用是C++中与C不同之外,形象地说,引用就是一个别名,定义引用的时候必须一起初始化,不能引用不存在的对象。下面是C++中定义三种对象类型的代码:
String a(“string a”);
String *pA = &a;
String *pB = new String(“string b”);
String &c = a;
语句1中定义一个String变量a,它的内容是”string a”;语句2中定义一个String对象指针,它指向对象a(栈对象);语句3中定义一个String对象指针,不过它指向一个分配在堆中的对象。最后一个语句是定义一个String对象的引用c,它引用a,也即是说c是a的别名,即同一个变量,两个不同的名字而已。只要改变a或c,该变量内容都会发生改变的。
Java中的对象类型只有一种,那就是引用(注意是Java的引用,而非C++的引用)。下面是定义一个引用的代码。
String s = new String(“string”);
在执行此代码时,在内存空间生成的结构如下面所示:
+--------+ +-------------------------+
|引用s |--------------------à|对象内容为“string”|
+-------- + +-------------------------+
上面的语句中其实做了两件事情,在堆中创建了一个String对象,内容为”string”,在栈中创建了一个引用s,它指向堆中刚创建好的String对象。并且引用s值的改变不影响它所指的对象,只有通过它调用对象的方法对可能改变对象的内容。请看如下语句:
s = new String(“abc”);
在上面这个语句中,只改变s的值,因此不会对内容为”string”对象造成影响(不考虑垃圾回收情况)。只不过是s指向堆中的新对象而已,从指针上来说,就是s的值改变了而已。
从上面来看,Java的引用,并不与C++的引用相同,因此它不是一个别名;与对象变量也不同,它只是表示一个内存位置,该位置就是存在一个对象的位置,而不是真实的对象变量。并且从指针的意义角度来说,C/C++的指针与Java的引用却是不谋而合。它们都表是一个内存地址,都可以通过这个内存地址来操纵它所对应的对象。因此Java的引用更像C++中的指针,在下文中把它称为Java中的指针,同样也可称为Java中的引用。
Java中的指针与C++中的指针
本文开始提到Java中的指针是限制的指针,那么在这里分析Java中的指针可以执行什么运算符。
在C++的对象指针里面,出现的指针运算符主要有以下几个:*,->。
运算符*是返回指针所指向的对象,而->是返回指针所指向对象的数据成员或方法成员。由于不存在对象变量,而是通过指针来访问对象的,因此Java中不需要提供*运算符,这是Java优化了C++的一个指针问题。对于->运行符,Java的指针是提供的,不过是采用.运算符的方式提供,看起来与C++中对象变量的.运算符一样,其实意义是有不一样的地方。
如String s = new String(“abc”);
s.indexOf(“a”);
与下面C++代码等价的
String *s = new String(“abc”);
s->indexOf(“a”);
对于C++中对象变量出现的复制构造函数,“=”运算符以及“==”运算符问题同样在Java中出现。
在C++中,如果类没有定义它的“=”运算符,那么有可能会出现浅度复制,而非深度复制,Java也有类似的问题。两者要程序员采用深度复制的策略编写构造函数;如果C++中的对象没有定义“==”运算法,那么它会依次对两个变量比较它的数据成员,看是否都相等。如果定义则按用户的比较方式进行比较。在Java,Object对象定义了equals方法,这个方法是用来比较两个对象如果相等的,Object中的equals方法只是比较两个指针的值是否相等而已,要根据所指向的对象内容进行比较,那应重写该类的equals方法。
正因为Java中存在指针,所以使用Java同样能写出丰富的数据结构,java中的集合框架就是最好的例子。
上面只要谈到Java中指针与C++中指针相同或类似的部分,我觉得两者之间是有差别的,差别主要有三个。
C++中的指针是可以参与和整数的加减运算的,当一个指对指向一个对象数组时,可以通过自增操作符访问该数组的所有元素;并且两个指针能进行减运算,表示两个指表所指向内存的“距离”。而Java的指针是不能参与整数运算和减法运算的。
C++中的指针是通过new运算或对象变量取地址再进行赋值而初始化的,可以指向堆中或栈中的内存空间。Java同样是类似的,通new运算得到初始化。Java中指针只能是指向堆中的对象,对象只能生存在堆中。C语言是可以通过远指针来指向任意内存的地址,因而可以该问任意内存地址(可能会造成非法访存);Java中的指针向的内存是由JVM来分配的中,由于new运算来实现,不能随所欲为地指向任意内存。
C++中通过delete和delete[] 运算符进行释放堆中创建的对象。如果对象生存周期完结束,但没有进行内存释放,会出现内存泄露现象。在Java中,程序员不用显式地释放对象,垃圾回收器会管理对象的释放问题,不用程序员担心。Java使用了垃圾回收机制使得程序不用再管理复杂的内存机制,使软件出现内存泄露的情况减少到最低。
小结
通过上面的分析,我们可以得到这样的结论:Java中的引用与C++中的引用是不同的,并且Java中的引用更像C++中的指针。因此,可以认为Java中的引用就是指针,是一种限制的指针,不能参与整数运行和指向任意位置的内存,并且不用显示回收对象。除了Java外,就本文开头提到的C#以及VB.NET中出现的引用,都类似于C++中的指针。Java中的采用引用的说法,其实是想程序员忘记指针所带来的痛苦;Java的引用比C++中的指针好用得多了,也容易管理,同时提供内存管理机制,让大家用得安心,写得放心而已。
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1573864
相关推荐
JAVA表面上看起来没有指针,但它的引用其实质就是一个指针,引用里面存放的并不是对象,而是该对象的地址,使得该引用指向了对象。在JAVA里,“=”语句不应该被翻译成赋值语句,因为它所执行的确实不是一个赋值的...
1.如果接受者是一个 map,func 或者 chan,使用值类型(因为它们本身就是引用类型)。 2.如果接受者是一个 slice,并且方法不执行 reslice 操作,也不重新分配内存给 slice,使用值类型。 3.如果接受者是一个小的数组...
在实际中,使用对象引用作函数参数要比使用对象指针作函数更普遍,这是因为使用对象引用作函数参数具有用对象指针作函数参数的优点,而用对象引用作函数参数将更简单,更直接。所以,在C++编程中,人们喜欢用对象...
java中clone的详细用法,分浅拷贝和深拷贝,并分别有详细的实例介绍。从原理分析。
使用类的对象还是指针,总结了下,给有疑问的朋友做个参考
Java中的指针与引用初探
2. Java中如何避免空指针异常? 3. Java中垃圾回收的机制是什么? 4. Java中什么是反射? 5. Java中什么是线程安全? 6. Java中抽象类和接口的区别是什么? 7. Java中什么是异常? 8. Java中如何防止对象的clone? 9...
将一个值类型变量 装箱成一个引用类型变量,首先会在托管堆上为新的引用类型变量分配内存空间,然后将值类型变量拷贝到托管堆上新分配的对象内存中,最后返回新分配的对象内 存地址。装箱操作是可逆的,所以还有拆箱...
易语言传递对象指针源码,传递对象指针,test,DLL_对象复制,DLL_对象释放,DLL_对象取指针
在 C 或 C 中与委托最接近的是函数指针,但函数指针只能引用静态函数,而委托可以同时引用静态方法和实例方法。在后一种情况中,委托不仅存储对方法入口点的引用,还存储对调用其方法的对象的引用。与 C 函数指针...
指针和引用的区别详细解答! 指针和引用的区别总结 1.从现象上看:指针在运行时可以改变其所指向的值,而引用...符号表生成后就不会再改,因此指针可以改变指向的对象(指针变量中的值可以改),而引用对象不能改。
C++数组与指针对象数组对象指针C++数组与指针对象数组对象指针
C#中使用指针源程序,我想许多C程序员不愿意学习Java的原因就是Java不支持指针,但是现在类似于Java的C#却已经支持了指针,你可以使用unsafe关键字来告诉编译器下面的函数或者代码是不安全的。一旦你使用了unsafe,...
深入理解引用与指针的关系从现象上看,指针在运行时可以改变其所指向的值,而引用一旦和某个对象绑定后就不再改变。这句话可以理解为:指针可以被重新赋值以指向另一个不同的对象。但是引用则总是指向在初始化时被...
详细分析了指针与引用的区别,适合初学者了解
Java 是传值还是传引用,问题主要出在对象的传递上,因为 Java 中简单类型没有引用。既然争论中提到了引用这个东西,为了搞清楚这个问题,我们必须要知道引用是什么。 简单的说,引用其实就像是一个对象的名字...
初学C++时对对象数组和对象指针都搞不太明白,后来找着了这篇文章才解开了我的疑虑!看看吧,挺不错的!
它可以接管任意类型的指针,所以你只需要放心大胆的new出任意对象,然后用智能指针去接管它,而不用担心在什么地方去delete,这个对象会最后一个接管它的智能指针释放它或者被销毁时而被delete;如果贪图方便,你...
经过几天的奋战,终于让我搞懂了JNA的解析以及指针在结构体中的应用!!!下了很多的资料,里面包含c++的.h头文件,给需要帮助的人看看!! 里面包含代码以及解析过程。
27.如何使用代码获取状态栏指针?(Visual C++编程 源代码)27.如何使用代码获取状态栏指针?(Visual C++编程 源代码)27.如何使用代码获取状态栏指针?(Visual C++编程 源代码)27.如何使用代码获取状态栏指针?...