浅谈对java中传参问题的理解
之前用的c/c++比较多,在c/c++中对于传参类型,无外乎就是传值、传引用、传指针这几种。但在java中,由于没有指针类型,其传参的方式也发生了相应的变化。根据网上的信息,按我之前的理解,java中传参方式应该主要有两种:传值和传引用
一 传值
java中的传值即传递的是原变量的一个副本。基本的数据类型,如:char,int,double等类型的变量向函数传递的参数,都是变量的副本都属于传值。函数内部不论进行任何操作,都不影响变量本身,影响的只是变量的副本。
例如:
public class Test {
public static void main(String[] args){
int a = 1, b = 2;
fun(a,b);
System.out.println("a="+a); }
static void fun(int m , int n)
{
m = m + n; }
}
运行结果为:a = 1. a的值并没有发生变化, 说明此处的传参是传的值。
二 传引用
从表面上来看,java中的对象类型都是传递的引用,而不是传递的值。首先,来看一个例子(此处以LinkedList对象为例):
public class Test {
public static void main(String[] args){
List<String> str_1 = new LinkedList<String>();
str_1.add("111");
fun(str_1);
System.out.println("str_1 ="+str_1);
}
static void fun(List s)
{
s.add("222");
}
}
运行结果为: str_1 =[111, 222] . 从这个例子来看的话,java中兑现的传参应该是传的引用。那么,再看下面的一个例子:
public class Test {
public static void main(String[] args){
List<String> str_1 = new LinkedList<String>();
List<String> str_2 = new LinkedList<String>();
str_1.add("111");
str_2.add("333");
fun(str_1,str_2);
System.out.println("str_1 ="+str_1);
System.out.println("str_2 ="+str_2);
}
static void fun(List s,List m)
{
List<String> str = new LinkedList<String>();
str = s;
s = m;
m = str;
}
}
运行结果为:str_1 =[111] , str_2 =[333] .我们发现str_1与str_2的值并没有发生交换。 如果该对象传的是引用的话,那它们两个的值应该发生了变化才对。
然而,java中对象作为实参,传递的实际上还是值,即java中的传参传递的都是值!为什么会这么说?我会从jvm的构成的角度来解释一下自己对这个问题的理解。接下来我们先看一下JVM的结构:
三 JVM的结构及相应的解释
JVM的结构图如下:
从Jvm的结构图上可以看出来,Jvm在实现的时候将属于它的内存分为五部分,其中程序代码(严格的说应当是字节码)和基本的数据类型是放在java栈的栈帧中,而对象是从堆中分配的,堆这个东西我认为可以理解成“对象池”。程序和程序中需要用到的对象放在两个相对独立的区域中,那么程序怎么使用对象呢?实际上是程序中真正使用对象的地方其实只是声明了一个对象的引用,也就是把堆中分配了的相应对象的地址放到引用中,当然引用也是放在栈内存中,栈和堆之间就是通过一个一个的引用来联系的。至于引用,我们可以把它看做是一个指针常量,说白了,就是一个数值,这个数值所表达的是引用对象的地址。所以,不管是基本类型变量(int,float,double等)还是对象,相应的内存地址中存放的都是一个数(无符号整数,整数,浮点数等)。当方法调用时候,方法的参数会占内存中开辟一块新的区域,同时把要传递的基本类型,或者引用类型名称复制到这块内存中,结果是,基本类型(存放在占内存中的)复制之后连同其数值也复制到了这块内存中,而对象只是复制了引用名,实际还要联系到原对象所在的堆区域中。之所以说java中传递的都是值,是因为传递得是内存地址中的数,当然,这个值对于基本类型和对象类型来说意义是不一样的,对于基本类型这个数就是其值本身,传递值的结果就是,改变新的变量的值不影响旧的变量的值;而对于对象来说这个数是它的地址,传递这个值就相当于传递了真实对象的引用,传递了引用或者说是地址的结果就是变化会全局可见。所以说java中的方法都是按值调用的!只不过基本类型和对象类型的"值"的在具体的机制上作用不同。
所以在第二个例子中,fun方法中,两个list s和m交换,实际只是str_1与str_2在栈中对应的引用值进行了交换,而引用与相应堆区域的联系并没有改变。因此,str_1与str_2的值并没有发生变化。
综上,java中不论是基本类型还是对象,方法调用时,传递的都是值!
1.对于基本类型的变量,相当于操作其副本。
2.对于对象,相当于复制了一个引用,该引用指向的还是原变量的内存区域。
浅谈对java中传参问题的理解的更多相关文章
- Java中传参的值传递和引用传递问题(转)
今天遇到了一个java程序,需要用参数来返回值(虽然最后用另一种方法实现了),在网上看到这样一篇文章,很受启发. 本文章来自于http://hi.baidu.com/xzhilie/blog/item ...
- 浅谈对java中锁的理解
在并发编程中,经常遇到多个线程访问同一个 共享资源 ,这时候作为开发者必须考虑如何维护数据一致性,在java中synchronized关键字被常用于维护数据一致性.synchronized机制是给共享 ...
- 浅谈在java中list集合的排序问题
定义实体类: public class Person { private Integer id; private String name; private Integer age; public In ...
- java中传参的要点
传参的是分为:值传递和引用传递,值传递不会改变值,传递的是这个值的副本(就是把这个值拿出来拷贝一份用拷贝的值):引用传递会改变值,传递的是这个值的“地址”: String是特殊的引用类型,用Strin ...
- Mybatis中传参包There is no getter for property named 'XXX' in 'class java.lang.String'
Mybatis中传参包There is no getter for property named 'XXX' in 'class java.lang.String' 一.发现问题 <select ...
- 关于Java函数传参以及参数在函数内部改变的问题——JAVA值传递与引用最浅显的说明!
看了很多关于阐述JAVA传参到底是值传递还是引用的问题,有些说得很肤浅让人感觉似懂非懂的感觉,但是好像又能解决一些问题,然后就止步了.还有一些则是,讲得很深奥,看着好像很有道理的样子,但是其实还是没怎 ...
- Hutool工具里,POST方法,body中传参的几种调用方法
接口说明: POSTMAN测试: JAVA代码: package com.provy.guard.api; import java.util.HashMap; import java.util.Map ...
- 浅谈关于QT中Webkit内核浏览器
关于QT中Webkit内核浏览器是本文要介绍的内容,主要是来学习QT中webkit中浏览器的使用.提起WebKit,大家自然而然地想到浏览器.作为浏览器内部的主要构件,WebKit的主要工作是渲染.给 ...
- c#Winform程序调用app.config文件配置数据库连接字符串 SQL Server文章目录 浅谈SQL Server中统计对于查询的影响 有关索引的DMV SQL Server中的执行引擎入门 【译】表变量和临时表的比较 对于表列数据类型选择的一点思考 SQL Server复制入门(一)----复制简介 操作系统中的进程与线程
c#Winform程序调用app.config文件配置数据库连接字符串 你新建winform项目的时候,会有一个app.config的配置文件,写在里面的<connectionStrings n ...
随机推荐
- nginx : server_name localhost 和 chrome : Provisional headers are shown
问题相关问题现象:解决思路解决方案总结 问题相关 nginx : server_name localhost chrome : Provisional headers are shown 问题现象: ...
- SmartRoute之远程接口调用和负载
基于接口的调用远比基于基础消息交互来得更简单和便于维护,特别在业务展现上,接口作为业务表现更适合其便利性.为了让SmartRoute更适合业务应用集成,在新的一年开始SmartRoute集成了远程接口 ...
- html5表单和伪类
type = "email"; 自带验证格式type = "url"; 网址 http//:type = "tel";移动端会变成数字键盘t ...
- Redis的二八定律
常用命令: 1.setex key 有效时间 value ----------意思就是添加并设置该键值对的存活时间 2.mset key1 value1 key2 value2 key3 value3 ...
- 在VMware Workstation 9中安装Mac OS X 10.8 Mountain Lion
本文环境: CPU:Intel Core i7 920: OS:Windows 7: 内存:8G: 玩Hackintosh各有各的理由,不管什么理由,利用虚拟机安装Mac OS X都是一个可行的办法. ...
- Raid0、Raid1、Raid0+1、Raid3和Raid5 几种磁盘阵列区别
前两天发现服务器挂了,到机房重启时发现硬盘挂载不上,虽然是开发,但是在交接工作的时候被告知了一点硬件的知识,判断出是硬盘故障.这个呵呵了,修不来只能找服务器售后来换硬盘或是维修了. 关于怎么诊断出硬盘 ...
- [NOI2007]货币兑换Cash(DP+动态凸包)
第一次打动态凸包维护dp,感觉学到了超级多的东西. 首先,set是如此的好用!!!可以通过控制一个flag来实现两种查询,维护凸包和查找斜率k 不过就是重载运算符和一些细节方面有些恶心,90行解决 后 ...
- BZOJ 1337: 最小圆覆盖1336: [Balkan2002]Alien最小圆覆盖(随机增量法)
今天才知道有一种东西叫随机增量法就来学了= = 挺神奇的= = A.令ci为包括前i个点的最小圆,若第i+1个点无法被ci覆盖,则第i+1个点一定在ci+1上 B.令ci为包括前i个点的最小圆且p在边 ...
- 快速排序OC、Swift版源码
前言: 你要问我学学算法在工作当中有什么用,说实话,当达不到那个地步的时候,可能我们不能直接的感觉到它的用处!你就抱着这样一个心态,当一些APP中涉及到算法的时候我不想给其他人画界面!公司的项目也是暂 ...
- ajax 做登录 实现页面免刷新
结合之前学的知识,可以用ajax来传递数据,实现页面不用刷新,仅数据刷新,来看一下ajax是怎么来实现页面免刷新的 方的是客户端,圆的是服务器 如果没有ajax的话,客户端直接把数据传给服务器,服务器 ...