Java 是传值还是传引用

实战指南:如何用DCCRN模型提升语音增强效果(附代码示例) 本文提供了基于DCCRN模型进行语音增强的实战指南。通过深入解析复数网络如何协同处理语音的幅度与相位信息,并附有完整的PyTorch代码实现,帮助开发者从数据准备、模型搭建到训练调优,构建高效的实时语音增强系统,有效提升嘈杂环境下的语音清晰度。 阅读详情


1. 简单类型是按值传递的

  Java 方法的参数是简单类型的时候,是按值传递的 (pass by value)。这一点我们可以通过一个简单的例子来说明:

/* 例 1 */
/**
 * @(#) Test.java
 * @author fancy
 */
public class Test {
    public static void test(boolean test) {
        test = ! test;
        System.out.println("In test(boolean) : test = " + test);
    }
    public static void main(String[] args) {
        boolean test = true;
        System.out.println("Before test(boolean) : test = " + test);
        test(test);
        System.out.println("After test(boolean) : test = " + test);
    }
}

  运行结果:

Before test(boolean) : test = true
In test(boolean) : test = false
After test(boolean) : test = true

  不难看出,虽然在 test(boolean) 方法中改变了传进来的参数的值,但对这个参数源变量本身并没有影响,即对 main(String[]) 方法里的 test 变量没有影响。那说明,参数类型是简单类型的时候,是按值传递的。以参数形式传递简单类型的变量时,实际上是将参数的值作了一个拷贝传进方法函数的,那么在方法函数里再怎么改变其值,其结果都是只改变了拷贝的值,而不是源值。

2. 什么是引用

  Java 是传值还是传引用,问题主要出在对象的传递上,因为 Java 中简单类型没有引用。既然争论中提到了引用这个东西,为了搞清楚这个问题,我们必须要知道引用是什么。

  简单的说,引用其实就像是一个对象的名字或者别名 (alias),一个对象在内存中会请求一块空间来保存数据,根据对象的大小,它可能需要占用的空间大小也不等。访问对象的时候,我们不会直接是访问对象在内存中的数据,而是通过引用去访问。引用也是一种数据类型,我们可以把它想象为类似 C 语言中指针的东西,它指示了对象在内存中的地址——只不过我们不能够观察到这个地址究竟是什么。

  如果我们定义了不止一个引用指向同一个对象,那么这些引用是不相同的,因为引用也是一种数据类型,需要一定的内存空间来保存。但是它们的值是相同的,都指示同一个对象在内存的中位置。比如

String a = "Hello";
String b = a;

  这里,a 和 b 是不同的两个引用,我们使用了两个定义语句来定义它们。但它们的值是一样的,都指向同一个对象 "Hello"。也许你还觉得不够直观,因为 String 对象的值本身是不可更改的 (像 b = "World"; b = a; 这种情况不是改变了 "World" 这一对象的值,而是改变了它的引用 b 的值使之指向了另一个 String 对象 a)。那么我们用 StringBuffer 来举一个例子:

/* 例 2 */
/**
 * @(#) Test.java
 * @author fancy
 */
public class Test {
    public static void main(String[] args) {
        StringBuffer a = new StringBuffer("Hello");
        StringBuffer b = a;
        b.append(", World");
        System.out.println("a is " + a);
    }
}

  运行结果:

a is Hello, World

  这个例子中 a 和 b 都是引用,当改变了 b 指示的对象的值的时候,从输出结果来看,a 所指示的对象的值也改变了。所以,a 和 b 都指向同一个对象即包含 "Hello" 的一个 StringBuffer 对象。

  这里我描述了两个要点:
  1. 1. 引用是一种数据类型,保存了对象在内存中的地址,这种类型即不是我们平时所说的简单数据类型也不是类实例(对象);
  2. 2. 不同的引用可能指向同一个对象,换句话说,一个对象可以有多个引用,即该类类型的变量。
3. 对象是如何传递的呢

  关于对象的传递,有两种说法,即“它是按值传递的”和“它是按引用传递的”。这两种说法各有各的道理,但是它们都没有从本质上去分析,即致于产生了争论。

  既然现在我们已经知道了引用是什么东西,那么现在不妨来分析一下对象作是参数是如何传递的。还是先以一个程序为例:

/* 例 3 */
/**
 * @(#) Test.java
 * @author fancy
 */
public class Test {
    public static void test(StringBuffer str) {
        str.append(", World!");
    }
    public static void main(String[] args) {
        StringBuffer string = new StringBuffer("Hello");
        test(string);
        System.out.println(string);
    }
}

  运行结果:

