关于Java的传值和传址问题

本文通过具体示例深入探讨Java中参数传递的机制,包括按值传递与按引用传递的区别,并重点分析了String类型及包装类在方法调用过程中的行为表现。
package com.jstyle.demo;

import java.util.ArrayList;
import java.util.List;

public class ParaPassingTest {

	public void test1() {
		int[] x = new int[2];
		x[0] = 1;
		x[1] = 2;
		test2(x);
		System.out.println("x[0]=" + x[0]);
		System.out.println("x[1]=" + x[1]);

		int[] xx = new int[2];
		xx[0] = 1;
		xx[1] = 2;
		test3(xx);
		System.out.println("xx[0]=" + xx[0]);
		System.out.println("xx[1]=" + xx[1]);

		int y = 12;
		test4(y);
		System.out.println("y=" + y);

		String str = new String("hello");
		List<String> list = new ArrayList<String>();
		list.add("hello");
		test5(str, list);
		System.out.println("str=" + str);
		System.out.println("list.get(0)= " + list.get(0));

		Integer i = new Integer(5);
		Double d = new Double(78);
		Float f = new Float(45.36);
		Character c = new Character('c');
		test6(i, d, f, c);
		System.out.println("i=" + i);
		System.out.println("d=" + d);
		System.out.println("f=" + f);
		System.out.println("c=" + c);
	}

	public void test2(int[] x) {
		x = new int[2];
		x[0] = 5;
		x[1] = 6;
	}

	public void test3(int[] x) {
		x[0] = 5;
		x[1] = 6;
	}

	public void test4(int y) {
		y = y + 10;
	}

	public void test5(String str, List<String> list) {
		str = "world";
		list.set(0, "world");
	}

	public void test6(Integer i, Double d, Float f, Character c) {
		i = 6;
		d = 789D;
		f = 45.363f;
		c = 'd';
	}

	public static void main(String[] args) {
		ParaPassingTest test = new ParaPassingTest();
		test.test1();
	}
}


前几天遇到一个问题,一个方法中传入了String型的变量str,在方法内修改str的值,但是方法没有返回这个str,而是在调用后直接使用这个str。本以为str的值应该改变,但是实际上没有。可参照以上代码。

在Java中,对象的传递,String和包装类除外,是按址传递。

String和包装类以及基本数据类型,是按值传递。包装类的特质之一是对其值进行操作时会体现出其对应的基本类型的性质。String的存储实际上通过char[]来实现,相当于是char[]的包装类。


### 引用的概念及区别 #### 1. (Call by Value) 在方式中,实际参数的副本被递给形式参数。这意味着任何对形参的操作都不会影响实参本身[^1]。这种方式通常用于简单的数据类型,比如整数或浮点数。 以下是的一个简单示例: ```c void add(int a, int b) { a += b; // 修改的是a的本地副本 } int main() { int x = 5; int y = 3; add(x, y); printf("%d\n", x); // 输出仍然是5,因为x未受影响 return 0; } ``` #### 2. (Call by Reference/Pointer) 是指将变量的实际内存地作为参数递给函数的形式参数。这样,在函数内部可以直接操作原始变量的内容,从而改变其[^4]。这种机制常见于C/C++等支持指针的语言中。 下面展示了一个利用指针实现乘法功能的例子: ```c void multiplyByTwo(int *pX) { (*pX) *= 2; // 改变原位置上的数 } int main(){ int z=7; multiplyByTwo(&z); printf("Result:%d ",z); // 结果应显示为14 return 0; } ``` 对于Java而言,尽管它不直接暴露指针概念,但对于对象来说实际上采用了一种特殊的“按递”,即递的是对象引用的拷贝而非真正的引用本身[^2]。 #### 3. 引用(Call by Reference with Modern Languages Perspective) 某些现代高级语言提供了更直观的方式处理类似需求——通过显式的引用类型来完成所谓的“引用”。例如,在C++中有专门的关键字`&`表示引用;而在Python里一切皆可视为对象,因此本质上也是基于引用计数管理资源释放等问题[^3]。 考虑如下C++代码片段: ```cpp void swapValues(int &val1, int &val2){ int temp=val1; val1=val2; val2=temp; } // 调用swapValues时无需取地符& ``` #### 区别总结表 | 特性 | **** | ** (通过指针)** | **引用** | |--------------|-----------------------------|------------------------------|---------------------------| | 数据共享 | 不共享 | 共享 | 共享 | | 性能开销 | 较低 | 可能较高(取决于上下文) | 高效 | | 安全性 | 更安全 | 存在潜在危险 | 相当安全 | ---
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值