图解JAVA参数传递

简介: 今天做项目,发现了一个问题,当String作为参数传递的时候,在函数内部改变值对外部的变量值无影响,如下代码: public static void main(String[] args) { String str = "11111"; changeStr(str); System.

今天做项目,发现了一个问题,当String作为参数传递的时候,在函数内部改变值对外部的变量值无影响,如下代码:

 public static void main(String[] args) {
        String str = "11111";
        changeStr(str);
        System.out.println(str);//输出11111
    }
    public static void changeStr(String str){
        str = "22222";
    }

一开始很不解,后来想明白了,遂去对java参数传递做一个总结,以加深自己的基础知识.

1.基本类型传递

对于:

  • 整型: byte short int long
  • 浮点型 float double
  • 逻辑型 boolean
  • 字符型 char

四类八种基本类型来说,传递的都是值,因为这些值是直接保存在栈内存中的,所以传递的时候直接拷贝过去了.

public static void main(String[] args) {
        int num = 0;
        change(num);
        System.out.println(num);//输出0
    }
    public static void change(int numChange){
        numChange =5;
    }

结构如下图,也因此最外层的num的值并没有受到影响.

2.对象传递

2.1 例一

对象传递,本质上也都是值传递,只不过传递的值是该引用的拷贝.看下面实例和图解:

public static void main(String[] args) {
        Person person = new Person("aaa", 11);
        change(person);
        System.out.println(person);//输出 bbb 11
    }
    public static void change(Person personChange){
        personChange.setName("bbb");
    } 

结构图如下:
当执行change的时候,会把person变量的指向的地址拷贝一份给personChange,两者都指向同一个堆内存,即使后面做了set方法修改,但是对两者的执行毫无影响.

2.2例二

例二和之前的不同之处在change里面,对personChange进行了new操作.代码如下:

public static void main(String[] args) {
        Person person = new Person("aaa", 11);
        change(person);
        System.out.println(person);//输出 aaa 11
    }
    public static void change(Person personChange){
        personChange = new Person("bbb",12);
    }

结构图如下:

当执行change的时候,会把person变量的指向的地址拷贝一份给personChange,两者都指向同一个堆内存,接下new操作会在堆中重新创建一个person对象,此时personChange则指向这个对象,而原person的指向没发生变化,故输出aaa 11.

2.3 例三

例三是综合例一和例二,前面两个搞懂的话这个就很容易懂了.

public static void main(String[] args) {
        Person person = new Person("aaa", 11);
        change(person);
        System.out.println(person);//输出 ccc 11
    }
    public static void change(Person personChange){
        personChange.setName("ccc");
        personChange = new Person("bbb",12);
    }

结构图如下:

读者自己理解下,不懂的话再看看前面的,看看为什么输出CCC 11

2.4特殊的String

终于到最初的问题,为什么String是对象,但是却不符合上面对象传递测试出来的结果?

 public static void main(String[] args) {
        String str = "11111";
        changeStr(str);
        System.out.println(str);//输出11111
    }
    public static void changeStr(String str){
        str = "22222";
    }

原因:
因为String对象具有不可变性,所以针对操作str = "22222",在String池中不存在的时候,就是相当于str = new String(),这样变化下的话,那么就和例一 一模一样了,具体图就不画了,希望对你有帮助.
ps:如果想改变的话,可以使用Holder包装类包装String,可以参考博文:Java基础系列18:Holder技术的实现原理分析 | zifangsky的个人博客

3.总结

要理解上面的结果,就要认为Java中只有值传递:

  • 对于基本类型,直接拷贝值传递过去
  • 对于对象,拷贝当前对象的引用地址,然后把该地址传递过去,所以也是值传递.
目录
相关文章
|
11月前
|
Java Linux 定位技术
Minecraft配置文件参数说明(JAVA服务器篇)
Minecraft JAVA版服务器启动后会生成server.properties配置文件,位于minecraft_server/根目录下。该文件包含多项关键设置,如游戏模式(gamemode)、最大玩家数(max-players)、难度(difficulty)等。此文档详细说明了各配置项的功能与默认值,帮助用户高效管理服务器环境。
2876 60
|
9月前
|
人工智能 Java
Java参数传递分析
本文详细探讨了Java中参数传递的机制,明确指出Java采用的是值传递而非引用传递。通过基本数据类型(如int)和引用类型(如Map、自定义对象People)的实例测试,证明方法内部对参数的修改不会影响原始变量。即使在涉及赋值返回的操作中,表面上看似引用传递,实际仍是值传递的结果。文中结合代码示例与执行结果,深入解析了值传递的本质及容易引起混淆的情形,帮助读者准确理解Java参数传递的核心概念。
197 7
|
Java API 编译器
Java编译器注解运行和自动生成代码问题之编译时通过参数设置选项值问题如何解决
Java编译器注解运行和自动生成代码问题之编译时通过参数设置选项值问题如何解决
159 0
|
10月前
|
Java
java中一个接口A,以及一个实现它的类B,一个A类型的引用对象作为一个方法的参数,这个参数的类型可以是B的类型吗?
本文探讨了面向对象编程中接口与实现类的关系,以及里氏替换原则(LSP)的应用。通过示例代码展示了如何利用多态性将实现类的对象传递给接口类型的参数,满足LSP的要求。LSP确保子类能无缝替换父类或接口,不改变程序行为。接口定义了行为规范,实现类遵循此规范,从而保证了多态性和代码的可维护性。总结来说,接口与实现类的关系天然符合LSP,体现了多态性的核心思想。
351 0
|
缓存 安全 算法
Java面试题:如何通过JVM参数调整GC行为以优化应用性能?如何使用synchronized和volatile关键字解决并发问题?如何使用ConcurrentHashMap实现线程安全的缓存?
Java面试题:如何通过JVM参数调整GC行为以优化应用性能?如何使用synchronized和volatile关键字解决并发问题?如何使用ConcurrentHashMap实现线程安全的缓存?
223 0
|
Java
实现java执行kettle并传参数
实现java执行kettle并传参数
301 1
|
存储 算法 Java
java制作海报六:Graphics2D的RenderingHints方法参数详解,包括解决文字不清晰,抗锯齿问题
这篇文章是关于如何在Java中使用Graphics2D的RenderingHints方法来提高海报制作的图像质量和文字清晰度,包括抗锯齿和解决文字不清晰问题的技术详解。
623 0
java制作海报六:Graphics2D的RenderingHints方法参数详解,包括解决文字不清晰,抗锯齿问题
|
Java
java构造方法时对象初始化,实例化,参数赋值
java构造方法时对象初始化,实例化,参数赋值
407 1
在Java中定义一个不做事且没有参数的构造方法的作用
Java程序在执行子类的构造方法之前,如果没有用super()来调用父类特定的构造方法,则会调用父类中“没有参数的构造方法”。因此,如果父类中只定义了有参数的构造方法,而在子类的构造方法中又没有用super()来调用父类中特定的构造方法,则编译时将发生错误,因为Java程序在父类中找不到没有参数的构造方法可供执行。解决办法是在父类里加上一个不做事且没有参数的构造方法。
|
消息中间件 Java 大数据
"深入理解Kafka单线程Consumer:核心参数配置、Java实现与实战指南"
【8月更文挑战第10天】在大数据领域,Apache Kafka以高吞吐和可扩展性成为主流数据流处理平台。Kafka的单线程Consumer因其实现简单且易于管理而在多种场景中受到欢迎。本文解析单线程Consumer的工作机制,强调其在错误处理和状态管理方面的优势,并通过详细参数说明及示例代码展示如何有效地使用KafkaConsumer类。了解这些内容将帮助开发者优化实时数据处理系统的性能与可靠性。
462 7