Hello, World!

  test(string) 调用了 test(StringBuffer) 方法,并将 string 作为参数传递了进去。这里 string 是一个引用,这一点是勿庸置疑的。前面提到,引用是一种数据类型,而且不是对象,所以它不可能按引用传递,所以它是按值传递的,它么它的值究竟是什么呢?是对象的地址。

  由此可见,对象作为参数的时候是按值传递的,对吗?错!为什么错,让我们看另一个例子:

/* 例 4 */
/**
 * @(#) Test.java
 * @author fancy
 */
public class Test {
    public static void test(String str) {
        str = "World";
    }
    public static void main(String[] args) {
        String string = "Hello";
        test(string);
        System.out.println(string);
    }
}

  运行结果:

Hello

  为什么会这样呢?因为参数 str 是一个引用,而且它与 string 是不同的引用,虽然它们都是同一个对象的引用。str = "World" 则改变了 str 的值,使之指向了另一个对象,然而 str 指向的对象改变了,但它并没有对 "Hello" 造成任何影响,而且由于 string 和 str 是不同的引用,str 的改变也没有对 string 造成任何影响,结果就如例中所示。

  其结果是推翻了参数按值传递的说法。那么,对象作为参数的时候是按引用传递的了?也错!因为上一个例子的确能够说明它是按值传递的。

  结果,就像光到底是波还是粒子的问题一样,Java 方法的参数是按什么传递的问题,其答案就只能是:即是按值传递也是按引用传递,只是参照物不同,结果也就不同。

4. 正确看待传值还是传引用的问题

  要正确的看待这个问题必须要搞清楚为什么会有这样一个问题。

  实际上,问题来源于 C,而不是 Java。

  C 语言中有一种数据类型叫做指针,于是将一个数据作为参数传递给某个函数的时候,就有两种方式:传值,或是传指针,它们的区别,可以用一个简单的例子说明:

/* 例 5 */
/**
 * @(#) test.c
 * @author fancy
 */
void SwapValue(int a, int b) {
    int t = a;
    a = b;
    b = t;
}
void SwapPointer(int * a, int * b) {
    int t = * a;
    * a = * b;
    * b = t;
}
void main() {
    int a = 0, b = 1;
    printf("1 : a = %d, b = %d/n", a, b);
    SwapValue(a, b);
    printf("2 : a = %d, b = %d/n", a, b);
    SwapPointer(&a, &b);
    printf("3 : a = %d, b = %d/n", a, b);
}

  运行结果:

1 : a = 0, b = 1
2 : a = 0, b = 1
3 : a = 1, b = 0

  大家可以明显的看到,按指针传递参数可以方便的修改通过参数传递进来的值,而按值传递就不行。

  当 Java 成长起来的时候,许多的 C 程序员开始转向学习 Java,他们发现,使用类似 SwapValue 的方法仍然不能改变通过参数传递进来的简单数据类型的值,但是如果是一个对象,则可能将其成员随意更改。于是他们觉得这很像是 C 语言中传值/传指针的问题。但是 Java 中没有指针,那么这个问题就演变成了传值/传引用的问题。可惜将这个问题放在 Java 中进行讨论并不恰当。

  讨论这样一个问题的最终目的只是为了搞清楚何种情况才能在方法函数中方便的更改参数的值并使之长期有效。

  Java 中,改变参数的值有两种情况,第一种,使用赋值号“=”直接进行赋值使其改变,如例 1 和例 4;第二种,对于某些对象的引用,通过一定途径对其成员数据进行改变,如例 3。对于第一种情况,其改变不会影响到方法该方法以外的数据,或者直接说源数据。而第二种方法,则相反,会影响到源数据——因为引用指示的对象没有变,对其成员数据进行改变则实质上是改变的该对象。

5. 如何实现类似 swap 的方法

  传值还是传引用的问题,到此已经算是解决了,但是我们仍然不能解决这样一个问题:如果我有两个 int 型的变量 a 和 b,我想写一个方法来交换它们的值,应该怎么办?

  结论很让人失望——没有办法!因此,我们只能具体情况具体讨论,以经常使用交换方法的排序为例:

/** 例 6 */
/**
 * @(#) Test.java
 * @author fancy
 */
