何为Java引用

来源:互联网 发布:越南 社会主义 知乎 编辑:程序博客网 时间:2024/05/23 22:04
    首先,你要明白什么是变量。变量的实质是一小块内存单元。这一小块内存里存储着变量的值,比如int a =1;a就是变量的名,1就是变量的值。而当变量指向一个对象时,这个变量就被称为引用变量,比如A a =new A();a就是引用变量,它指向了一个A对象,也可以说它引用了一个A对象。我们通过操纵这个a来操作A对象。 此时,变量a的值为它所引用对象的地址。举个例子来加以说明:
String str1="string";
str1有本身的内存,是一个变量,而对象"string"也有它自己的内存空间,此时就说str1引用了"string"这个对象。
String str2=null;
这里的str2也是一个引用变量,只是它没有引用任何的对象。
如果将str1赋值给str2,即:
str2=str1;
那么str2与str1都是同一个引用变量,他们的值也就是具体对象的首地址(首地址也就是内存地址)。JVM会知道它们是不是引用变量(相对于原始类型int ,long等变量),JVM知道一个变量为原始变量的时候就会根据它们的值(一个地址值)再去访问具体的内存空间,也就是访问到具体的对象.因为str2=str1;就是把str1的值(一个地址值)复制给str2,所以在运行的时候JVM发现str2也是一个引用变量,就根据它的值(与str1的值一样) 去访问具体的内存空间,因为str2与str1的值相等,所以说:str2与str1引用对一个对
既然了解了引用,接下来讲解一下引用传值的问题:
StringBuffer sb=new StringBuffer();
sb是一个引用变量,当执行到new StringBuffer()的时候就会分配一段内存空间给这个对象使用,并把这段空间的首地址返回,也就是把首地址返回给sb变量,就形成了"sb引用这个对象". 
例如:
public void addString(StringBuffer sb1) 

    sb1.append("function"); 

下边这段代码: 
StringBuffer   sb = new StringBuffer(); 
sb.append("hh"); 
addString(sb); 
System.out.println(sb.toString()); 

结果是:hhfunction 
原理:sb引用一个具体的对象,它的值是一个StringBuffer对像的首地址,执行到sb.append("hh");在那个具体对象的地方就会加上这个"hh"字符串,然后执行到 addString(sb);实际就是把sb的值(什么值?想想)传给方法里的参数,那个方法的参数StringBuffer sb1只是一个引用变量,当执行这句代码的时候就是把sb的值传给sb1,然后执行方法时的代码,sb1与sb都是引用同一个对像,因为它们的值相同.所以在方法里访问sb1实际就是访问原来sb所指向的那个对象. 

相当与下边这段代码 
StringBuffer   sb = new StringBuffer(); 
sb.append("hh"); 
StringBuffer   sbe=null;//这里相当与方法的参数 
sbe=sb;//调用方法的时候就会执行这样的结果,把sb的值给与sbe 
sbe.append("function");//这一句相当与方法里的代码. 

结果也是hhfunction. 

如果将StringBuffer用final关键字来修饰的话,以上例子将变成如下的样子:
final StringBuffer sb=new StringBuffer();
那么,问题来了,当使用final这个关键字来修饰sb这个变量时,是引用变量不能变,还是引用的对象不能变?
答案是引用的变量不能变,因为当new一个StringBuffer的时候已经给StringBuffer这个对象分配了内存空间,并把这段空间的首地址返回给sb变量,所以sb变量就不能再修改了,但是引用变量所指向的对象中的内容还是可以改变的,所以有人在定义方法的参数时,可能想采用如下形式来阻止方法内部修改传进来的参数对象:

public void method(final StringBuffer param){}实际上,这是办不到的,在该方法内部仍然可以增加如下代码来修改参数对象:param.append("a");


 
0 0
原创粉丝点击