先看代码
public class Test01{
public String String_="6";
public String String_1 = new String("5");
public int int_= 7;
public Integer Integer_ = 8;
public Dog dog_ = new Dog();
public static void main(String[] args) {
Test01 sv=new Test01();
sv.change(sv.String_,sv.String_1,sv.int_,sv.Integer_,sv.dog_);
//6 5 7 8 Dog{name='taofen'}
System.out.println(sv.String_ +" " + sv.String_1 + " " +sv.int_+" " + sv.Integer_+" " + sv.dog_);
}
//结果6 5 7 8 Dog{name='taofen'}
public void change(String a,String e,int b,Integer c,Dog d) {
a = "66";
e = new String("55");
b = 77;
c = 88;
d.name = "taofen";
}
}
class Dog{
public String name = "cxk";
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
'}';
}
}
基本类型
共有8种,即int, short, long, byte, float, double, boolean, char(注意,并没有string的基本类型)。
这种类型的定义是通过诸如int a = 3; long b = 255L;的形式来定义的,称为自动变量。值得注意的是,自动变量存的是字面值,不是类的实例,即不是类的引用,这里并没有类的存在。如int a = 3; 这里的a是一个指向int类型的引用,指向3这个字面值。这些字面值的数据,由于大小可知,生存期可知(这些字面值固定定义在某个程序块里面,程序块退出后,字段值就消失了),出于追求速度的原因,就存在于栈中。
另外,栈有一个很重要的特殊性,就是存在栈中的数据可以共享。假设我们同时定义:
int a = 3;
int b = 3;
编译器先处理int a = 3;首先它会在栈中创建一个变量为a的引用,然后查找有没有字面值为3的地址,没找到,就开辟一个存放3这个字面值的地址,然后将a指向3的地址。接着处理int b = 3;在创建完b的引用变量后,由于在栈中已经有3这个字面值,便将b直接指向3的地址。这样,就出现了a与b同时均指向3的情况。
所以基本数据类型 值复制 不改变原有
引用数据类型
方法传递的是地址,在方法栈中,将地址复制一份进行传递
String
包装类
这里比较乱人心的是包装类型,因为包装类型也是引用类型,这里应该就是和包装类型的实现有关了,在包装类型中,比如Integer a=1,有一个自动装箱的操作。其实a=1,如果现在令a=2,不会令2覆盖1(即1本身是不会变的),真正改变的是a被赋给了一个新地址,这个地址指向了2。因此方法内的改变包装类型的值就相当于改变了形参里面的地址,相当于重新new了一遍。而方法外面的实参仍旧指向含1的那个地址,一次方法内的改变不会影响方法外的实参。