public class Test {
    public static void swap(int[] data, int a, int b) {
        int t = data[a];
        data[a] = data[b];
        data[b] = t;
    }
    public static void main(String[] args) {
        int[] data = new int[10];
        for (int i = 0; i < 10; i++) {
            data[i] = (int) (Math.random() * 100);
            System.out.print(" " + data[i]);
        }
        System.out.println();
        for (int i = 0; i < 9; i++) {
            for (int j = i; j < 10; j++) {
                if (data[i] > data[j]) {
                    swap(data, i, j);
                }
            }
        }
        for (int i = 0; i < 10; i++) {
            System.out.print(" " + data[i]);
        }
        System.out.println();
    }
}

  运行结果(情况之一):

78 69 94 38 95 31 50 97 84 1
1 31 38 50 69 78 84 94 95 97

  swap(int[] data, int a, int b) 方法在内部实际上是改变了 data 所指示的对象的成员数据,即上述讨论的第二种改变参数值的方法。希望大家能够举一反三,使用类似的方法来解决相关问题。

核磁干货 | RESTplus实战:静息态fMRI预处理全流程解析 本文详细解析了使用RESTplus工具包进行静息态fMRI数据预处理的完整流程,包括数据准备、环境配置、预处理步骤及高级分析技巧。RESTplus作为基于SPM的批处理工具,以其图形化界面和智能化参数设置显著提升了核磁静息态数据分析的效率,特别适合新手和临床研究人员。文章还分享了实战中的常见问题解决方案和性能优化技巧。 阅读详情

相关推荐

S32K144(1)新建裸机项目以及烧录调试工程

目录 1、简介 2、S32DS新建裸机项目 2.1、新建空的项目 2.2、选择标准库的S32DS 2.3、选择使用EWL官方库 2.4、新建成功 3、烧录工程 3.1、点击Debug,选择Debug Configurations 3.2、新建GDB SEGGER J-Link Debugging 3.3、确认Project和C/C++ Applicants是需要烧写的项目名和路径正确 3.4、确认Executable Device name Interface等各个配置信息正确,后点击

朗朗上口就行啦的博客 4975

java实现swap函数的几种方案

java中没有地址传递,java中都是基于值的传递。 由于java中“对基本类型的变量是不支持引用传递的”,所以根本不能像c/c++那样直接传地址。 java只能用对象做参数,传递的是对象的地址。 因此,java实现swap的方案中,不管哪种方式,都是通过对象传递的方式来实现的。 基本类型变量作为参数传递的话,是直接把变量值复制过去; 引用类型作为参数传递的话,是把引用里面的值复制过去 。 对于解决方案的选择,这个不一定的,需要看你那边的编码规范,如果没有硬性要求,个人建议还是使用包装类,这样方便你.

demo_yo的博客 1万+

手把手用ROS实现Ego-Planner动态避障:无人机撞树问题终结方案

本文详细介绍了如何在ROS和Gazebo仿真环境中,通过配置和调优Ego-Planner算法,实现无人机的动态避障功能。文章深入解析了其基于局部梯度优化的核心思想,提供了从环境搭建、参数详解到代码集成的完整实践指南,并分享了实战排错经验,旨在彻底解决无人机在复杂动态场景中的碰撞问题。

weixin_29031161的博客 1631

【Java】Java中的swap

Java中的swapC/C++中的swap学过C语言的人都知道,在C中交换两个变量可以通过指针的方式实现:void swap(int *a, int *b) { int temp; temp = a; a = b; b = temp; }C++里面可以使用指针也可以使用引用来实现: int temp; temp = *a; *a = *b;

Jackin 的博客 5万+

人工智能100问☞第5问:什么是AI三要素?

人工智能的核心三要素是​​数据、算法和算力​​,分别作为AI的“燃料”、“大脑”和“动力”,三者协同驱动智能系统的学习、推理与决策能力。

bjdx_001的博客 1994

车辆TBOX科普 第7次 TBOX技术深度解析:硬件架构与核心组件详解

摘要: TBOX(车载远程信息处理单元)是智能网联汽车的核心组件,承担数据采集、通信连接与安全交互等关键功能。其硬件架构以主控单元为核心,采用ARM架构处理器(如NXP i.MX系列)实现高效能低功耗处理,搭配DDR4/LPDDR5内存保障性能,eMMC/UFS存储确保数据可靠性。设计中需平衡车规级可靠性(AEC-Q100)、EMC兼容性及成本控制,同时集成通信、定位与安全模块。未来趋势聚焦异构计算、先进制程及功能安全(ASIL-D)与信息安全融合,推动TBOX向边缘计算节点演进。该技术是汽车智能化转型的重

IT深耕十余载,大道之简 861

java swap_Java中swap()方法的实现

