java 的引用类型、值类型,引用传递与值传递
java有没有引用传递?
很多书上说,java只有值传递,所以没有引用传递,这句话是对的么?
上代码
?
例一:
public class StringTest {public int i=1;public static void st(StringTest st){st.i=10;}public static void main(String args[]){StringTest st=new StringTest();st(st);System.out.println(st.i);//输出:10}}
?输出的时10,不是1,这说明这个对象传递的是引用而不是值。
?
这么说java是有引用传递的,那为什么那么多人还说java只有值传递呢?
?
在网上找了很久,最终发现,网上有人总结了如下4点:(我觉得可以说清楚了)
?
1、对象是按引用传递的 (这里的传对象其实也是传值,因为对象就是一个指 针,这个赋值是指针之间的赋值,因此在java中就将它说成了传引用。(引用是什么?不就是地址吗?地址是什么,不过就是一个整数值) )
2、Java 应用程序有且仅有的一种参数传递机制,即按值传递
3、按值传递意味着当将一个参数传递给一个函数时,函数接收的是原始值的一个副本
4、按引用传递意味着当将一个参数传递给一个函数时,函数接收的是原始值的内存地址,而不是值的副本
?
在网上找了很久,
对于1肯能有点困惑,看例子
?
例二:
public class StringTest {public int i=1;public StringTest(int i){this.i=i;}public static void st(int in,StringTest st1,StringTest st2){in=1;st1.i=10;st2=st1; //1st2.i=20; //2}public String toString(){return String.valueOf(i);}public static void main(String args[]){StringTest st1=new StringTest(1);StringTest st2=new StringTest(2);int in=0;st(in,st1,st2);System.out.println(in);//输出:0 这说明他是传值,而不是传址(引用)System.out.println(st1);//输出:10System.out.println(st2);//我们发现无论是否注释掉位置2那一行,其输出:2 这里为什么是2呢?我们知道参数st2其实传递的是内存地址,而当把st1赋值个st2,其实改变的时st2这个变量的引用地址,因此当前的st2是没有变化的//输出:10}}
?
这也证实了,java中只有值传递而没有引用传递这么说也是对的
?
?
?
关于string的问题
今天我朋友问我,String是引用类型还是值类型?
string是对象,按照如上4条规则,那他应该是引用传递(引用类型)了,可又人说他特殊,不是引用传递(值类型),是值传递
上例子吧
?
例三:
public class StringTest {public int i=1;public static void st(String st){//System.out.println("st()方法中st的hashcode"+st.hashCode()); //1st="bb";}public static void main(String args[]){String st="aa";//System.out.println("st的hashcode"+st.hashCode()); //2st(st);System.out.println(st);/** * 输出:aa 有人说从此例中可以看出string是值传递,我觉得这个有相当大的争议 首先string是一个对象,那么他传递的是应该是引用, * 可这个例子证明了却相反,为什么? * st是一个变量,传进去的当然是st这个变量所引用的(一个整数型id)内存地址,如何证明呢 * 我们吧 1和2这两行取消注释,你回发现,二者还是同一个hashcode * 那为什么我改变了st在main方法中他还是那个了,其实这和 例二 中讲的原因是一样的,因为你 改变了变量的引用,二不是给引用的本身 * */}}
?
?? 如果可以改变String中的变量的话,我想可以更好的证实这一点,但String对象是不可改变的,看他得源代码
??? private final char value[];
??? /** The offset is the first index of the storage that is used. */
??? private final int offset;
??? /** The count is the number of characters in the String. */
??? private final int count;
??? /** Cache the hash code for the string */
??? private int hash; // Default to 0
??? /** use serialVersionUID from JDK 1.0.2 for interoperability */
??? private static final long serialVersionUID = -6849794470754667710L;
可以看出String对象里的变量是不可改变的,那么也就是说String对象是不可改变的
注:本文参考了http://www.zxbc.cn/html/20081016/66711.html