01-Java程序设计语言是按值调用还是按引用调用?
在写代码过程中,我们经常会将基本类型作为参数传递给一个方法;或者将一个对象作为参数传递给一个方法。这样的方式思考,好像是既有按值调用又有按引用调用;
其实上面的回答是错误的;Java程序设计语言是按值调用,即方法得到所有参数值的一个副本;那么下面我们分析下为什么没有按引用调用
概念
- 按值调用:方法接收的是调用者提供的值;该值是参数的副本(复制一份数据操作)
- 按引用调用:方法接收的是调用者提供的变量地址(直接操作源文件)
注意两者区别:按值调用是 参数副本;按引用调用 直接操作源文件;
例子
package com.dwb.snail.day.day01;
/**
* @Description javac程序设计是按值传递
* @Date 2020/10/8 11:32 PM
* @Created by dwb
* 微信: snail_java
*/
public class CallByReference {
public static void main(String[] args) {
int a = 20;
System.out.println("基本类型调用前:" + a);
changeValue(a);
System.out.println("基本类型调用后:" + a);
Student student = new Student(18, "小明");
System.out.println("引用类型调用前:" + student);
System.out.println("引用类型调用前学生年龄:" + student.getAge());
changeStudent(student);
System.out.println("引用类型调用后:" + student);
System.out.println("引用类型调用后学生年龄:" + student.getAge());
}
private static void changeValue(int a) {
a = 10;
}
private static void changeStudent(Student student) {
student.setAge(10);
student.setName("小红");
}
private static class Student{
int age;
String name;
public Student(int age, String name) {
this.age = age;
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
}
输出:
基本类型调用前:20
基本类型调用后:20引用类型调用前:com.dwb.snail.day.day01.CallByReference$Student@61bbe9ba
引用类型调用前学生年龄:18
引用类型调用后:com.dwb.snail.day.day01.CallByReference$Student@61bbe9ba
引用类型调用后学生年龄:10
基本类型没有变化是可以理解的,因为我操作的是参数传过来的20,原来的20没有变化是对的;但是引用类型,学生的年龄变化了啊,输出的学生对象(默认是地址)没有变化;不应该是按引用调用吗?
这时候我们需要结合jvm堆栈理解
-
Java虚拟机栈描述的是Java方法执行的内存模型:每个方法执行的同时会创建一个栈帧
-
栈帧(Stack Frame)是用于支持虚拟机进行方法调用和方法执行的数据结构。它是虚拟机运行时数据区中的java虚拟机栈的栈元素
-
栈帧存储了方法的局部变量表、操作数栈、动态连接和方法返回地址等信息
每个方法的运行都会创建一个栈帧;该栈帧存放参数的值;如果是基本类型,则拷贝基本类型值的副本到栈帧中;如果是引用类型,则拷贝引用类型的引用副本到栈帧中,都是创建了副本到栈帧中,所以java程序设计是按值调用。
网友评论