为了能更多的掌握C/C++,时不时的就会拿起一本什么书看看。昨天又看到了请指针和引用的部分,又会有经典的swap()方法的实现。几乎所有人都知道了,要实现一个正确的swap()方法需要以指针或引用为参数,例如://使用指针void swap(int* a, int* b){int tmp = *a;*a = *b;*b = tmp;}//使用引用void swap(int& a,int&a...

weixin_42485957的博客 5443

qcc304x笔记之手机端显示电量(九)

默认的sdk有些安卓手机不支持电量显示,所以需要加电量显示的补丁 流程分析 1. 首先新建一个task,并将task注册给电池模块 appBatteryRegister(batteryRegistrationForm) 实现handler处理函数,当battery模块电池电量更新后,会将电池百分比值发送到本模块,然后我们就可以在handler中将实时电量同步到手机端了。 hfpAtCmdInit atCmdTask.task.handler = appAtCmdHandleM...

在云巅的博客 2201

java中实现swap函数的几种方式

java中实现swap解决方案由于java中“对基本类型的变量是不支持引用传递的”,所以根本不能像c/c++那样直接传地址,但是可以如下解决: 1.使用数组传值public class TestSwap2 {//由于java中的参数传递都是采用值传递的传递方式,因此不能使用引用符号。 //可以使用重新赋值的方法 private static int[] swap(int a, int b){

自天祐之,吉,无不利。 3万+

HandwrittenMathFormulaRecognition:基于YOLOv8的手写数学公式识别系统

输入:包含手写数学公式的图像(拍摄的板书、作业纸等)输出:对应的数字文本形式的数学公式(如LaTeX格式或文本表达式)标准的手写数学表达式数据集,包含在线轨迹及图片,广泛用于公式识别研究。包含近10万对公式图片及对应的LaTeX标注,适合训练公式识别模型。MathBrush公开手写数学公式图像数据集,含多种书写风格。手写数字与符号数据集(MNIST及其扩展)用于基础数学符号的训练。

YOLO 283

[SystemC]SystemC中的模块和程序

SystemC 中的层次结构是使用类 sc_module 创建的。sc_module 可以直接使用,也可以使用宏 SC_MODULE “隐藏”。上面的示例 SC_MODULE 创建了一个名为 nand2 的 sc_module 类对象。它的输出纯粹是输入值的函数。因此,模型可以使用最简单的 SystemC 进程,即 SC_METHOD。摘要:本节包含一个完整的简单设计,用于演示 SystemC 中模块和流程的使用。同样,重要的是要注意这不是典型的设计风格 - 但它很好而且易于理解。为什么要看模块和流程?

元直的博客 1869

Java中传值和传引用的区别

声明:此文是作为本人自己学习的心得与总结,同时也是与同学们进行交流,如果有错误的地方,希望同学们进行指正        在这里,要想搞清楚二者的区别,那么首先明白两个概念,“传值”、“传引用”。        1、传值:传值就是指将一个值传递到方法的内部。例如int a = 5,那么也就是给int型变量a赋值,值为5.如果一个方法,将这个变量传进方法的内部,则进行的就是传值。在java中,有8

【 风中摇曳的小码农】的专栏 1万+

让 RAP 弹窗参数真正变成必填:Excel Upload Action 的两种实现路径

摘要 在RAP应用中,action弹窗参数经常缺乏必填校验,导致用户体验差。本文提出两种解决方案:1)在action实现中手动校验,简单但交互不流畅;2)通过root abstract entity和abstract BDEF建模,利用field(mandatory)实现框架级校验,推荐此长期方案。后者将约束集中到模型层,使UI与执行期校验一致,特别适合ABAP Cloud环境。以Excel导入为例,强制填写备注和明确选择试运行,可避免审计问题,提升系统可靠性。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 198

Java中变量的传值和传引用

Java中变量的传值和传引用 1.Java中变量的基本类型   为了了解Java中参数的传值和传引用,我们需要先知道Java中参数的基本类型,Java中数据类型分为两大类,基本类型和对象类型。相应的,变量也有两种类型:基本类型和引用类型。 基本类型的变量保存原始值,即它代表的值就是数值本身;而引用类型的变量保存引用值,"引用值"指向内存空间的地址,代表了某个对象的引用,而不是对象本身,对象本身存放...

HNUTheMao的博客 1317

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

【JavaSE基础】深入了解Java的传值和传引用

终极手撕架构师的学习笔记:分布式+微服务+开源框架+性能优化《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!” />终极手撕架构师的学习笔记:分布式+微服务+开源框架+性能优化[外链图片转存中…(img-a95tt8ro-1713393744432)]《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

2301_76238237的博客 992

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

java传值or传引用

