一.引用变量
java数据类型分为两种,基本数据类型和引用数据类型。
基本类型定义:int i=1;程序运行到这句会在栈中定义一个变量 i 并且直接在栈在划分出int类型所对应长度的内存给i使用,变量和变量值都在栈里。
引用类型定义:Person p = new Person();程序会在栈中创建一个变量p,在堆中划分出一个(内存地址是连续的)Person对象所需要的内存,再将这个内存块的首地址返回给变量p。因为这样变量p就只是一个引用,所以对象类型的变量也叫引用变量。
引用的意思可以理解为指向,就是所引用对象的地址;
一个简洁的解读:引用变量存储在java运行时数据区的栈中,具体的实例(对象)则存储在java运行时数据区的堆中。
不同的引用可以指向同一个对象!
二.传参
在某种意义上,所有的传参,传的都是值,都是直接传自己的值,只是引用变量的值就是引用,引用对象传过去的是对象的地址,值传递过去的时候相当于重新创建了一个引用变量a,接下来的所有操作都是对a操作,a也是在栈中,所以就算是原来的引用变量本身也是不会变的,不过指向的是同一个对象。
其实按值还是按引用的区别在于“是否在传递的时候进行对象的内存拷贝”,java中基本类型是由于在JVM中存储区域不同于普通对象所以传递前会拷贝,传递的是拷贝后的 值,但是对象在传递的时候不拷贝,直接传“引用值”,指向同一片对象堆内存区域。
三.示例(在一群人的讨论中看到的)
public class Example {
String str = new String("good");
char[] ch = { 'a', 'b', 'c' };
public static void main(String args[]) {
Example ex = new Example();
ex.change(ex.str, ex.ch);
System.out.print(ex.str + " and ");
System.out.print(ex.ch);
}
public void change(String str, char ch[]) {
str = "test ok";
ch[0] = 'g';
}
}
Q:为什么 str没被改变,但是ch[0]却改变了?
A:首先,String 和 char数组都是引用类型,不是基本类型。第二,你传进去的引用类型的参数,传进去的时候相当于新建了一个变量var,已经不是原来的变量了,但是他们指向的数据区域都一样(数据地址相同),所以如果你改变了str指向的数据区域,那也只是改变var的数据地址,没有改变str的数据地址,str还是指向原来的数据区域 。而 =str = "test ok"; 这一句,就是改变了内部str指向的数据区域(改变数据地址),它不再指向"good"对象,而是指向一个新对象"test ok",相当于str = new String("test ok");,这只在函数内部有效,外部的str的数据地址没有变,还是指向原来"good"对象;而ch[0] = 'g';这一句,意思把内部ch指向的数据区域(也就是实际存放数组内容的地方)里面的第一个字符改成g,还是在原来指向的数据区域上操作,并没有改变内部ch的数据地址,所以这个修改也会反映到外部的ch。可以试一下在函数里面的 ch[0] = 'g'; 前面加多一句 ch = {'a','b','c'}; ,这时候就改变内部ch的数据地址了,它的内容虽然还是abc,但是已经指向一个新的数据区域,你在外部再打印ch就会发现内容没有改变。