之前用的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. Android搜索框以及内容提供器

    先看结果: 相关的官方文档在这里:Creating a Search Interface Android官方提供了两种方式: 弹出一个Dialog,覆盖当前的Activity界面 在AppBar中扩展 ...

  2. docker - 容器里安装mysql

    在docker中安装mysql ubuntu官方镜像是精简的ubuntu系统,很多软件和库没有安装,所以直接安装mysql的话依赖较多,建议直接从源码编译安装mysql 通过命令行安装 先启动一个容器 ...

  3. MongoDB学习总结(二) —— 基本操作命令(增删改查)

    上一篇介绍了MongoDB在Windows平台下的安装,这一篇介绍一下MongoDB的一些基本操作命令. 下面我们直奔主题,用简单的实例依次介绍一下. > 查看所有数据库 (show dbs) ...

  4. iOS开发~制作同时支持armv7,armv7s,arm64,i386,x86_64的静态库.a

    一.概要 平时项目开发中,可能使用第三方提供的静态库.a,如果.a提供方技术不成熟,使用的时候就会出现问题,例如: 在真机上编译报错:No architectures to compile for ( ...

  5. css居中问题

    学习过程中遇到css居中问题 , 也查阅了资料,每个人的方法都不尽相同,而且当时看懂了,过后就记混淆了;so作为一个前端小白,也来写一下俗话说好脑子不如烂笔头,毕竟自己知道的也不多,其实是抱着学习和交 ...

  6. 2017年2月16日-----------乱码新手自学.net 之MVC模型

    第二篇博文,最近学习的内容还是回到了正题:ASP.NET MVC5之上.虽然EF学了个一知半解,但是用这点知识,看MVC5的MODEL部分应该还是够了.尽管周末还要恶补一下EF才行. (一)MVC简述 ...

  7. windows下读取utf-8文件

    #include <stdio.h> #include <tchar.h> #include <memory> int main() { FILE* fp1 = f ...

  8. JMeter使用简单教程

    去Apache JMeter官网下载最新的Windows下的zip安装包并解压     进入JMeter安装目录下的bin目录,双击jmeter.bat,运行JMeter程序     打开测试计划主界 ...

  9. JVM 堆和栈的区别

      栈内存:   程序在栈内存中运行   栈中存的是基本数据类型和堆中对象的引用   栈是运行时的单元   栈解决程序的运行问题,即程序如何执行,或者说如何处理数据   一个线程一个独立的线程栈   ...

  10. 架构师之路——单一职责原则SRP (我单纯,我快乐)

    定义: 不要存在多于一个导致类变更的原因.通俗地讲,一个类只做一件事情.   单一职责原则的好处: 1.类的复杂性降低,实现什么职责都有清晰明确的定义: 2.可读性提高,复杂性降低,那当然可读性提高了 ...