近期连续看到有关数组的问题帖,其问题是将一个数组作为参数传递给某个method,并期望通过该method改变原先所引用之数组内容,但结果往往是原先的数组丝毫未动,小弟对JAVA reference机制偶有研究,希望以实际例子来说明java reference机制有别于C\C++首先该示例引用自本版帖子《如下的代码有什么问题?》,作者:wingofsea (翱翔的翼) ,为说明问题对实例稍做改动,如有冒犯之处还忘见量。其次要说明的是数组作为参数传递的问题乃是一个有关于java reference机制非常经典的问题,大多数初学JAVA的朋友在这样的问题上产生的困惑源自于C\C++的机制所带来的主观影响,因为在关于reference传递的问题上,JAVA 与 C\C++十分不一样。我们用实例来说明问题:示例代码1:
/**
* 该类将说明将数组作为参数传递过程中,引用机制所起到的作用
*/
class testArray {
/**
* 打印数组的内容,并显示该数组的引用地址
*/
static void printArray( int[] array ) {
System.out.println( "The array's address: " + array );
for( int i = 0; i < array.length; i++ )
System.out.print( " " + array[i] );
System.out.println();
}
/**
* 企图通过该函数对所传递的数组进行改变
*/
static void changeArray( int[] a1 ) {
System.out.println( "array a1 in changeArray: " + a1 );
int[] b = { 1, 2, 3 };
System.out.println( "\nCreate array b..." );
printArray( b );
System.out.println( "\nafter a1 = b..." );
a1 = b;
System.out.println( "array a1's address : " + a1 + "\n");
}
/**
* 主函数,实例化一个int array,并查看其在调用changeArray() method前
* 与调用后内部数据的变化以及引用地址的变化。
*/
public static void main( String[] args ) {
System.out.println( "------------ Start Process ------------" );
int[] a = { 3, 2, 1 };
System.out.println( "Create array a... " );
printArray( a );
System.out.println( "\nCall changeArray methods.");
changeArray( a ); // 期望通过引用传递改变数组a的内容
System.out.println( "After call changeArray methods...(back main() method)" );
System.out.println( "The array a is not changed..." );
printArray( a );
}
} /// @.@||~运行结果...
------------ Starting Process ------------
Create array a...
The array's address: [I@15601ea
3 2 1Call changeArray() methods...
In changeArray(), array a1's address: [I@15601eaCreate array b...
The array's address: [I@197d257
1 2 3after a1 = b...
a1's address: [I@197d257after call changeArray methods...(back main() method)
The array a is not changed...
The array's address: [I@15601ea
3 2 1
总结:
这里我们可以很清楚的看到,虽然我们将数组a以引用传递的方式传递给了changeArray() method,并且在开始时changeArray() method中的int[] a1确实依然指向原先的对象,但是当我们改变了a1的指向,将其指向另一个新的数组b时,注意,注意,问题出现了,我们很自然的会和c\c++做参考,于是我们认为,由于此时a1(也就是方法内部的引用)发生了改变,同时就会引起
外部数组的改变,但是当我们回到main()函数时,数组a没有发生热和变化,我们可以看到a的引用依然指向原先的对象,这是为什么呢?是的,在JAVA中,数组依然是一个对象,对象就会以reference的形式传递,但是这个reference却是一个值传递,
我们先搞清楚
Tyep a = new Type();
这里a is a reference, 他指向一个Type Object,JAVA中突出了一个引用变量的概念,reference本身也是一种变量,所以reference本身以值传递的形式传送给某个method,
-----------------------------------------------------------------------------
重点
这时 changeArray()中的int[] a1 与 main()中的int[] a乃是两个同时引用同一个long array object的不同的reference,
------------------------------------------------------------------------------
当我们修改了changeArray()中的int[] a的指向时,并不会影响另一个reference的指向,这就是为什么没有发生改变的原因了。如果欲在此地同时改变两者就必须实际改变两者所引用的对象。
源代码如下:
class testArray {
static void printArray( int[] array ) {
System.out.println( "The array's address: " + array );
for( int i = 0; i < array.length; i++ )
System.out.print( " " + array[i] );
System.out.println();
}
static void changeArray( int[] a1 ) {
System.out.println( "array a1 in changeArray: " + a1 );
int[] b = { 1, 2, 3 };
System.out.println( "\nCreate array b..." );
printArray( b );
/* Don't do this,以下代码只是改变了reference a1 的指向,并位改变a1原先引用之对象的内部状态
* System.out.println( "\nafter a1 = b..." );
* a1 = b;
* System.out.println( "array a1's address : " + a1 + "\n");
*/
// 实际改变Object
for( int i = 0; i < a1.length; i++ )
a1[i] = b[i];
}
public static void main( String[] args ) {
System.out.println( "------------ Start Process ------------" );
int[] a = { 3, 2, 1 };
System.out.println( "Create array a... " );
printArray( a );
System.out.println( "\nCall changeArray methods.");
changeArray( a ); // 期望通过引用传递改变数组a的内容
System.out.println( "After call changeArray methods...(back main() method)" );
System.out.println( "The array a is not changed..." );
printArray( a );
}
} /// @.@||~运行结果...
------------ Starting Process ------------
Create array a...
The array's address: [I@15601ea
3 2 1Call changeArray() methods...
In changeArray(), array a1's address: [I@15601eaCreate array b...
The array's address: [I@197d257
1 2 3after call changeArray methods...(back main() method)
The array a is changed...
The array's address: [I@15601ea
1 2 3我们可以看到main() method中的array a确实发生了改变。希望这个实例还能够说明一些JAVA reference的问题,希望能够对初学JAVA,或者是刚从C++跳转过来的朋友们有所帮助,本人也还是个JAVA初学者,上面的实例与说明难免会出现问题之处,望各位朋友多多包涵 ^ ^
/**
* 该类将说明将数组作为参数传递过程中,引用机制所起到的作用
*/
class testArray {
/**
* 打印数组的内容,并显示该数组的引用地址
*/
static void printArray( int[] array ) {
System.out.println( "The array's address: " + array );
for( int i = 0; i < array.length; i++ )
System.out.print( " " + array[i] );
System.out.println();
}
/**
* 企图通过该函数对所传递的数组进行改变
*/
static void changeArray( int[] a1 ) {
System.out.println( "array a1 in changeArray: " + a1 );
int[] b = { 1, 2, 3 };
System.out.println( "\nCreate array b..." );
printArray( b );
System.out.println( "\nafter a1 = b..." );
a1 = b;
System.out.println( "array a1's address : " + a1 + "\n");
}
/**
* 主函数,实例化一个int array,并查看其在调用changeArray() method前
* 与调用后内部数据的变化以及引用地址的变化。
*/
public static void main( String[] args ) {
System.out.println( "------------ Start Process ------------" );
int[] a = { 3, 2, 1 };
System.out.println( "Create array a... " );
printArray( a );
System.out.println( "\nCall changeArray methods.");
changeArray( a ); // 期望通过引用传递改变数组a的内容
System.out.println( "After call changeArray methods...(back main() method)" );
System.out.println( "The array a is not changed..." );
printArray( a );
}
} /// @.@||~运行结果...
------------ Starting Process ------------
Create array a...
The array's address: [I@15601ea
3 2 1Call changeArray() methods...
In changeArray(), array a1's address: [I@15601eaCreate array b...
The array's address: [I@197d257
1 2 3after a1 = b...
a1's address: [I@197d257after call changeArray methods...(back main() method)
The array a is not changed...
The array's address: [I@15601ea
3 2 1
总结:
这里我们可以很清楚的看到,虽然我们将数组a以引用传递的方式传递给了changeArray() method,并且在开始时changeArray() method中的int[] a1确实依然指向原先的对象,但是当我们改变了a1的指向,将其指向另一个新的数组b时,注意,注意,问题出现了,我们很自然的会和c\c++做参考,于是我们认为,由于此时a1(也就是方法内部的引用)发生了改变,同时就会引起
外部数组的改变,但是当我们回到main()函数时,数组a没有发生热和变化,我们可以看到a的引用依然指向原先的对象,这是为什么呢?是的,在JAVA中,数组依然是一个对象,对象就会以reference的形式传递,但是这个reference却是一个值传递,
我们先搞清楚
Tyep a = new Type();
这里a is a reference, 他指向一个Type Object,JAVA中突出了一个引用变量的概念,reference本身也是一种变量,所以reference本身以值传递的形式传送给某个method,
-----------------------------------------------------------------------------
重点
这时 changeArray()中的int[] a1 与 main()中的int[] a乃是两个同时引用同一个long array object的不同的reference,
------------------------------------------------------------------------------
当我们修改了changeArray()中的int[] a的指向时,并不会影响另一个reference的指向,这就是为什么没有发生改变的原因了。如果欲在此地同时改变两者就必须实际改变两者所引用的对象。
源代码如下:
class testArray {
static void printArray( int[] array ) {
System.out.println( "The array's address: " + array );
for( int i = 0; i < array.length; i++ )
System.out.print( " " + array[i] );
System.out.println();
}
static void changeArray( int[] a1 ) {
System.out.println( "array a1 in changeArray: " + a1 );
int[] b = { 1, 2, 3 };
System.out.println( "\nCreate array b..." );
printArray( b );
/* Don't do this,以下代码只是改变了reference a1 的指向,并位改变a1原先引用之对象的内部状态
* System.out.println( "\nafter a1 = b..." );
* a1 = b;
* System.out.println( "array a1's address : " + a1 + "\n");
*/
// 实际改变Object
for( int i = 0; i < a1.length; i++ )
a1[i] = b[i];
}
public static void main( String[] args ) {
System.out.println( "------------ Start Process ------------" );
int[] a = { 3, 2, 1 };
System.out.println( "Create array a... " );
printArray( a );
System.out.println( "\nCall changeArray methods.");
changeArray( a ); // 期望通过引用传递改变数组a的内容
System.out.println( "After call changeArray methods...(back main() method)" );
System.out.println( "The array a is not changed..." );
printArray( a );
}
} /// @.@||~运行结果...
------------ Starting Process ------------
Create array a...
The array's address: [I@15601ea
3 2 1Call changeArray() methods...
In changeArray(), array a1's address: [I@15601eaCreate array b...
The array's address: [I@197d257
1 2 3after call changeArray methods...(back main() method)
The array a is changed...
The array's address: [I@15601ea
1 2 3我们可以看到main() method中的array a确实发生了改变。希望这个实例还能够说明一些JAVA reference的问题,希望能够对初学JAVA,或者是刚从C++跳转过来的朋友们有所帮助,本人也还是个JAVA初学者,上面的实例与说明难免会出现问题之处,望各位朋友多多包涵 ^ ^
//C++
void fun(int * point){
*point = 12345;//这里和JAVA完全相同
int temp = 12345;
point = &temp;//同上
&point = 12345;
}//JAVA
void fun(int [] point){
point[0] = 12345;
point = new int[]{12345}; //JAVA是不支持直接修改指针储存的内存区域的
//&point = 12345;
}
抱歉,本人并不同意您的说法。
对于reference机制,其提供的操作便是如何籍由reference控制object,C++提供的操作直接支持reference对对象的直接控制,而JAVA中必须通过reference来间接控制object,但程序员本身却只可能操控reference。
就实现机制本身而言,这就是二者最大的不同了,何为相同?@.@||~
p = "test";
}能改变实参
void changeArray1( int *a )
{
int b[] = { 1, 2, 3 };
a = b; //为什么修改不能影响外部,其实相当 int *temp=a1; temp=b;
}void changeArray2(int* &a)
{
int *b = new int[3];
b[0]=1;
b[1]=2;
b[2]=3;
a = b;
}void test(){
int *a = new int[3];
a[0] = 3;
a[1] = 2;
a[2] = 1; printArray(a);
changeArray1(a);
printArray(a);
changeArray2(a);
printArray(a);
}java里的只是相当与changeArray1, 而没用changeArray2这种形式
不过那里面是对象,而不是这里的数组
TO:lxleaves(飘泊的叶子)
谢谢您给的建议,不过我完全赞同kingfish的观点,JAVA的引用十分接近于C/C++的指针概念,而非他们的引用概念。^^