最近好多初学者问我这个问题,说怎么前面学的方法说数据通过传参不能修改外面变量的属性值,学到后面又可以改变很是迷糊,这里我来解答一下。
目录
1 区分参数是基本类型还是引用数据类型
2 实例说明
2.1 变量存储位置
2.2 方法内基本数据类型值传递修改
2.3 引用数据类型通过方法修改数据
3 结论
1 区分参数是基本类型还是引用数据类型
因为很多的教学或者书籍讲解都是很明确的讲解基本数据类型就是常见八大类:六种数字类型(四个整数型,两个浮点型),一种字符类型,还有一种布尔型,很少去单独开辟一章说什么是引用数据类型,引用数据类型:引用类型继承与Object类,引用(即指针)是存储在有序的内存栈上,而对象本身的值存储在内存堆中。
这里要提到jvm内存分析大致说一个笼统的概述:
- 堆: 类的成员变量引用, new且只有new出来的对象放在堆里,只要是引用数据类型变量,其具体内容都是存放在堆中的,而栈中存放的是其具体内容所在内存的地址之后通过引用来拿到其中的值。
- 栈:运行时,成员方法的局部变量及其在方法中定义的非全局基本数据类型变量的具体内容是存储在栈中。
- 方法区: class 文件常量池,存放成员变量里的字面量,字符串常量。 静态成员变量。运行时常量池,存放成员函数运行时的常量。
实际上
基本类型:值存放在局部变量表中,无论如何修改只会修改当前栈帧的值,方法执行结束对方法外不会做任何改变;此时需要改变外层的变量,必须返回主动赋值,或者外部覆盖掉原来的值才能从根本进行修改。
引用数据类型:栈帧存放在局部变量表中,调用方法的时候,副本引用压栈,赋值仅改变副本的引用。但是如果直接改变副本引用的值,修改了引用地址的对象,此时方法以外的引用此地址对象当然被修改。假如说方法内修改了堆的内容但是栈帧还是指向原来对象所值的位置。
2 实例说明
2.1 变量存储位置
public class Main{
public static void main(String[] args){
//基本数据类型
int a=5;
double b=3.14;
//引用数据类型
String str="helloworld";
}
}
解析:
2.2 方法内基本数据类型值传递修改
//基本数据类型作为方法参数被调用
public class Main{
public static void main(String[] args){
int msg = 100;
System.out.println("调用方法前msg的值:\n"+ msg); //100
fun(msg);
System.out.println("调用方法后msg的值:\n"+ msg); //100
}
public static void fun(int temp){
temp = 0;
}
}
运行效果:
解析:
2.3 引用数据类型通过方法修改数据
//引用数据类型作为方法参数被调用
class Book{
String name;
double price;
public Book(String name,double price){
this.name = name;
this.price = price;
}
public void getInfo(){
System.out.println("图书名称:"+ name + ",价格:" + price);
}
public void setPrice(double price){
this.price = price;
}
}
public class Main{
public static void main(String[] args){
Book book = new Book("Java开发指南",66.6);
book.getInfo(); //图书名称:Java开发指南,价格:66.6
fun(book);
book.getInfo(); //图书名称:Java开发指南,价格:99.9
}
public static void fun(Book temp){
temp.setPrice(99.9);
}
}
运行效果:
、
解析:
3 结论
- 如果传入的是基本类型,该变量在方法1中的值不变,需要return 返回值
- 如果传入的是引用类型(对象),不修改该变量原指针时,该变量在方法1中的值将改变
- 不管传入方法2的参数是什么类型,方法2内部都能够获取到方法1中该参数的值