一个实例介绍——java中的参数传递(传值、传引用)

java的学习之路总是不平坦的,最近被java中函数参数的传递搞得有点糊涂了,所以经过查资料,现在总结一下自己的理解。下面这个例子不一定是那么有代表性,但是我个人觉得还是能说明一些问题。在这里的总结只是想让后面的人少走一些弯路,共同学习。

  • 首先,看一行代码:Human man = new Human();相信学过C/C++的人可能会误以为man是一个对象,反正我一开始是这么觉得的,原来man只是一个对象的引用,对象的创建是用new Human()实现的。
  • 然后,java中调用一个函数,参数间有一个拷贝动作(值的拷贝、对象引用的拷贝),本人刚看到是引用时,还以为和C++中的一样没有拷贝动作呢。
  • 最后,关于概念上的传值、传引用,个人觉得不需要去纠结那么多,也可以全部理解成传值(这一点和C/C++里的理解是一样的地址也可以看作是值)。
下面看一个简单的例子:
package calculate;

class Test{
	int val1;
	int val2;
	Test(int i1, int i2){
		val1 = i1;
		val2 = i2;
	}
}

public class Demo {
	
	Test test1;
	Test test2;
	
	public static void main(String[] args) {
		
		Demo demo = new Demo();
		demo.test1 = new Test(1, 2);
		demo.test2 = new Test(3, 4);
		
		int i1 = 5;
		int i2 = 6;
		
		System.out.println("初始值如下:");
		System.out.println("demo.test1 = " + demo.test1.val1 + ", " + demo.test1.val2);
		System.out.println("demo.test2 = " + demo.test2.val1 + ", " + demo.test2.val2);
		System.out.println("i1 = " + i1);
		System.out.println("i2 = " + i2);
		
		System.out.println("测试如下:");
		System.out.println("传值函数(1种情况)");
		demo.fun1(i1, i2);
		System.out.println("i1 = " + i1);
		System.out.println("i2 = " + i2);
		System.out.println("传引用函数(2种情况)");
		System.out.println("1、交换两个对象引用");
		demo.fun2(demo.test1, demo.test2);
		System.out.println("demo.test1 = " + demo.test1.val1 + ", " + demo.test1.val2);
		System.out.println("demo.test2 = " + demo.test2.val1 + ", " + demo.test2.val2);
		System.out.println("1、修改对象引用的属性");
		demo.fun3(demo.test1, demo.test2);
		System.out.println("demo.test1 = " + demo.test1.val1 + ", " + demo.test1.val2);
		System.out.println("demo.test2 = " + demo.test2.val1 + ", " + demo.test2.val2);
	}
	
	void fun1(int int1, int int2){
		int1 = 4;
		int2 = 3;
	}
	
	void fun2(Test t1, Test t2){
		Test temp;
		temp = t1;
		t2 = t1;
		t2 = temp;
	}	
	
	void fun3(Test t1, Test t2){
		t1.val1 = 0;
		t1.val2 = 0;
		t2.val1 = 0;
		t2.val2 = 0;
	}	

}
结果如下所示:

这里说说本人的理解,第一个函数和C/C++中的差不多,是值的一份拷贝,所以对形参的修改并不能对实参进行改变;第二个函数,t1和t2分别是demo.test1和demo.test2的一份拷贝,此时它们分别和它们的拷贝指向同一个对象,但是对对象引用的修改(这里是修改了t1和t2指向的对象)并不会影响实参;第三个函数和第二个函数差不多,不过第三个函数内部是分别修改了t1和t2指向的对象属性,所以demo.test1和demo.test2也跟着一起修改了,因为它们都是指向同一个对象。

### Spring MVC 中的参数传递方法 在Spring MVC框架内,存在多种方式用于处理HTTP请求中的参数传递。对于简单的数据类型以及基本的对象绑定,可以通过`@RequestParam`和`@PathVariable`注解实现;而对于复杂的数据结构比如列表或是JSON格式的内容,则可能需要用到`@RequestBody`。 #### 使用 `@RequestParam` 当需要获取URL查询字符串或者是表单提交过来的名字/对形式简单类型的参数时,可以采用`@RequestParam`来进行映射[^1]。下面是一个例子展示了如何接收两个不同类型的参数并返回拼接后的字符串: ```java @RequestMapping("/r3") public String request3(@RequestParam("userName") String name, @RequestParam("userAge") Integer age){ return "姓名:" + name + ", 年龄:" + age; } ``` 此段代码定义了一个处理器方法request3(),它接受来自客户端发送到路径/r3上的GET或POST请求,并从中提取名为`userName`的字符串型参数和名为`userAge`整数型参数作为输入[^3]。 #### 利用 `@PathVariable` 如果希望从URI模板变量中读取信息,那么应该考虑使用`@PathVariable`。这种方式特别适合RESTful风格的应用程序设计模式下资源定位的需求。 #### 处理集合类参数 针对像数组或者集合这样的复合类型参数,在某些情况下可以直接利用`@RequestParam`配合泛型指定具体的容器类型来完成解析工作。例如,要接收一组爱好名称组成的列表,可参照如下做法: ```java @Controller @RequestMapping("/param") public class ParamController { /** * 接收List<String> 类型的hobbyList 参数 */ @RequestMapping(value = "/list", method = RequestMethod.POST) @ResponseBody public String list(@RequestParam List<String> hobbyList) { hobbyList.forEach(System.out::println); return "success"; } } ``` 上述实例表明了怎样通过`@RequestParam`标注的方法形参去捕获由前端入的一系列兴趣爱好的条目[^2]。 #### JSON 数据与 `@RequestBody` 最后一种常见的情形涉及到了非标准表单编码(application/x-www-form-urlencoded 或 multipart/form-data)之外的数据交换媒介——即应用层协议为application/json的情况。此时应当借助于`@RequestBody`将整个消息体反序列化成Java对象实例以便进一步操作。这里给出一段示范性的源码片段说明这一点: ```java @ResponseBody @RequestMapping("demo5") public List<Long> demo5(@RequestBody List<Long> idList) { System.out.println("ids:" + idList); return idList; } ``` 这段逻辑表示服务器端准备好了响应带有特定ID编号集合作为目标位置的API调用,而这些ID将会被封装在一个`List<Long>`里边并通过实体主体的方式携带至后台服务端点进行后续业务流程处理[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值