一、概述

目前各类语言中向函数传递参数的类型分为三种:

  1. 按值传递
  2. 按引用传递
  3. 按指针传递

其中按值传递表示方法(函数)接收的是调用者提供的变量的拷贝,不改变参数的值;按引用传递表示方法(函数)接收的调用者提供的变量地址;按指针传递表示方法(函数)接收的是调用者提供的指针的拷贝,不改变指针的值和地址,但可以改变指针所指向的地址。

java中没有指针和引用传递,只有值传递,因此,在函数中改变局部变量的参数不会影响到全局变量的值。

二、Java函数中数据交换的实质

此时,虽然局部变量str1和str2与全局变量的str1和str2同名,但是,局部变量得到的仅仅是常量区值的地址的拷贝;如果交换局部变量的值,只是改变了局部变量的指向;不会影响大到全局变量。而方法区中的常量是final类型的,更是不会改变。

示例如下: String x = new String("x111");

 String y = new String("y111");

 swap(x,y);
System.out.println(x);
System.out.println(y); public static void swap(String a, String b) {
String temp = a;
a = b;
b = temp;
} int[] arr = new int[3];
change(arr);
System.out.println(arr.length);

public static void change(int[] arr) {
  arr = Arrays.copyOf(arr, arr.length * 2);
 }

输出的结果是:x111,y111,3

有人可能会说,String是一个final类型的类,太过特殊,那我们使用包装类试试。示例如下,得到的结果仍然是:3,4

 Integer inteA = new Integer("3");
Integer inteB = new Integer("4");
swapInte(inteA, inteB);
System.out.println(inteA);
System.out.println(inteB); public static void swapInte(Integer InteA, Integer InteB) {
Integer temp = 0;
temp = InteA.intValue();
InteB = InteA;
InteA = temp;
}

由此可见,不论java向方法中传递的是基本类型的数据还是引用类型的数据,其实质都是将该变量指向的地址拷贝一份传给了局部变量,本质上拷贝的该变量指向的一个值,随便局部变量如何玩耍,都不会波及全局变量。

三、C语言的指针传递和C#的引用传递

为了对比说明值传递与指针传递、引用传递的区别,下面结合C指针传递和C#的引用传递说明下;

指针传递和引用传递的本质是将全局变量自身的地址传给了局部变量,因此,局部量修改时,同时也修改了全局变量的地址。

C语言的指针交换示例:

#include <stdio.h>

void swop(char **str1, char **str2)
{
char *temp = NULL; temp = *str1;
*str1 = *str2;
*str2 = temp;
} int main()
{
char *str1 = "hello";
char *str2 = "world"; printf("str1 = %s, str2 = %s\n", str1, str2);
swop(&str1, &str2);
printf("str1 = %s, str2 = %s\n", str1, str2);
return ;
}

C#的引用传递

       static void Main(string[] args)
{
string x = "hello";
string y = "world";
Console.WriteLine("x={0},y={1}",x, y);
Swap(ref x, ref y);
Console.WriteLine("x={0},y={1}", x, y);
Console.ReadKey();
}
static void Swap(ref int x, ref int y)
{
int temp = x;
x = y;
y = x;
}
static void Swap(ref string x, ref string y)
{
string temp = x;
x = y;
y = x;
}

四、Java数据交换的三种方法

那么,我们如何做到修改函数局部变量的同时也修改全局变量呢?

方式1:使用数组,此时修改的是全局变量和局部变量共同指向的地址中的值,因此,二者的值都会改变。

        int[] arr = {3,4};
System.out.println(arr[0]);
System.out.println(arr[1]);
arr = swap(arr);
System.out.println(arr[0]);
System.out.println(arr[1]);
public static int[] swap(int[] arr){
int temp = arr[0];
arr[0] = arr[1];
arr[1] = temp;
return arr;
}

方式2:使用反射

