精华内容
下载资源
问答
  • 先放结论:可以认为Java中的引用就是指针,是一种限制的指针,不能参与整数运行和指向任意位置的内存,并且不用显示回收对象。 作为一名程序员,我们应该对新知识和新技术刨根问底,而不应泛泛而谈。我未曾接

    初学Java,感觉引用和c中的指针很像,特此学习,mark一下

    原文详见:http://blog.csdn.NET/linyt/article/details/1573864

    先放结论:可以认为Java中的引用就是指针,是一种限制的指针,不能参与整数运行和指向任意位置的内存,并且不用显示回收对象。

    作为一名程序员,我们应该对新知识和新技术刨根问底,而不应泛泛而谈。我未曾接触到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的引用不用关心内存回收的问题

          

    小结

           通过上面的分析,我们可以得到这样的结论:Java中的引用与C++中的引用是不同的,并且Java中的引用更像C++中的指针。因此,可以认为Java中的引用就是指针,是一种限制的指针,不能参与整数运行和指向任意位置的内存,并且不用显示回收对象。除了Java外,就本文开头提到的C#以及VB.NET中出现的引用,都类似于C++中的指针。Java中的采用引用的说法,其实是想程序员忘记指针所带来的痛苦;Java的引用比C++中的指针好用得多了,也容易管理,同时提供内存管理机制,让大家用得安心,写得放心而已。
    展开全文
  • 因为是单例模式,所以我在每个条件判断上要再加个条件,就是,如果我之前的Parser类型的引用本来就引用了一个XMLParser的对象,那就不需要再生成新的XMLParser对象了,我怎样能判断原来Parser引用是不是引用了XML...
  • 当我们把变量赋值给一个变量时,解析器首先要确认的就是这个值是基本类型值还是引用类型值。2、常见的基本数据类型:Number、String 、Boolean、Null和Undefined。基本数据类型是按值访问的,因为可以直接操作保存在...

    ECMAScript包括两个不同类型的值:基本数据类型和引用数据类型。

    基本数据类型指的是简单的数据段,引用数据类型指的是有多个值构成的对象。

    当我们把变量赋值给一个变量时,解析器首先要确认的就是这个值是基本类型值还是引用类型值。

    2、常见的基本数据类型:

    Number、String 、Boolean、Null和Undefined。基本数据类型是按值访问的,因为可以直接操作保存在变量中的实际值。示例:

    var a = 10;

    var b = a;

    b = 20;

    console.log(a); // 10值

    上面,b获取的是a值得一份拷贝,虽然,两个变量的值相等,但是两个变量保存了两个不同的基本数据类型值。

    b只是保存了a复制的一个副本。所以,b的改变,对a没有影响。

    下图演示了这种基本数据类型赋值的过程:

    678a287ca92157e950d7f43b871287a5.png

    3、引用类型数据:

    也就是对象类型Object type,比如:Object 、Array 、Function 、Data等。

    javascript的引用数据类型是保存在堆内存中的对象。

    与其他语言的不同是,你不可以直接访问堆内存空间中的位置和操作堆内存空间。只能操作对象在栈内存中的引用地址。

    所以,引用类型数据在栈内存中保存的实际上是对象在堆内存中的引用地址。通过这个引用地址可以快速查找到保存中堆内存中的对象。

    var obj1 = new Object();

    var obj2 = obj1;

    obj2.name = "我有名字了";

    console.log(obj1.name); // 我有名字了

    说明这两个引用数据类型指向了同一个堆内存对象。obj1赋值给onj2,实际上这个堆内存对象在栈内存的引用地址复制了一份给了obj2,

    但是实际上他们共同指向了同一个堆内存对象。实际上改变的是堆内存对象。

    下面我们来演示这个引用数据类型赋值过程:

    903ec204c234e5a2864f1c94ef5a3869.png

    4、总结区别

    a 声明变量时不同的内存分配:

    1)原始值:存储在栈(stack)中的简单数据段,也就是说,它们的值直接存储在变量访问的位置。

    这是因为这些原始类型占据的空间是固定的,所以可将他们存储在较小的内存区域 – 栈中。这样存储便于迅速查寻变量的值。

    2)引用值:存储在堆(heap)中的对象,也就是说,存储在变量处的值是一个指针(point),指向存储对象的内存地址。

    这是因为:引用值的大小会改变,所以不能把它放在栈中,否则会降低变量查寻的速度。相反,放在变量的栈空间中的值是该对象存储在堆中的地址。

    地址的大小是固定的,所以把它存储在栈中对变量性能无任何负面影响。

    b 不同的内存分配机制也带来了不同的访问机制

    1)在javascript中是不允许直接访问保存在堆内存中的对象的,所以在访问一个对象时,

    首先得到的是这个对象在堆内存中的地址,然后再按照这个地址去获得这个对象中的值,这就是传说中的按引用访问。

    2)而原始类型的值则是可以直接访问到的。

    c 复制变量时的不同

    1)原始值:在将一个保存着原始值的变量复制给另一个变量时,会将原始值的副本赋值给新变量,此后这两个变量是完全独立的,他们只是拥有相同的value而已。

    2)引用值:在将一个保存着对象内存地址的变量复制给另一个变量时,会把这个内存地址赋值给新变量,

    也就是说这两个变量都指向了堆内存中的同一个对象,他们中任何一个作出的改变都会反映在另一个身上。

    (这里要理解的一点就是,复制对象时并不会在堆内存中新生成一个一模一样的对象,只是多了一个保存指向这个对象指针的变量罢了)。多了一个指针

    d 参数传递的不同(把实参复制给形参的过程)

    首先我们应该明确一点:ECMAScript中所有函数的参数都是按值来传递的。

    但是为什么涉及到原始类型与引用类型的值时仍然有区别呢?还不就是因为内存分配时的差别。

    1)原始值:只是把变量里的值传递给参数,之后参数和这个变量互不影响。

    2)引用值:对象变量它里面的值是这个对象在堆内存中的内存地址,这一点你要时刻铭记在心!

    因此它传递的值也就是这个内存地址,这也就是为什么函数内部对这个参数的修改会体现在外部的原因了,因为它们都指向同一个对象。

    参考文献:

    展开全文
  • 这貌似是一个极其简单的问题,还用得着专门写一篇博文?各位看官,最初我也这么认为,但这的确蒙蔽了你那水灵灵的小眼睛,不妨看看什么是...这就是所谓的引用,那对象是不是也是这样的呢?class A{public $num = 10...

    这貌似是一个极其简单的问题,还用得着专门写一篇博文?各位看官,最初我也这么认为,但这的确蒙蔽了你那水灵灵的小眼睛,不妨看看什么是引用?

    $a = 10;

    $b = &$a;

    $b = 20;

    var_dump($a,$b);

    在这段极其简单的代码中,$b是$a的引用,也即是别名,修改$b,$a会变,反之亦然。这就是所谓的引用,那对象是不是也是这样的呢?

    class A

    {

    public $num = 10;

    }

    $a = new A();

    $a->num = 20;

    function demo($b)

    {

    $b[0] = 5;

    var_dump($b);

    }

    demo($a)

    var_dump($a);

    你会发现两次输出一样,那这是不是说明对象做函数参数时是引用传参呢?在这一点上不得不说千锋的学生的确是勤学好问,我刚开始以为是引用传参,但同学提出如果你把demo里修改为:

    function demo($b)

    {

    $b = new A();

    var_dump($b);

    }

    两次输出并不一样!这是为什么呢?如果从C语言角度讲,PHP里的任何变量,包括对象都是指针,对象做参数相当于二重指针,所以当$b指向一个全新的对象后,并不影响$obj,所以对象做函数参数并不是引用传参!又这么一帮勤学好问的学生,整个水准都不一样了。

    互联网+时代,时刻要保持学习,携手千锋PHP,Dream It Possible。

    展开全文
  • 这貌似是一个极其简单的问题,还用得着专门写一篇博文?各位看官,最初我也这么认为,但这的确蒙蔽了你那水灵灵的小眼睛,不妨看看什么是...这就是所谓的引用,那对象是不是也是这样的呢?class A{public $num = 10...

    这貌似是一个极其简单的问题,还用得着专门写一篇博文?各位看官,最初我也这么认为,但这的确蒙蔽了你那水灵灵的小眼睛,不妨看看什么是引用?

    $a = 10;

    $b = &$a;

    $b = 20;

    var_dump($a,$b);

    在这段极其简单的代码中,$b是$a的引用,也即是别名,修改$b,$a会变,反之亦然。这就是所谓的引用,那对象是不是也是这样的呢?

    class A

    {

    public $num = 10;

    }

    $a = new A();

    $a->num = 20;

    function demo($b)

    {

    $b[0] = 5;

    var_dump($b);

    }

    demo($a)

    var_dump($a);

    你会发现两次输出一样,那这是不是说明对象做函数参数时是引用传参呢?在这一点上不得不说千锋的学生的确是勤学好问,我刚开始以为是引用传参,但同学提出如果你把demo里修改为:

    function demo($b)

    {

    $b = new A();

    var_dump($b);

    }

    两次输出并不一样!这是为什么呢?如果从C语言角度讲,PHP里的任何变量,包括对象都是指针,对象做参数相当于二重指针,所以当$b指向一个全新的对象后,并不影响$obj,所以对象做函数参数并不是引用传参!又这么一帮勤学好问的学生,整个水准都不一样了。

    互联网+时代,时刻要保持学习,携手千锋PHP,Dream It Possible。

    展开全文
  • 值类型与引用类型

    2020-12-26 13:03:19
    对于引用类型来说,每个对象的开头都包含一个数据块,它标识了对象的实际类型,同时还提供了其他的一些信息. 永远不能改变对象的类型,当执行简单的强制类型转换时,运行时会获取一个引用,检查它引用的对象是不是目标类型...
  • 这貌似是一个极其简单的问题,还用得着专门写一篇博文?各位看官,最初我也这么认为,但这的确蒙蔽了你那水灵灵的小眼睛,不妨看看什么是引用?...这就是所谓的引用,那对象是不是也是这样的呢? clas
  • 当我们用一个类型的构造器构造出一个对象时,这个对象类型就已经确定的,也就说它的本质是不会再发生变化了。在Java中我们可以通过继承、向上转型的关系使用父类类型引用它,这个时候我们是使用功能较弱的类型
  • 变量类型值类型VS引用类型typeof运算符深拷贝 值类型VS引用类型 区别:值类型的值存在栈中,引用类型的值刚在堆中。 值类型 String,Undefined,Number,Boolean,Symbol 引用类型 Object,Array,null(特殊引用类型,...
  • ``` Integer aa = new Integer(1001); Integer bb; bb = aa; bb=1002; System.out.println(aa); /* OutPut: ...用Integer声明的也不是引用吗?java中具体哪些类型声明出来后不是引用而是对象
  • 1、JS基础类型 number 数字类型 string 字符串类型 boolean 布尔类型 true/false ...2、JS引用类型 object 对象 array 数组 DATA类型 function类型 补充:array数组的常用方法 isArray():判断是不是数组 pop():弹
  • a、可变性:String类中使用字符数组保存字符串,private final char value[],所以string对象是不可变的。StringBuilder与StringBuffer都继承自AbstractStringBuilder类,在AbstractStringBuilder中也是使用字符数组...
  • 目录JaveScript的数据类型基本数据类型引用数据类型数据的类型检测1. typeof()2. 验证原型对象 --获取对象的隐式原型3.验证构造函数4. 检查内部属性class每个对象创建时使用的类型的属性 Object.prototype....
  • 引用数据类型

    2021-04-14 17:21:30
    引用数据类型引用数据类型包括3钟。存储空间分为两部分,一个在stack中,一个在heap中。一般在stack中存放head的地址,head里面存放实际的数据。引用数据类型在类中初始化为null。 1、数组2、类3、接口 注:1、不同...
  • java确定对象类型

    千次阅读 2019-08-27 09:58:04
    instanceof运算符 只被用于对象引用变量,检查左边的被测试对象 是不是 右边类或接口的 实例化。 自身实例或子类实例 instanceof 自身类 返回true String s=new String("hello"); System.out.println(s ...
  • 基本数据类型==比较的是值,引用数据类型==比较的是...因为 Java 只有值传递,所以,对于 == 来说,不管是比较基本数据类型,还是引用数据类型的变量,其本质比较的都是值,只是引用类型变量存的值是对象的地址。 ...
  • javascript:引用类型

    2018-04-21 15:56:43
    引用类型 1.x Object类型 1.1.x Object类型对象的创建方式有两种: 1.2.x 访问对象属性的两种方式: 2.x Array类型 2.1.x Array类型对象创建方式有两种: 2.2.x 读取和设置数组的值 2.3.x 判断一个对象是不是数组...
  • js 的引用类型

    2018-04-01 15:45:45
    引用类型的值(对象)是引用类型的一个实例,,在js 里引用类型是一种数据结构,通常被称为类,es6貌似加了类这个概念, 1:object是一个基础类,其他所有类型都从object继承了基本行为, js在使用typeof 方法时,...
  • 转载以下,希望帮到同样疑惑的人Java中的对象类型引用还是指针,谁是谁非?Java中的对象类型引用还是指针,谁是谁非?作者:海枫作为一名程序员,我们应该对新知识和新技术刨根问底,而不应泛泛而谈。我未曾接触...
  • 动态验证对象类型

    2008-12-18 22:11:00
    instanceof运算符 只被用于对象引用变量,检查左边的被测试对象是不是右边类或接口的实例。如果被测对象是null值,则测试结果总是false。 形象地:自身实例或子类实例 instanceof 自身类,返回true。 Class类的...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 899
精华内容 359
关键字:

对象类型是不是引用类型