数据类型
首先了解一下Java中的数据类型
数据类型:
- 基本类型
- 对象类型
对应的,变量类型:
- 基本类型
包括byte,short,int,long,char,float,double,boolean... - 引用类型
包括 类、接口和数组
基本类型和引用类型的区别
- 存值
基本类型的变量保存原始值,即它代表的值就是数值本身
引用类型的变量保存引用值,指向内存空间的地址,对象本身存放在这个地址的位置 - 空间分配
基本类型是在声明时就分配空间
引用类型在声明时只分配引用空间,不分配数据空间
"引用"也是占用空间的,一个空Object对象的引用大小大概是4byte
值传递和引用传递
进入主题
概念
值传递:方法调用时,实参把它的值直接传递给形参,函数接收到的是原始值的copy,此时内存中存在两个相等的基本类型,即实参和形参,后面方法都是对这个形参的修改,不影响实参
引用传递:方法调用时,实参把它的引用传给形参,函数接收到的是原始值的内存地址,此时实参和形参指向同一片内存地址,对形参的修改会影响到实参
举一个栗子:
class MyObj{
public int b=99;
}
public static void main(String[] args) {
ReferencePkValue2 t = new ReferencePkValue2();
int a=99;
t.test1(a);//这里传递的参数a就是按值传递
System.out.println(a); //此处是对实参的输出 99
MyObj obj=new MyObj();
t.test2(obj);//这里传递的参数obj就是引用传递
System.out.println(obj.b); //此处是对实参的输出 100
}
public void test1(int a){
a++;
System.out.println(a); //此处是对形参的输出 100
}
public void test2(MyObj obj){
obj.b=100;
System.out.println(obj.b); //此处是对形参的输出 100
}
输出:
100;
99;
100;
100;
由结果可见,只有在值传递时实参没有受到影响
这里要特殊考虑String,以及Integer、Double等几个基本类型包装类,它们都是immutable类型,
因为没有提供自身修改的函数,每次操作都是新生成一个对象,所以要特殊对待,可以认为是和基本数据类型相似,传值操作
再看一个栗子:
public static void main(String[] args){
ReferencePkValue1 pk=new ReferencePkValue1();
//String类似基本类型,值传递,不会改变实际参数的值
String test1="Hello";
pk.change(test1);
System.out.println(test1); //输出为 Hello
//StringBuffer和StringBuilder等是引用传递
StringBuffer test2=new StringBuffer("Hello");
pk.change(test2);
System.out.println(test2.toString()); //输出为 Helloworld
}
public void change(String str){
str=str+"world";
}
public void change(StringBuffer str){
str.append("world");
}
总结
- 基本数据类型传值,对形参的修改不会影响实参
- 引用类型传引用,形参和实参指向同一个内存地址(同一个对象),所以对参数的修改会影响到实际的对象
-
String,Integer,Double等immutable的类型特殊处理,可以理解为传值,最后的操作不会修改实参对象