JAVA中值类型和引用类型的区别?(面试题)
值类型:基本数据类型 基本数据类型被称为四类八种
四类:1、整型 2、浮点型 3、字符型 4、逻辑型
八种:
1、整型3种 byte、short、int、long
2、浮点型2种 float,double
3、字符型1种 char
4、逻辑型1种 boolean
引用类型:除了四类八种基本类型外,所有的类型都称为引用类型:类(class)、接口(interface)、数组(array)
值传递:基本数据类型的赋值是值传递,当值类型变量a赋值给值类型变量b之后,再去改变a的值那么b不会随着a的改变而改变。
如下列子:
public static void main(String[] args) {
int a=1;
int b=a;
a=2;
System.out.println("a="+a+"b="+b);
}
输出的值为:a=2b=1
引用传递:
引用值类型的赋值是引用传递,传递的是对象的引用地址。当引用值类型变量a赋值给引用值类型变量b之后,再去改变a的值那么b不会随着a的改变而改变。
如下列子
int a;
public Test(int a){
this.a=a;
}
public void seta(int a){
this.a=a;
}
public Test(){
}
public static void main(String args[]){
Test test1= new Test(1);
Test test2= new Test();
test2=test1;
test1.seta(2);
System.out.println("test1="+test1.a+"------test1="+test2.a);
}
输出的值为:test1=2------test1=2
2 内存分配
之所以会出现以上的现象是因为,值类型数据和引用类型数据在在Java中的内存分配不一样。
值类型数据是直接存储在栈中,Java JVM直接在栈中给数据开辟了一块空间,直接存储数据的值。
int a=1; //JVM为变量a在栈中开辟了一块空间(假设为A),栈中存储的是 1;
int b=a; //JVM为变量b在栈中开辟另了一块空间(假设为B),栈中存储的也是 1;
a=2; //为变量a重新赋值,栈空间A中存储的值改为2,栈空间B中存储的值不变为1
引用类型数据并不是直接存储在栈中,Java JVM会在堆中给数据分配内存空间,堆存储数据。栈存储的是指向对应堆的地址。可以说是栈中的地址引用了堆中的数据。
Test test1= new Test(1);
/*
JVM为test1变量在堆中开辟一块空间(假设为K),那么堆空间K存储的是 1;
JVM为test1变量在栈中开辟一块空间(假设为A),那么栈空间A存储的是指向堆空间的地址(假设为1000)
*/
Test test2= new Test(0);
/*
JVM为tb变量在堆中开辟一块空间(假设为J),那么堆空间J存储的是 0;
JVM为ta变量在栈中开辟一块空间(假设为B),那么栈空间B存储的是指向堆空间的地址(假设为2000)
*/
test2=test1;
/*
栈空间B中存储的地址从2000改为1000(从指向J改为指向K) 现在ta 和 tb 都引用堆空间K
*/
test1.seta(2);
/*堆空间K中存储的值改为2 所以 test1.a 和 test2.a 都是2 */
垃圾回收机制
当堆空间存储的对象没有被栈空间中存储的地址所指向时(引用时),该对象会被自动清理掉。如前面提到的堆空间J中本来存储着 0
Test test2= new Test(0);
但是 test2=test1;
不再有地址指向堆空间J中本来存储的0,0会被自动清除。