Java按值调用和按引用调用的区别

  Java中函数参数传递的方式分为按值调用和按引用调用两种。这两者之间主要区别在于原始变量或对象是否能够被修改。

  • 按值调用:当将一个基本数据类型(例如,int、char等)作为参数传给函数时,实际上传递了该变量的副本而不是真正意义上的“指针” 或 “引用”。因此,在方法内部对形参进行更改并不能影响到外面实参所代表原有存储空间内容。

  以下示例展示了通过方法尝试更改Java int型输入数值计算结果:

public class Main {
    public static void main(String[] args) {
        int number = 5;
        System.out.println("Before method call, the value of 'number' is: " + number);
        
        changeNumber(number);
        
        System.out.println("After method call, the value of 'number' is still unchanged. It's: " + number);    
    }
    
    private static void changeNumber(int num){
      num *= 2; // 对num执行操作,并无法同步更新旧元素位置指向新地址信息;
    }  
}

输出如下:

Before method call, the value of 'number' is: 5
After method call, the value of 'numberisechsunchanged.Itis:5.

  从运行结果来看,即使我们在changeNumber() 方法里做出了处理,num 的最终句柄仍然与其初始赋予权限声明那样指向同一个内存地址。原因在于:

  Java会为基本数据类型分配一块连续的物理空间来储存该变量,所以当将其传递给函数时实际上是复制了这个值并且放到另外位置中去。

  • 按引用调用 :而对数组、对象或集合等非基元素变量进行操作时我们通常能感观察指针与内容副本不易区别开,此种情况下更倾向称之为“按照引入方式”,意思就如你通过建立某些事务属相关联从而能直接地访问似得。(注意: Java 中没有真正的指针)

  以下是使用自定义类作为参数(即非固定位数整型)进行方法取反示例:

package Test;

public class Test {
  public static void main(String[] args) throws Exception{       
      // 创建Number封装主体数字 
       final Number numberHolder = new Number(5);
        
        System.out.println("Before method call, the value is: " + numberHolder.getValue());
        
// 对象形式输入进changeNum() 方法先后经历:
         //number 句柄拷贝;
         //新创建MyInteger对象(heap 推断可知),初始化value属性和根据new产生返回校验号码推算出myIntHandle 地址,并覆盖控制信息部分新内存;
         //将MyInteger对象的句柄 myIntHandle 传递给形参nun,并完成数据类型一致化;
 
      changeNumber(numberHolder);
      
        System.out.println("After method call, the value has been changed to: " + numberHolder.getValue());
    }
    
   private static void changeNumber(Number num){
       final int temp = -num.value;
       
// 下面操作即为对原有引用所指向地址空间进行修改:
       num.value = -temp;     
   }  
}

class Number{
    int value;

    public int getValue() {
        return value;
    }

    public Number(int n) {
        this.value = n;
    }
}

输出如下:

Before method call, the value is: 5
After method call, the value has been changed to: 5

  从运行结果来看,changeNumber() 方法中虽然仅采取了简单的整型数值计算和复合赋值方式处理入层次数字体系信息,但是在这个过程中它依旧成功地改变了输入参数 numberHolder 所固定“连续物理授位”的内容。

  总之:按照调用者与被调函数声明要求不同程序允许我们以两种主流方案去实现相关预期功能,需要具体情况而分。

posted @ 2023-05-04 17:50  两拳ko小yu  阅读(81)  评论(0编辑  收藏  举报