学过Java的人都知道,Java里面除了8个基本数据类型外,其它的都可以称为引用类型。 
String类型是个特殊的引用类型,因为它在表面是兼具了基本类型和引用类型的特征,也是大部分人最迷惑的地方,这也成为了知其然,而不其所以然的原因! 
     首先说说Java对象吧,很多人都说Java中的对象其实就是一个指针,因为我们在任意可触及的地方利用对象句柄来操作对象里面任意公开的字段和方法,但是奇妙的是Java的值传递和引用传递总是让人迷惑不清,因为在对象被当作参数传入某个方法里的时候,让该句柄重新指向另外一个新对象的时候,调用方的句柄仍然不会收到任何影响,这不是值传递的特性吗,和C++里面的对象概念在这里就画了一个风水岭了, 这种现象有谁知道这是为什么吗?   
     所以,我个人认为Java里面没有引用传递,只有值传递的! 因为,我们传递的永远都是一个值,而不会是一个真正意义上的指针,那么它为什么会在值不发生改变的时候具有引用的特性呢?   其实对象的句柄和基本数据类型大致相同,不同的是他们的标识目标不同,基本类型数据标识的是一个存在与内存中的某个数据,而对象的句柄标识的却是一个指针,对象的句柄本身不是一个指针,但是它可以标识一个指针,指针就是这个句柄的值,这样它就可以通过指针来操作这个对象的内部数据了。任意多的具有相同对象的类型的句柄它们的值都是一个相同的指针。 这样以来,任何对象句柄都是值传递。 为什么Java需要这样设计了,个人认为Java是门安全的语言,不会让用户直接操作指针,以免让用户直接操作内存和造成野指针的现象; 再一个就是Java的垃圾回收器定期需要移动一次当前可触及的对象而清除垃圾对象,那么移动对象的同时,会造成对象的内存地址发生改变,如果每个句柄都是一个指针的话,在有多个句柄的情况下,虚拟机需要同时将多个当前指向的内存地址的指针修改成新的内存地址,这是件非常不明智且需要的大量内存开销的做法!那么让所有的句柄都拥有同一个指针,在移动一个对象的时候,只需要修改这个指针的内存地址即可,其它句柄完全不用做任何改动,我们称这个指针为转向指针! 说到这里,大家应该对Java对象有个大概印象了吧! 
     String类型也是一个对象,那么它与上面说的原理也是一样的。String是靠一个名称为value的char数组来储存字符串的,这个char数组是final类型的,一旦被初始化就是不可改变的! 所以如果要改变一个String的值,就需要不断的去创造新的对象。   String类型的赋值有两种方式: 
1.直接赋值:String str = "abc";   这种赋值,内存是用栈来存储"abc"的。 
2.用new指令来创建的:String str = new String("abc"); 这种赋值,内存是用堆来存储"abc"的。 
所以,第一种方法在效率上要优于第二种方法,读者可以自己去验证。 
需要注意的是,第一种方法,"abc"才是一个对象,而str只是一个对象句柄,也可以理解成一个载体。 
     写到这里,读者应该明白了Java里面,在一个方法内部修改了一个传进来的对象句柄值,为什么方法外的对象不会收到任何影响了吧! 有什么不对的地方,希望大家能提出来! 我也是个菜鸟!

解决方案 »

  1.   

    错的地方非常多,比如
    1。java的引用是什么?
    这是跟实现有关的。
    按照sun最新的实现,The Java HotSpot Performance Engine Architecture:http://java.sun.com/products/hotspot/whitepaper.html
    In the Java HotSpot VM, no handles are used by Java codeObject references are implemented as direct pointers. This provides C-speed access to instance variables. When an object is relocated during memory reclamation, the garbage collector is responsible for finding and updating all references to the object in place.2。String是靠一个名称为value的char数组来储存字符串的,这个char数组是final类型的,一旦被初始化就是不可改变的!
    这是不正确的,把一个数组声明为final的,并不能保证它的内容是不可变的,请参考不变类的设计。这不是不变的本质原因。3。关于堆和栈的内容,不多说了,自己看资料,理解堆,栈,常量池等基本概念。
    注意"abc"并不是对象,java语言规范中有说明,String字面量是指向String类的实例的引用
      

  2.   

    ZangXT 大侠好:  
    谢谢大侠的耐心指点,纠正了我的一些类错误理解!
      1. char之所以不能被改变的本质,是因为外界不能触及到这个变量。
      2. "abc"本身就是一个引用,我还里理解成一个对象了!  原来string类型的对象,比我想象中的要深沉!
      3. 关于垃圾回收器的理解,还有待研究! 如果真像sun规范里所说的:当一个对象在内存搬迁,垃圾回收器,负责查找和更新所有引用该对象的地方。
     那我就得重新换个观点和设计方面的理解去认识JAVA VM了! 
      
      希望大家能多多指点! 谢谢!