一、概述

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

  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. 吴裕雄 Bootstrap 前端框架开发——Bootstrap 表格:精简表格

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  2. Immediate Decodability[UVA644](Trie入门)

    传送门 题意:给出一些数字串,判断是否有一个数字串是另一个串的前缀. 这题真的可以算是Trie树的一道模板题了. 先把Trie树建好,建树的时候记录一个sum表示一个节点有多少个串会包含此节点,然后再 ...

  3. Memcached 最新版本发布,不再仅仅是个内存缓存了

    导读 Memcached 1.5.18和之后版本可以在服务重启时恢复内存缓存.新版本还通过DAX文件系统挂载来实现缓存持久性功能. 可以通过在启动选项使用该功能: -e /tmpfs_mount/me ...

  4. STM32CubeIDE printf 串口重定向

  5. 1-4SpringBoot操作之Spring-Data-Jpa(一)

    Spring-Data-Jpa JPA(Java Persistence API)定义了一系列对象持久化的标准, 目前实现这一规范的产品有Hibernate.TopLink等. Spring Data ...

  6. ES6转换ES5

    各大浏览器的最新版本,对 ES6 的支持可以查看kangax.github.io/es5-compat-table/es6/.随着时间的推移,支持度已经越来越高了,超过 90%的 ES6 语法特性都实 ...

  7. Jquery属性操作、添加类

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  8. java 根据传入的时间获取当前月的第一天的0点0分0秒和最后一天的23点59分59秒

    /** * 获取指定日期所在月份开始的时间 * lkeji * @return */ public static String getMonthBegin(String specifiedDay) { ...

  9. 51nod 1433:0和5

    1433 0和5 题目来源: CodeForces 基准时间限制:1 秒 空间限制:131072 KB 分值: 10 难度:2级算法题  收藏  取消关注 小K手中有n张牌,每张牌上有一个一位数的数, ...

  10. 看雪hello

    在看雪做了一道题目很简单,但是还是记录一下自己的学习. 用ida打开,然后shift+F12查看 这里可以看到基本的结构,转到pass查看 发现ATA XREF: sub_401770+Bo打开这里 ...