Java中void方法传参后变量更新差异:为何数组与基本类型表现不同?
Java参数传递:为什么int和数组的表现不一样?
这个问题绝对是Java新手(甚至不少老鸟)最容易踩的坑之一!其实核心点在于:Java只有传值传递,没有传引用传递——只不过针对不同类型的变量,传递的"值"的含义完全不同,才导致了这两种看起来矛盾的表现。
先看int的例子:基本数据类型的传值
先看你第一段代码:
public static void main(String[] args) { int c=0; changeC(c); System.out.println(c); // 输出0 } public static void changeC(int c) { c++; }
这里的int c是基本数据类型,当你把main里的c传给changeC方法时,Java会把c的值(也就是0)复制一份,传给方法里的参数c——这两个c完全是两个独立的变量,只是名字一样而已。
所以changeC里的c++,只是把这个副本的值从0改成了1,和main里的原变量半毛钱关系都没有,最后输出自然还是0。
再看数组的例子:对象引用的传值
再看岛屿数量的代码:
public int numIslands(char[][] grid) { int count=0; for(int i=0;i<grid.length;i++) for(int j=0;j<grid[0].length;j++){ if(grid[i][j]=='1'){ dfsFill(grid,i,j); count++; } } return count; } private void dfsFill(char[][] grid,int i, int j){ if(i>=0 && j>=0 && i<grid.length && j<grid[0].length&&grid[i][j]=='1'){ grid[i][j]='0'; dfsFill(grid, i + 1, j); dfsFill(grid, i - 1, j); dfsFill(grid, i, j + 1); dfsFill(grid, i, j - 1); } }
这里的char[][] grid是数组对象,Java里数组本质上是对象。当你把numIslands里的grid传给dfsFill时,传递的是这个数组对象引用的副本——换句话说,numIslands里的grid变量和dfsFill里的grid参数,指向的是同一个数组对象。
所以当你在dfsFill里执行grid[i][j]='0'时,你是在修改这个共享的数组对象的内部元素,而不是修改引用本身。既然两个变量指向同一个对象,那numIslands里的grid自然能看到这个修改后的结果。
补充个小测试:如果替换整个对象会怎样?
要是你在dfsFill里写这么一行:
grid = new char[3][3];
那numIslands里的grid完全不会变——因为你只是把dfsFill里的那个引用副本,改成指向了一个新的数组对象,而numIslands里的原引用还是指向原来的数组。
总结一下核心规则
- 对于基本数据类型(int、char、boolean、double等):传递的是变量值的副本,方法内修改副本不会影响原变量
- 对于对象类型(数组、自定义类对象、String等):传递的是对象引用的副本,方法内可以修改对象的内部状态,但无法改变原变量的引用指向(也就是不能让原变量指向新的对象)
内容的提问来源于stack exchange,提问作者James Mitchell
相关产品推荐
相关产品推荐