Integer inteA = new Integer("3");
Integer inteB = new Integer("4");
try {
swap(inteA, inteB);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(inteA);
System.out.println(inteB); public static void swap(Integer a1, Integer b1) throws Exception { Field value = Integer.class.getDeclaredField("value"); value.setAccessible(true); int temp = a1.intValue(); value.set(a1, b1.intValue()); value.set(b1, temp);
}

方式3:使用类封装的属性进行交换,这个方式网上例子很多,在此不再举例说明了。

总结:Java中方法的参数传递都是值传递,方法内局部变量的改变不会影响到全局变量。但是对局部变量和全局变量共同指向的值进行了修改的话,全局变量和局部变量的值都会改变。 

Java交换数据为何不起作用原因分析的更多相关文章

  1. SAP R3和JAVA交换数据之JCO

    SAP Java Connector (JCo)     SAP的JAVA中间件,使用它可以使SAP的客户和合作伙伴使用JAVA语言轻松地建立可以和SAP系统通信的兼容的组件和应用程序下面是JCo一些 ...

  2. Java -Dfile.encoding=UTF-8 出现乱码问题原因分析

    这两天写了一个 Java 程序来玩,结果又遭遇了以前遇到过很多次的乱码问题,具体描述一下: 在 Mac 系统里面,常用的 Java 程序启动方式有如下几种: 1.通过 eclipse 执行 class ...

  3. java.lang.OutOfMemoryError GC overhead limit exceeded原因分析及解决方案

    最近一个上线运行良好的项目出现用户无法登录或者执行某个操作时,有卡顿现象.查看了日志,出现了大量的java.lang.OutOfMemoryError: GC overhead limit excee ...

  4. java线程数据交换Exchanger

    两个线程都等到交换函数才能完成交换数据操作,代码如下: package threadLock; import java.util.Random; import java.util.concurrent ...

  5. Java多线程之~~~使用Exchanger在线程之间交换数据[这个结合多线程并行会有解决很多问题]生产者消费者模型

    http://blog.csdn.net/a352193394/article/details/39503857  Java多线程之~~~使用Exchanger在线程之间交换数据[这个结合多线程并行会 ...

  6. Java并发工具类(四):线程间交换数据的Exchanger

    简介 Exchanger(交换者)是一个用于线程间协作的工具类.Exchanger用于进行线程间的数据交换.它提供一个同步点,在这个同步点两个线程可以交换彼此的数据.这两个线程通过exchange方法 ...

  7. Java并发编程--6.Exchanger线程间交换数据

    在两个线程之间定义同步点,当两个线程都到达同步点时,他们交换数据结构,因此第一个线程的数据结构进入到第二个线程中,第二个线程的数据结构进入到第一个线程中 在生产者-消费者情境模式中它包含了一个数缓冲区 ...

  8. Java中数据类型转换&基本类型变量和对象型变量

    1.Java的数据类型分为三大类 布尔型,字符型和数值型 其中数值型又分为整型和浮点型 2.Java的变量类型 布尔型 boolean 字符型 char 整型    byte,short,int,lo ...

  9. Mybatis成为Java互联网时代首选持久框架的原因

    持久层可以将业务数据存储到磁盘,具备长期存储能力,只要磁盘不损坏(大部分的重要数据都会有相关的备份机制),在断电或者其他情况下,重新开启系统仍然可以读取这些数据.一般执行持久任务的都是数据库系统.持久 ...

随机推荐

  1. KMP(模板)

    kmp算法是解决单模匹配问题的算法,难点在于求next[]数组 求next[]数组:对于模板串的所有前缀子串的最长公共前后缀的长度,就是next[]数组的值 eg:主串为cbbbaababac  子串 ...

  2. 如何:使用 as 和 is 运算符安全地进行强制转换(C# 编程指南)

    如何:使用 as 和 is 运算符安全地进行强制转换(C# 编程指南) 由于对象是多态的,因此基类类型的变量可以保存派生类型.若要访问派生类型的方法,需要将值强制转换回该派生类型.不过,在这些情况下, ...

  3. 微信小程序(基础)

    文档官网:https://developers.weixin.qq.com/miniprogram https://developers.weixin.qq.com/miniprogram/dev/f ...

  4. oracle练习-day02

    .查询员工表和部门表.查询出雇员的编号,姓名,部门的编号和名称,地址.查询出每个员工的上级领导.在上一个例子的基础上查询该员工的部门名称.在上一个例子的基础上查询员工工资等级和他的上级领导工资等级.查 ...

  5. Day3-C-Radar Installation POJ1328

    Assume the coasting is an infinite straight line. Land is in one side of coasting, sea in the other. ...

  6. js隐藏button

    $("#plshbtn").attr("style","display:none;");

  7. 物联网学习笔记——构建RESTFul平台1

    0.前言     前些时间顺着Yeelink学习了RESTFUL,使用PHP和Slim框架尝试实现简单的REST API,树莓派可通过GET方法获得JSON数据包,通过这种方式实现了树莓派和服务器(我 ...

  8. VScode禁用alt+key触发菜单栏快捷键

    因为用惯了Mac,突然改回Windows,但是已经习惯了按Command键.所以在Windows下把vscode的快捷键全改成alt+key了.但是Windows的alt+key快捷键就比较烦人了.所 ...

  9. P1079 延迟的回文数

    P1079 延迟的回文数 转跳点:

  10. day04-Python运维开发基础(位运算、代码块、流程控制)

    # (7)位运算符: & | ^ << >> ~ var1 = 19 var2 = 15 # & 按位与 res = var1 & var2 " ...