示例代码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 1
Call changeArray() methods...
In changeArray(), array a1 's address: [I@15601ea
Create array b...
The array 's address: [I@197d257
1 2 3
after a1 = b...
a1 's address: [I@197d257
after 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 1
Call changeArray() methods...
In changeArray(), array a1 's address: [I@15601ea
Create array b...
The array 's address: [I@197d257
1 2 3
after call changeArray methods...(back main() method)
The array a is changed...
The array 's address: [I@15601ea
1 2 3
我们可以看到main() method中的array a确实发生了改变。
2 garbage 与reference
Java 提供自动内存管理的机制,也就是俗称的 garbage collection(垃圾收集)。当一个对象不再被任何 variable (Reference) 所指到,就代表此对象从此不可能再被利用,Java 虚拟机器内一个负责收集垃圾的 thread 就会在适当的时机出来将此块内存回收。
后来对reference进行了补充(关于debugger的困扰)
Direct Reference > Soft Reference > Weak Reference > Phantom Reference
其中,direct reference 就是一般的 reference。只要被任何 direct reference 所reference 到的对象就不会被 garbage collector 清除。其它的三种 reference(包括soft reference,weak reference,phantom reference)则不然,他们不会影响 gar bage collection。
如果对这些特殊的 reference 感兴趣,具体去看看 java.lang.ref 的 Javadoc,顺便写几个程序试试看。