`

Java中的对象类型像引用还是指针,谁是谁非?

 
阅读更多

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,也即是说ca的别名,即同一个变量,两个不同的名字而已。只要改变ac,该变量内容都会发生改变的。

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++中的对象没有定义“==”运算法,那么它会依次对两个变量比较它的数据成员,看是否都相等。如果定义则按用户的比较方式进行比较。在JavaObject对象定义了equals方法,这个方法是用来比较两个对象如果相等的,Object中的equals方法只是比较两个指针的值是否相等而已,要根据所指向的对象内容进行比较,那应重写该类的equals方法。

正因为Java中存在指针,所以使用Java同样能写出丰富的数据结构,java中的集合框架就是最好的例子。

上面只要谈到Java中指针与C++中指针相同或类似的部分,我觉得两者之间是有差别的,差别主要有三个。

C++中的指针是可以参与和整数的加减运算的,当一个指对指向一个对象数组时,可以通过自增操作符访问该数组的所有元素;并且两个指针能进行减运算,表示两个指表所指向内存的“距离”。而Java的指针是不能参与整数运算和减法运算的。

C++中的指针是通过new运算或对象变量取地址再进行赋值而初始化的,可以指向堆中或栈中的内存空间。Java同样是类似的,通new运算得到初始化。Java中指针只能是指向堆中的对象,对象只能生存在堆中。C语言是可以通过远指针来指向任意内存的地址,因而可以该问任意内存地址(可能会造成非法访存);Java中的指针向的内存是由JVM来分配的中,由于new运算来实现,不能随所欲为地指向任意内存。

C++中通过deletedelete[] 运算符进行释放堆中创建的对象。如果对象生存周期完结束,但没有进行内存释放,会出现内存泄露现象。在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中的指针,引用及对象的clone

    ### Java中的指针概念与引用解析 #### 一、引言 Java作为一种广泛使用的面向对象编程语言,在设计之初就摒弃了C/C++中的指针概念。然而,尽管Java没有传统意义上的指针,但仍然存在一种类似的概念——引用。本文将...

    Java中对象与引用对象的关系

    Java中对象与引用对象的关系 在 Java 中,对象和引用对象的关系是一个非常重要的概念。从宏观的角度来看,对象是类的实例。例如,我们可以定义一个名为 Someone 的类,代表一些人(通过指定年龄、性别、性格等基本...

    Java中的指针与引用初探.pdf

    本文主要探讨Java中的对象、指针(受限指针)和引用,以及对象的存储空间和回收机制。 首先,Java语言中的万物皆对象。对象是面向对象编程的核心,它代表了现实世界中具体的事物或概念,并包含了其特性和行为。对象...

    java中对象创建、初始化、引用

    虽然两者之间存在一定的相似性,但在Java中句柄主要用来处理对象引用,而非直接指向对象的内存地址。 #### 三、总结 通过上述内容,我们可以了解到在Java中创建对象、初始化以及引用传递的基本流程和概念。对象是...

    Go语言的方法接受者类型用值类型还是指针类型?

    1.如果接受者是一个 map,func 或者 chan,使用值类型(因为它们本身就是引用类型)。 2.如果接受者是一个 slice,并且方法不执行 reslice 操作,也不重新分配内存给 slice,使用值类型。 3.如果接受者是一个小的数组...

    C++对象和指针的引用

    在实际中,使用对象引用作函数参数要比使用对象指针作函数更普遍,这是因为使用对象引用作函数参数具有用对象指针作函数参数的优点,而用对象引用作函数参数将更简单,更直接。所以,在C++编程中,人们喜欢用对象...

    探讨Java的对象是怎么在内存中产生的?

    这些字段可以是基本数据类型、对象引用等。HotSpot虚拟机默认使用8字节对齐,即每个字段都会根据类型进行适当的填充以保证数据对齐。 3. **对齐填充(Padding)**:为了保持内存地址的对齐,有时需要添加额外的填充...

    浅谈java面向对象和引用

    - **引用与值类型的区别**:Java中的基本数据类型(如`int`、`double`等)是值类型,而类的实例是引用类型。值类型的赋值操作会复制一个副本,而引用类型的赋值只是复制了指向同一对象的引用。 #### 示例解析 以...

    Java对象及其引用的理解

    而对于对象引用,虽然传递的是引用的副本,但这些副本都指向同一个堆内存中的对象。这意味着,如果在方法内改变了对象的属性,外部也能看到这些变化,因为所有引用都在指向同一个对象。 例如,假设我们有一个`...

    JNA 转java接口以及指针结构体解析

    JNA允许你在Java中定义回调函数,这些函数可以被本地代码调用。在提供的`CallBackTest`示例中,可能包含了一个如何定义和注册Java回调函数的示例。回调函数通常需要实现`com.sun.jna.Callback`接口,并将适当类型的...

    对象数组与对象指针及this指针

    this 指针是 C++ 中的一个隐含指针,用于引用当前对象。每当成员函数被调用时,C++ 都会自动产生一个 this 指针,指向当前对象。例如: ```cpp class exth { int i; public: void load(int val) { i = val; } ...

    C++指针与引用的区别

    指针和引用是C++语言中两种不同的概念,初学者容易把它们混淆一起。这两种概念都是地址的概念,但它们有很多不同的特点和应用场景。 相同点 1. 都是地址的概念;指针指向一块内存,它的内容是所指内存的地址;引用...

    java对象引用易混解析

    ### Java对象引用详解 #### 一、Java对象与引用的基本概念 在Java中,对象是类的一个实例,而引用则是指向这些对象的变量。理解Java中的对象与引用之间的区别至关重要,因为这涉及到如何管理和操作对象。 #### 二...

    java_指针_数组的

    Java中数组可以被看作是对象的一种特殊形式,因此数组变量实际上存储的是指向实际数组的引用。这一点类似于其他语言中的指针概念。例如,在代码中出现了这样的操作: ```java int[] arr3 = arr; ``` 这里的`arr3`...

    内存中引用与指针之间的使用与区别

    内存中的引用和指针是C++编程语言中的两种重要概念,它们都用于间接访问和操作对象,但在使用和性质上存在显著差异。 首先,指针是一个变量,它存储了一个对象的内存地址。声明指针时,我们可以使用*操作符,如`...

    面向对象语言还需要指针么?

    面向对象语言是否需要指针?这是一个经典的问题。在C语言中,指针是必不可少的,但是 java 等高级语言却不需要指针。那么,到底是好事还是坏事?本文将通过对比C++和C#两种语言,探讨高级面向对象语言中指针的必要性...

    详细分析指针的运作!判断指针使用的错误,越界!引用错误!指针数据流分析。分析静态数据相关性,java实现!

    在Java中,虽然没有直接的指针概念,但可以利用数据流分析来检测类成员的访问、方法调用的顺序等相关性。比如,单相关和双相关分析可以识别变量之间的依赖关系,帮助找出可能的并发问题,如数据竞争和死锁。 在分析...

    java中对象创建、初始化、引用文.pdf

    总的来说,理解Java中的对象创建、初始化和引用机制,以及类比的“句柄”概念,有助于开发者更好地管理内存,防止因误操作导致的空指针异常等问题,提高程序的健壮性和效率。在编写Java代码时,正确地使用和理解这些...

    Java中的对象和引用详解

    对象引用可以看作是一个指针,它指向对象的内存地址。对象引用可以被赋值、比较和传递,它们可以在不同的语句中使用。对象引用是Java语言中一个非常重要的机制,它是Java语言的基础之一。 三、对象和对象引用的区别...

    指针对学习Java语言的价值.pdf

    总之,虽然Java语言设计时避免了指针的使用,但通过理解简化版的指针概念,我们可以更清晰地认识Java中的引用类型,从而更好地学习和掌握Java语言。在实践中,这有助于解决诸如引用变量的存储、内存管理等问题,提高...

Global site tag (gtag.js) - Google Analytics