详解Java引用类型的参数也是值传递

简述

调用方法的时候,有需要传参数的情况。在Java中,参数的类型有基本类型和引用类型两种。

一开始听到一个说法,Java没有引用传递,但是一直没有太多的思考在上面,直到前不久玩数组的时候,突然间发现把数组引用变量作为参数传递到一个方法当中进行操作之后,再去访问原数组,尽然改变了。于是乎,就想到了之前在C++里面学过的引用传递,突然有一种错愕的感觉,就查了一些资料,探究当Java引用类型变量作为参数传递给方法的时候,到底是值传递还是引用传递。

结论:如果将Java引用类型变量作为参数传递给方法,是将引用变量的值传递给形参,而引用变量的值实际上就是引用对象在堆内存中的地址。也就是说,这个时候实参和形参指向了同一个对象,如果利用形参进行操作,操作的就是实参指向的对象,最后通过实参的那个引用访问,自然是被形参操作过的结果。

基本类型参数

基本类型参数是典型的值传递,著名的案例就是更换两个数的值。下面是这个问题的示例代码:

public class Main {
	public static void main(String[] args) {
		int num1 = 11;
		int num2 = 22;
		System.out.println("Before the call: num1 is " + num1 + " and num2 is " + num2);
		swap(num1, num2);
		System.out.println("After the call: num1 is " + num1 + " and num2 is " + num2);
	}

	public static void swap(int num1, int num2) {
		System.out.println("num1 is " + num1 + " and num2 is " + num2 + " in method of swap.(before)");
		int tmp = num1;
		num1 = num2;
		num2 = tmp;
		System.out.println("num1 is " + num1 + " and num2 is " + num2 + " in method of swap.(after)");
	}
}

运行结果如下

Before the call: num1 is 11 and num2 is 22
num1 is 11 and num2 is 22 in method of swap.(before)
num1 is 22 and num2 is 11 in method of swap.(after)
After the call: num1 is 11 and num2 is 22

通过运行结果,可以清楚地知道,通过这样的参数传递,交换的仅仅是形参的值,而main方法当中的两个数的值并内有发生变化。这就是值传递的结果。

引用类型参数

通过一个数组引用演示引用类型参数的传递效果

public class ArrayTest {
	public static void main(String[] args) {
		int[] arr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
		System.out.print("Before calling the inversion: ");
		for (int i : arr) {
			System.out.printf("%3d", i);
		}
		System.out.println();
		inversion(arr);
		System.out.print(" After calling the inversion: ");
		for (int i : arr) {
			System.out.printf("%3d", i);
		}
		System.out.println();

		setNull(arr);
		System.out.println("@" + arr);
	}
	public static void inversion(int[] arr) {
		int length = arr.length;
		for (int i = 0; i <= length / 2; i++) {
			int temp = arr[i];
			arr[i] = arr[length - i - 1];
			arr[length - i -1] = temp;
		}
	}

	public static void setNull(int[] array) {
		System.out.println("#" + array);
		array = null;
		System.out.println("$" + array);
	}
}

程序运行结果:

Before calling the inversion:   0  1  2  3  4  5  6  7  8  9
   After calling the inversion:   9  8  7  6  4  5  3  2  1  0
