最近在搞一个springBoot多线程的问题,其中有个map的值总是会出现数据脏读的问题,原因就是因为对java中值传递和引用传递理解不够深刻,今天专门又查了查温习一遍
java中的数据类型
java中把内存分为了四部分
1.存代码: 编译后的class文件
2.存静态变量: 例如用static关键字的变量,例如字符串常量。
3.栈(stack): 是用来装变量和引用类型的!但区别在于,装了变量以后,变量上是有值的,而引用类型本身在栈上是没有值的。
4.堆(heap): 堆可以回一句话概括,装new出来的东西!
综上所述,基本数据类型都存在栈中,而引用类型,变量是放在栈中,真正有内容的东西放在堆中,也就是当new了一个新的引用类型,他的内容就会放在堆中,同时栈中的引用类型变量会指向堆中你new出来的东西!
public static void main(String[] args) {
int a = 25;
float w = 77.5f;
valueCrossTest(a, w);
System.out.println("方法执行后的age:" + a);
System.out.println("方法执行后的weight:" + w);
Person p = new Person();
p.setName("我是马化腾");
p.setAge(45);
PersonCrossTest(p);
System.out.println("方法执行后的name:" + p.getName());
}
public static void valueCrossTest(int age, float weight) {
System.out.println("传入的age:" + age);
System.out.println("传入的weight:" + weight);
age = 33;
weight = 89.5f;
System.out.println("方法内重新赋值后的age:" + age);
System.out.println("方法内重新赋值后的weight:" + weight);
}
public static void PersonCrossTest(Person person) {
System.out.println("传入的person的name:" + person.getName());
person=new Person();//加多此行代码
person.setName("我是张小龙");
System.out.println("方法内重新赋值后的name:" + person.getName());
}
执行结果为:
传入的age:25
传入的weight:77.5
方法内重新赋值后的age:33
方法内重新赋值后的weight:89.5
方法执行后的age:25
方法执行后的weight:77.5
传入的person的name:我是马化腾
方法内重新赋值后的name:我是张小龙
方法执行后的name:我是马化腾
基本类型作为参数传递时,是传递值的拷贝,无论你怎么改变这个拷贝,原值是不会改变的,输出的结果证明了这一点,所以不管在方法中怎么修改age的值,后面的打印依然还是25
在Java中对象作为参数传递时,是把对象在内存中的地址拷贝了一份传给了参数。此时对该对象的操作会改变之前对象的值,但是因为中间有一步操作是
person=new Person();//加多此行代码 就代表person的引用指向了一个新的new person(),所以此时内部和外部的不是一个引用了,所以内部做操作不会影响外部的结果