讲述Java初学者必须要了解的两个常识

王朝java/jsp·作者佚名  2008-05-31
宽屏版  字体: |||超大  

一、对象(object)与引用(reference)

我们知道:

A a = new A();

产生一个A类型的对象,a是这个对象的的一个引用,即a指向heap中真正的对象,而a和其他基本数据类型一起存放在stack中。也就是object通过reference操控,在底层的话,a更象一个指针。

对于有些书本所说,a就是对象,初学者的话也没什么大问题,因为对a的操作,就是对a指向的对象的操作。

问题是,当a的指向发生改变时,a就是对象的说法就不能适应程序设计的需要。让我们来看一个简单的程序:

class A

{

private int i=0;

public void setI(int x)

{

i=x;

}

public int getI()

{

return i;

}

}

public class MyRef1

{

public static void main(String[] args)

{

A a=new A();

A b=new A();

a.setI(10);

b.setI(15);

System.out.println("a的i="+a.getI());

System.out.println("b的i="+b.getI());

a=b;

a.setI(20);

System.out.println("a的i="+a.getI());

System.out.println("b的i="+b.getI());

}

}

我想,大家对于程序的输出应该认为是:

a的i=10

b的i=15

a的i=20

b的i=15

第一,第二行应该没什么异义,第三行是对a设置后i的值,问题是,第四行是不会输出i=15的,正确结果是:

i=20

因此,a,b都是对对象的引用,当我们将b的引用赋予a时,a已经重新指向了b,对指向发生改变后的a的操作,就是对b的操作。当然,那些坚持"a,b就是对象"说法的人,还是可以解释这个问题。

我们知道,Java通过final来定义常量:

final int i=10;

当我们对一个常量重新赋值时,会发生编译错误:

i=5;//编译不通过

我们也可以通过final来定义常量对象:

final A a = new A();

这样的话,我们将不能对a重新赋值。

假如a本身是个对象,那么,这个对象就不能发生改变,其实,a只不过是一个引用,它只能指向原来指向的对象,

并不是说它所指的对象的状态不能改变,因此,我们可以通过不改变a原来的指向的情况下对对象状态进行改变,看程序:

class A

{

private int i=0;

public void setI(int x)

{

i=x;

}

public int getI()

{

return i;

}

}

public class MyRef1

{

public static void

main(String[] args)

{

final A a = new A();

System.out.println(a.getI());

a.setI(8);

System.out.println(a.getI());

}

}

假如a本身是个对象,那么,根本就不可能a.setI(8);而实际a是一个引用,程序可以编译并运行: 显示:8

总之,Java通过renfence来操控object,是深入学习Java知识的基础。

二,Java参数是值(value)传递还是引用(reference)传递我们先看程序:

public class MyRef2

{

static int x=10;

static int y=20;

public static void fangfa(int i)

{

i++;

x=i;

}

public static void main(String[] args)

{

System.out.println("x="+x);

System.out.println("y="+y);

MyRef2.fangfa(y);

System.out.println("x="+x);

System.out.println("y="+y);

}

}

显然,将显示:

x=10

y=20

x=21

y=20

y的值并没有发生改变,MyRef2.fangfa(y)使用的仅仅是y的值,里面的i++也不会作用到y本身。显然,java的参数是值传递,但是,为什么会有引用传递的说法呢?看下面这个程序:

class A

{

private int i=0;

public void setI(int x)

{

i=x;

}

public int getI()

return i;

}

}

public class MyRef1

{

public static void setA1(A newA,int t)

{

newA.setI(t);

}

public static void main(String[] args)

{

A a=new A();

System.out.println(a.getI());

MyRef1.setA1(a, 30);

System.out.println(a.getI());

}

}

按照值传递的说法,MyRef1.setA1(a,30);将使用a所指的对象的一个复件,最终对这个对象没有作用,而事实是,方法对这个对象起了作用,程序将显示0,30。那么,Java参数是值传递是不是错误了呢?其实并不是的,我们要记住,a只不过是对象的reference,而reference的复件与原来的reference指向的是同一个对象,我们对复件的操作,与对a的操作一样,最终还是对指向对象的操作,因此,Java的参数,只有值传递。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
© 2005- 王朝网络 版权所有