#[I@1d251891
$null
@[I@1d251891

程序中,在main方法中定义了一个数组,并且在类中定义了一个将数组元素倒置的方法inversion(),这个方法需要传入一个数组类型的引用。在main方法中调用这个方法,并将arr这个数组的引用作为参数传递给inversion方法,通过程序执行的结果,可以看到当inversion方法执行完毕,main方法中的arr数组的内容的确发生了倒置。

那么,这个时候是否就可以认为,引用类型的传递是引用传递而并非值传递呢?按照资料显示的,引用类型的参数传递传递的是引用变量的值,有什么方法可以证明一下呢?setNull()方法提供了这样的证明。

setNull方法的参数是数组的引用变量,程序中传入的是arr.进入方法,首先打印了array,然后将它置空再打印一次,然后在main方法中,打印arr的地址。程序运行的结果表示,array置空之前和arr指向的是同一区域,而后array=null却并没有影响到arr.

所以,可以肯定,当一个引用类型的变量被作为参数传递到方法中的时候,仅仅是将变量值复制后传递过去,而本身没有发生改变去指向其他。

当array=null的时候,array指向堆区的引用失效了。

以上的示例和分析都表明,Java中的确没有引用传递,当把一个引用类型的变量作为参数传递给方法的时候,也仅仅是将引用变量的值复制一份给了方法中的参数,自己始终指向原本的对象。

以上所述是小编给大家介绍的Java引用类型的参数也是值传递详解整合,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持!

(0)

相关推荐

  • 详解JAVA中的Collection接口和其主要实现的类

    Collection是最基本的集合接口,一个Collection代表一组Object,即Collection的元素(Elements).一些Collection允许相同的元素而另一些不行.一些能排序而另一些不行.Java SDK不提供直接继承自Collection的类,Java SDK提供的类都是继承自Collection的"子接口"如List和Set,详细信息可见官方文档http://tool.oschina.net/uploads/apidocs/jdk-zh/java/util/

  • 深入理解Java多线程与并发编程

    一.多线程三大特性 多线程有三大特性:原子性.可见性.有序性. 原子性 (跟数据库的事务特性中的原子性类似,数据库的原子性体现是dml语句执行后需要进行提交): 理解:即一个操作或多个操作,要么全部执行并且执行的过程中不会被任何因素打断,要么都不执行. 一个很经典的例子就是银行账户转账问题: 比如从账户A向账户B转1000元,那么必然包括2个操作:从账户A减去1000元,往账户B加上1000元.这2个操作必须要具备原子性才能保证不出现一些意外的问题. 我们操作数据也是如此,比如i = i+1:其

  • Java中缀表达式转后缀表达式实现方法详解

    本文实例讲述了Java中缀表达式转后缀表达式实现方法.分享给大家供大家参考,具体如下: 本文先给出思路与方法,最后将给出完整代码 项目实战: https://www.jb51.net/article/158335.htm 算法综述: 一.中缀表达式转后缀表达式: 1.中缀表达式要转后缀表达式,首先需要两个Stack(栈),其中一个应用于存放字符,另一个用于存放数字. 2.读到数字直接存入数字栈中,读到字符时,要咸鱼栈内前一元素(字符)进行比较,当当前(要存入的字符)优先级大于迁移字符时才存入,否

  • 浅谈java String不可变的好处

    一.java内部String类的实现: java 8: public final class String implements java.io.Serializable, Comparable<String>, CharSequence { /** The value is used for character storage. */ private final char value[]; } java 9 及之后:(使用coder标识了编码) public final class Stri

  • Java常用工具类—集合排序

    一.集合排序概述 1.主要内容 集合中的基本数据类型排序 集合中的字符串排序 Comparator接口 Comparable接口 回顾: //数组的排序 int[] arr= {2,3,4,5,2,1}; Arrays.sort(arr); 2.集合排序方法 使用Collections类的sort(List list)方法 sort(List list)是根据元素的自然顺序对指定列表按升序进行排序. 二.对基本数据类型和字符串类型进行排序 1.对基本数据类型排序 List中只能存放对象,要想存放

  • Javascript的this详解

    在理解javascript的this之前,首先先了解一下作用域. 作用域分为两种: 1.词法作用域:引擎在当前作用域或者嵌套的子作用域查找具有名称标识符的变量.(引擎如何查找和在哪查找.定义过程发生在代码书写阶段) 2.动态作用域:在运行时被动态确定的作用域. 词法作用域和动态作用域的区别是:词法作用域是在写代码或定义时确定的:动态作用域是在运行时确定的. this的绑定规则 this是在调用时被绑定,取决于函数的调用位置.由此可以知道,一般情况下(非严格模式下),this都会根据函数调用(调用

  • Java BigInteger类,BigDecimal类,Date类,DateFormat类及Calendar类用法示例

    本文实例讲述了Java BigInteger类,BigDecimal类,Date类,DateFormat类及Calendar类用法.分享给大家供大家参考,具体如下: BigInteger类 发 package cn.itcast_01; import java.math.BigInteger; /* * BigInteger:可以让超过Integer范围内的数据进行运算 * * 构造方法: * BigInteger(String val) */ public class BigIntegerDe

  • 详解Java中Thread 和Runnable区别

    Thread 和Runnable 关系 Thread类是接口Runnable的一个实现类. public class Thread implements Runnable 源码分析 Thread Threa类运行的时候调用start()方法,源代码如下: 调用start()方法,实际运行的是start0方法,方法声明如下: private native void start0() native表明这个方法是个原生函数,即这个函数是用C/C++实现的,被编译成DLL,由Java调用. native

  • 详解Java包装类及自动装箱拆箱

    Java包装类 基本类型 大小 包装器类型 boolean / Boolean char 16bit Boolean byte 8bit Byte short /16bit Short int 32bit Integer long 64bit Long float 32bit Float double 64bit Double void / Void Java 的包装类有两个主要的目的: Java包装类将基本数据类型的值"包装"到对象中,对基本数据类型的操作变为了对对象进行操作,从而使

  • 4位吸血鬼数字的java实现思路与实例讲解

    这个问题来源于Java编程思想一书,所谓"吸血鬼数字"就是指位数为偶数的数字,可以由一对数字相乘而得到,而这对数字各包含乘积的一半位数字,其中从偶数位数字中选取的数字可以任意排列.例如: 1260=21*60,1827=21*87,2187=27*81-- 先列出结果: 一共7个: 1260=21*60,1395=15*93,1435=41*35,1530=51*30,1827=87*21,2187=27*81,6880=86*80 第一种思路对所有的4位数进行穷举,假设这个4位数是a

随机推荐