1.对于赋值的小练习–海象之谜:
Walrus a = new Walrus(1000, 8.3);
Walrus b;
b = a;
b.weight = 5;
System.out.println(a);
System.out.println(b);
最终a和b都会被改成5,因为对象的赋值是将a,b同时指向该内存块,代表同一块内存
与之不同的是
int x = 5;
int y;
y = x;
x = 2;
System.out.println("x is: " + x);
System.out.println("y is: " + y);
将x赋值给y之后,扭转x的值并不会再扭转y的值
2.primitive type
java语言不提供让你晓得变量具体内存地址的办法,与C不同,这节俭了咱们对内存的治理,就好比你晓得你的心脏在时刻跳动,但你无奈在某一确切时刻优化其跳动速度,免得犯错误间接将其敞开。
java申明一个变量后,并不赋初值(primitive type),因而当你想应用你所申明的变量时,必须先赋予其初值。
java的赋值操作是将y的bit复制给x
8种根本类型:byte, short, int, long, float, double, boolean, char
3.援用类型
java的存储,比方int x,x在内存中的地址是200-250,那么java会创立一个盒子存储x的第一位数据,也就是200
当咱们申明一个援用类型的变量时,java会主动调配一个64bit的盒子,无论你贮存任何类型的变量
例如
Walrus someWalrus;
someWalrus = new Walrus(1000, 8.3);
第一行创立一个someWalrus盒子,贮存大小64bit
第二行通过new关键字创立实例,大小为double+int 为96bit,new返回其第一个数据的地址,存在someWalrus外面,这也就解释了为何64bit大小的盒子却存下了96bit大小的实例,因为它只是存储其地址而非实在的数据值
`Walrus someWalrus;
someWalrus = null;`
如果咱们将someWalrus赋值为null,则someWalrus贮存64个0
对于此,如果一个box notation(someWalrus)值全为0,则代表null
如果一个box notation的值非0,代表其通过箭头指向一个对象实例
综上所述,当咱们执行这段代码时:
Walrus a = new Walrus(1000, 8.3);
Walrus b;
b = a;
b.weight = 5;
创立盒子a,贮存new Walrus(weight1000,size8.3)的地址,创立盒子b,暂未赋值,但非null,b=a,示意将a贮存的内存bit信息复制给b,因而a与b同时指向Walrus(weight1000,size8.3),所以扭转b.weight也会扭转a,这就是援用类型和primitive type的区别。
4.参数传递
public static double average(double a,double b)
{
return (a+b)/2;
}
在main函数外面:
double x=5.5;
double y=10.5
double avg=average(x,y);
在传递参数时同样是遵循Golden Rule of Equal,即average函数创立两个新的盒子x,y,这两个x,y 有他本人的作用域,在传递参数时只是将main外面的x,y复制到average外面的x,y。
5.一个加深了解的练习:
public static void main(String[] args) {
Walrus walrus = new Walrus(3500, 10.5);
int x = 9;
doStuff(walrus, x);
System.out.println(walrus);
System.out.println(x);
}
public static void doStuff(Walrus W, int x) {
W.weight = W.weight - 100;
x = x - 5;
}
请判断打印出的x与walrus的值
解决问题的要害是了解java在贮存primitive type类型变量与reference type类型变量的区别,后者的盒子贮存的是walrus实例对象的地址,指向walrus(data存在其中),而前者则间接贮存其值data
因而,无论是函数参数传递还是赋值操作,实质上都是将盒子外面存的bit复制一份放到新盒子外面去
所以本题中,
public static void doStuff(Walrus W,int x);
首先创立了两个空盒子W和x,在main中执行doStuff(walrus,x)时,将main中的walrus和x盒子中的值复制一份传递给doStuff外面去了,咱们晓得walrus外面存储的是64bit的地址,而x则贮存的是32bit的值,因而这样做的后果是:
doStuff外面的W和main外面的walrus是寄存的同一个地址,因而均指向Walrus(3500,10.5),而因为main外面的x只是贮存的值而非地址,在函数传参时拷贝过来的就是x的值,而函数本人也有一个作用域,因而在函数外面对x进行减法不影响main外面的x
最终输入是
Walrus(3400,10.5)
x=9 不变
同样是援用类型的还有数组
int [] a;
a=new int[] {1,2,3};
第一行是创立了一个大小为64bit的盒子,第二行创立一个大小为3X32bit的盒子贮存数据,而后通过new关键字返回首地址,=赋值给第一个盒子,也即是第一个盒子贮存数组的首地址
整个过程是:申明—实例化—赋值
当初a是惟一存储实例对象{1,2,3}的地址的盒子,如果咱们此时令a=new int[] {4,5,6};
那么最开始的{1,2,3}的地址就失落了,咱们再也找不到这个对象,将会Garbage collector被作为垃圾回收
发表回复