温习java中的数据类型,和内存分配规则
最近在搞一个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(),所以此时内部和外部的不是一个引用了,所以内部做操作不会影响外部的结果