之前用的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中传参问题的理解的更多相关文章

  1. Java中传参的值传递和引用传递问题(转)

    今天遇到了一个java程序,需要用参数来返回值(虽然最后用另一种方法实现了),在网上看到这样一篇文章,很受启发. 本文章来自于http://hi.baidu.com/xzhilie/blog/item ...

  2. 浅谈对java中锁的理解

    在并发编程中,经常遇到多个线程访问同一个 共享资源 ,这时候作为开发者必须考虑如何维护数据一致性,在java中synchronized关键字被常用于维护数据一致性.synchronized机制是给共享 ...

  3. 浅谈在java中list集合的排序问题

    定义实体类: public class Person { private Integer id; private String name; private Integer age; public In ...

  4. java中传参的要点

    传参的是分为:值传递和引用传递,值传递不会改变值,传递的是这个值的副本(就是把这个值拿出来拷贝一份用拷贝的值):引用传递会改变值,传递的是这个值的“地址”: String是特殊的引用类型,用Strin ...

  5. 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 ...

  6. 关于Java函数传参以及参数在函数内部改变的问题——JAVA值传递与引用最浅显的说明!

    看了很多关于阐述JAVA传参到底是值传递还是引用的问题,有些说得很肤浅让人感觉似懂非懂的感觉,但是好像又能解决一些问题,然后就止步了.还有一些则是,讲得很深奥,看着好像很有道理的样子,但是其实还是没怎 ...

  7. Hutool工具里,POST方法,body中传参的几种调用方法

    接口说明: POSTMAN测试: JAVA代码: package com.provy.guard.api; import java.util.HashMap; import java.util.Map ...

  8. 浅谈关于QT中Webkit内核浏览器

    关于QT中Webkit内核浏览器是本文要介绍的内容,主要是来学习QT中webkit中浏览器的使用.提起WebKit,大家自然而然地想到浏览器.作为浏览器内部的主要构件,WebKit的主要工作是渲染.给 ...

  9. c#Winform程序调用app.config文件配置数据库连接字符串 SQL Server文章目录 浅谈SQL Server中统计对于查询的影响 有关索引的DMV SQL Server中的执行引擎入门 【译】表变量和临时表的比较 对于表列数据类型选择的一点思考 SQL Server复制入门(一)----复制简介 操作系统中的进程与线程

    c#Winform程序调用app.config文件配置数据库连接字符串 你新建winform项目的时候,会有一个app.config的配置文件,写在里面的<connectionStrings n ...

随机推荐

  1. (转)JAVA的整型与字符串相互转换

    JAVA的整型与字符串相互转换1如何将字串 String 转换成整数 int? A. 有两个方法: 1). int i = Integer.parseInt([String]); 或         ...

  2. Java LinkedList特有方法程序小解 && 使用LinkedList 模拟一个堆栈或者队列数据结构。

    package Collection; import java.util.LinkedList; /* LinkedList:特有的方法 addFirst()/addLast(); getFirst( ...

  3. php正则表达式(持续更新)

    1.字符串替换多个关键字 $pattern = array('/a/', '/a/', '/a/'); $replacement = array('x', 'y', 'z'); $subject = ...

  4. WP8.1开发中关于如何显示.gif格式动态格式图片方法

    这几天又遇到个问题,就是如何显示动态图片,本来以为和显示静态图片一样,谁知不行,在网上一查才知道WP8.1不支持.gif格式动态图片的显示: 后来又在MSDN论坛上查找,也有人问类似的问题,后来就大概 ...

  5. [Hadoop] - Cannot run program "cmake"

    在编译hadoop的过程中,遇到缺少cmake命令的异常,异常信息为:Cannot run program "cmake" (in directory "/opt/wor ...

  6. MongoDB【第一篇】安装

    第一步:准备 1. 操作系统 CentOS-7-x86_64-Everything-1511 2. MongoDB 版本 mongodb-linux-x86_64-rhel70-3.4.2 3. 设置 ...

  7. 【CNMP系列】CentOS7.0下安装FTP服务

    一个小插曲,安装一个FTP服务,便于和远程服务器的文件沟通.后续我们会讲到如何使用Capistrano配合git完成服务器的代码部署以及发布流程.现在,代码先走FTP吧,挺稳. FTP简介 FTP 是 ...

  8. p1154 地平线

    题目描述 Farmer John的牛们认为,太阳升起的那一刻是一天中最美好的,在那时她们可以看到远方城市模糊的轮廓.显然,这些轮廓其实是城市里建筑物模糊的影子. 建筑物的影子实在太模糊了,牛们只好把它 ...

  9. (三目运算符)PHP中问号?和冒号: 的作用

    <表达式1>?<表达式2>:<表达式3>; "?"运算符的含义是: 先求表达式1的值, 如果为真, 则执行表达式2,并返回表达式2的结果 ; 如 ...

  10. 前端发展态势 && 前端工作流程个人浅析

    于在未开启cleartype的情况下,一些中文字体在非偶数字号下的显示效果欠佳,所以一般建议使用12.14.16.18.22px等偶数字号.也就 是对某个分辨率选择离它最近的偶数字号.例如:屏幕横向分 ...