从C/C++转到 java的 ,一直 没有弄清java方法中的参数到底是传值还是传引用,在网上找了 两篇比较传威的 文章 。都摘抄下来 : 第一种说法1. 简单类型是按值传递的  Java 方法的参数是简单类型的时候,是按值传递的 (pass by value)。这一点我们可以通过一个简单的例子来说明:/* 例 1 *//**@(#) Test.java * @auth

为了你 7222

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

Java形参是传值还是传引用

1. 简单类型是按值传递的   Java 方法的参数是简单类型的时候,是按值传递的 (pass by value)。这一点我们可以通过一个简单的例子来说明: /* 例 1 */ /** * @(#) Test.java * @author fancy */ public class Test {     public static void test(boolean tes

hwuyule的专栏 523

java传值传引用_java传值与传引用总结

基本数据类型public class ParamTest {public static void main(String[] arge) {double percent = 10;System.out.println("Testing tripleValue:");System.out.println("Before: percent="+ percent);tripleValue(percent...

weixin_34558810的博客 163

java传值 传引用_Java 到底是传引用还是传值

原标题:Java 到底是传引用还是传值来源:ImportNew,问题: 如果Java是用引用来传递的话,为什么交换函数(swap)不起作用呢?回答: 你的问题引出了Java新手的常犯的错误。事实上,一些老手也很难搞清楚这些概念。Java确实使用对象的引用来做计算的,所有的对象变量都是引用。但是,Java在向方法传递参数时传的不是引用,是值。以 badSwap() 函数为例:public void ...

weixin_42510717的博客 145

java 传值传引用

java 传值传引用 值传递:传递的只是值的地址(副本),方法中对副本进行修改,不会影响调用方。 引用传递:传递的是引用的副本,方法中更改属性值会影响此地址中的数值。此时形参和实参是同一个内存地址。 空指针异常:访问一个对象的属性或方法,出现对象值为null。只有地址,地址中没有属性值,故为空指针。 例子 public class Main { public void changeInt...

weixin_44952377的博客 233

Java 到底是传值还是传引用

本文是节选自stackoverflow中的答案做一个总结,方便自己日后查看。 结论:Java没有传引用,只有传值 Dog myDog; myDog实际上是一个指向Dog的指针,不是真实的Dog。 Dog myDog = new Dog("Rover"); fuc(myDog); 假定新创建的Dog对象存在内存地址42的位置 使用fuc()函数传入的是 Dog对象 myDog的地址(也就是42) public void fuc(Dog someDog) { someDog.setName("Max

qq_39751320的博客 203

浅谈在Java语言中究竟是传值还是传引用

首先,推荐对Java有一定理解的同仁一本书《Practical Java》。 在《Practical Java》中也有一个章节介绍Java中关于传值和传引用的问题,堪称经典。 《Practical Java》 在Java中,事实上底层工作原理不存在传引用的概念,这也象《Practical Java》中所说的那样,Java中只有传值。这句话理解起来需要费一定的周折。

u013890660的专栏 1088

java传引用_Java中的传值与传引用

曾经对java中传值还是传引用的问题十分困惑,而且也被问到过许多次,无论是面试,还是平时我们平时的讨论中。在stackoverflow上面浏览时,无意中发现了跟这个问题有关的论题,于是深入地查看了,感觉获益匪浅,于是结合自己过去的经验,写了这篇博客跟大家分享。以前我觉得是这样的,java中的基本数据类型和String是传值的,而其它的类类型的数据则是传引用的。不过现在我觉得不是这样的。******...

weixin_39599454的博客 133

Java方法中传值与传引用的区别

版权声明:本文为博主原创文章,未经博主允许不得转载 值传递就是基本类型的传值 static int a=100; public static int incr(int i){ return i=i+1; } public static void main(String[] args) { System.out.println(incr(a)); System.out....

zhaomin4833085的博客 961

java传值和传引用

public class TestTransForValue { public void changeValue1(int age) { age=30; } public void changeValue2(Person person) { person.setPersonName("xxx"); } public void changeValue3(String str) { str="xxx"; } public static void main(String[] a

weixin_45934066的博客 623

Java 传值和传引用的区别

传值(传的是副本,相当于我又创建了一个相同的值) // 基本数据类型 public class ParamChangeValue { public static void main(String[] args) { int s = 1; System.out.println("args = [" + s + "]"); change(s); System.out.p

liulang68的博客 250
上一篇: 什么是Portal
下一篇: 职业经理人提高EQ三步曲
dankes
博客等级 码龄22年 41粉丝 55原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值