在c/c++中对于传参类型,无外乎就是传值、传引用、传指针这几种。但在java中,由于没有指针类型,其传参的方式也发生了相应的变化。之前有搜过相关的知识点一直理解的是:Java的传参方式中主要有两种:传值和传引用。(基本数据类型相当于传值,对象相当于传参)

但是,在做需求的时候遇到了,将从上一个方法中获取到的对象,当做参数传进下一个方法中的时候,如果传进来的是空对象,那么在给这个“对象”直接赋值的时候,会报空指针异常!

探究与理解:
Java中传值也就是传的是原变量的一个副本,函数内部无论怎么操作都不会影响到原变量本身,影响到的只是原变量的那个副本。

经典的一个test:

public class Test {
    public static void main(String[] args){
        , b = ;
        fun(a,b);
        System.out.println("a="+a);}
    static void fun(int m , int n){
        m = m + n;     }
}

运行结果:a=1.

另一个例子:

public class Test {
    public static void main(String[] args){
        List<String> str_1 = new LinkedList<String>();
        str_1.add(");
        fun(str_1);
        System.out.println("str_1 ="+str_1);}
    static void fun(List s){
            s.add(");}
}

运行结果: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(");
        str_2.add(");
        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在执行Java程序的时候将属于它的内存分为五部分。其中程序代码(字节码)和基本的数据类型是放在java栈的栈帧中,而对象是从堆中分配的。堆,我们可以形象的理解成“对象池”。程序和程序中需要用到的对象放在两个相对独立的区域中,那么程序怎么使用对象呢?

实际上是程序中真正使用对象的地方其实只是声明了一个对象的引用,也就是把堆中分配了的相应对象的地址放到引用中,当然引用也是放在栈内存中,栈和堆之间就是通过一个一个的引用来联系的。至于引用,我们可以把它看做是一个指针常量,这个指针指向引用对象的地址。所以,不管是基本类型变量(int,float,double等)还是对象,相应的内存地址中存放的都是一个数(无符号整数,整数,浮点数等)。当方法调用时候,方法的参数会占内存中开辟一块新的区域,同时把要传递的基本类型,或者引用类型名称复制到这块内存中,结果是,基本类型(存放在占内存中的)复制之后连同其数值也复制到了这块内存中,而对象只是复制了引用名,实际还要联系到原对象所在的堆区域中。之所以说java中传递的都是值,是因为传递得是内存地址中的数,当然,这个值对于基本类型和对象类型来说意义是不一样的,对于基本类型这个数就是其值本身,传递值的结果就是,改变新的变量的值不影响旧的变量的值;而对于对象来说这个数是它的地址,传递这个值就相当于传递了真实对象的引用,传递了引用或者说是地址的结果就是变化会全局可见。所以说java中的方法都是按值调用的!只不过基本类型和对象类型的"值"的在具体的机制上作用不同。

所以在第二个例子中,fun方法中,两个list s和m交换,实际只是str_1与str_2在栈中对应的引用值进行了交换,而引用与相应堆区域的联系并没有改变。因此,str_1与str_2的值并没有发生变化。

结论:

java中不论是基本类型还是对象,方法调用时,传递的都是值!

对于基本类型的变量,相当于操作其副本。

对于对象,相当于复制了一个引用,该引用指向的还是原变量的内存区域。

Java的对象传参问题的更多相关文章

  1. java复用和传参

    java复用和传参的三种方法总结: (1) 直接在一个类中调用函数 : 1 package test1; 2 3 public class a 4 { 5 public static void get ...

  2. [Java]_函数传参的疑惑与思考

    问题来源于leetcode上的两道题 Path Sum I && II,分别写了两个dfs. void dfs(TreeNode node , int sum , ArrayList& ...

  3. 由PHP实现单向链表引发的对象赋值,对象传参,链表操作引发的一系列问题

    2019年2月25日14:21:13 测试版本php 5.4 ,5.6,7.0,7.2 代码请看: https://www.cnblogs.com/zx-admin/p/10373866.html 1 ...

  4. datasnap远程方法支持自定义对象传参

    有同仁需要远程方法传输自定义的数据类型,他以为要自己写代码会很复杂,其实DATASNAP早就为我们想到了. datasnap的数据序列和还原真是无与伦比的强大,其远程方法支持自定义对象传参,DATAS ...

  5. Java函数的传参机制

    一 最近的一个项目,里面各种返回void,参数用引用类型,那叫一个熟和多,但是也把我绕糊涂了. 我就打算好好理一理java的传参机制,整理一番 二 很多人一听Java的传参,那一定会脱口而出,java ...

  6. SpringBoot系列: Java应用程序传参和SpringBoot参数文件

    ===========================向java 程序传参的几种形式:===========================1. 使用 OS 环境变量. 这个不推荐. 2. 使用JVM ...

  7. 在Java中动态传参调用Python脚本

    最近,又接触到一个奇葩的接口,基于老板不断催促赶时间的情况下,在重写java接口和复用已有的python脚本的两条路中选择了后者,但是其实后者并没有好很多,因为我是一个对python的认识仅限于其名称 ...

  8. dynamic结合匿名类型 匿名对象传参

    首先说明下,我一般很少用dynamic关键字(类)的,因为毕竟是由反射实现的,所以对于性能方面还是吃亏不少(注:由于心里没底,查了一些资料得知,dynamic实质上好像不是由反射实现的,其性能也比直接 ...

  9. java的方法传参,最容易混淆的问题!!!

    参数传递 参数传递,可以理解当我们要调用一个方法时,我们会把指定的数值,传递给方法中的参数,这样方法中的参数就拥有了这个指定的值,可以使用该值,在方法中运算了.这种传递方式,我们称为参数传递. 在这里 ...

随机推荐

  1. Excel&mdash;&mdash;使用OFFSET、MATCH、COUNTA实现二级菜单

    如图所示,接下来提供两种办法实现: 1.将A.B.C.D定义为名称NAME. 2.设置一级菜单单元格数据有效性为NAME. 3.设置二级菜单格数据有效为: =OFFSET($A$1,MATCH($A6 ...

  2. JSP模板继承功能实现

    背景 最近刚入职新公司,浏览一下新公司项目,发现项目中大多数JSP页面都是独立的.完整的页面,因此许多页面都会有如下重复的代码: <%@ page language="java&quo ...

  3. Windows 2008 IIS7.5中创建独立账号的FTP站点图文教程

    Windows 2008上的IIS7.5,FTP功能已经非常强大了,完全不下于Serv-U这样的第三方软件.本文小编就介绍在IIS7.5上配置独立账号的FTP站点. 1.创建Windows账号 右击点 ...

  4. linux之&quot;server&quot; directive is not allowed here in

    配置完rewrite之后重启nginx发现如下错误 "server" directive is not allowed here in* 原因是因为 外部配置的simple.con ...

  5. HTML中特殊字符和与之对应的ASCII代码

    ASCII代码是说明了在html中每个特殊字符的属性以及字符的简要说明.在使用html时,如何把ASCII代码添加到网页中.例如版权符号'©'在html中可以通过 "©"来显示. ...

  6. 【Java】C/C++与Java的简单比较

    转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/5827273.html     C/C++:            编译(不同的系统编译出不同的机器码,所以同一 ...

  7. SOD框架的数据容器,打造最适合DDD的ORM框架

    SOD框架的数据容器,打造最适合DDD的ORM框架 引言:DDD的困惑 最近,我看到园子里面有位朋友的一篇博客 <领域驱动设计系列(一):为何要领域驱动设计? >文章中有下面一段话,对DD ...

  8. SSH程序框架的整合(1)

    spring整合hibernate 有两种方式 1.注解方式 2.xml方式实现 Spring整合Hibernate有什么好处? 1.由IOC容器来管理Hibernate的SessionFactory ...

  9. 关于Python的函数(Method)与方法(Function)

    先上结论: 函数(function)是Python中一个可调用对象(callable), 方法(method)是一种特殊的函数. 一个可调用对象是方法和函数,和这个对象无关,仅和这个对象是否与类或实例 ...

  10. JAVA中的Log4j

    Log4j的简介: 使用异常处理机制==>异常 使用debug调试(必须掌握)    System.out.Print(); 001.控制台行数有限制        002.影响性能      ...