5.1 Java的值

Java 的值以及它们与类型系统的关系非常简单。Java 的值有两种类型——基本值和对象引用。

5.1 Java的值 - 图1 有些书把基本值称为“值类型”——把 Java 的对象引用当成值时,这个称呼会产生歧义。因此,只要涉及 Java 的八种非引用类型,我们都使用“基本值”这个术语。

只有这两种值才能赋值给变量。其实,值的一种定义方式是“可以赋值给变量或传入方法的东西”。C++ 和 C 语言程序员要注意,对象的内容不能赋值给变量,所以 Java 没有解除引用运算符或结构体。

基本值和对象引用的主要区别是,基本值不能修改——2 永远都是 2,而对象引用的内容一般都能修改——一般称这种修改为对象内容的变化(mutation)。

Java 试图简化一个经常会让 C++ 程序员困惑的概念,即“对象的内容”和“对象的引用”之间的区别。但也不能完全忽视这个区别,因此,程序员要理解 Java 平台中引用值的运作方式。

Java 是“引用传递”语言吗?

Java“ 通过引用”处理对象,但不能把这种处理方式和“引用传递”(pass by reference)搞混了。“引用传递”是一个术语,用于描述某些编程语言中方法的调用方式。在引用传递语言中,值,甚至是基本值,不直接传入方法,而是把值的引用传入方法。因此,如果方法修改了参数,方法返回后这一变化仍然存在。就算是基本类型,也使用这种处理方式。

Java 不会这么做,Java 是“值传递”语言。不过,如果传入的值是引用类型,那么实际传入的是引用副本。但是这和引用传递并不是一回事。如果 Java 是引用传递语言,把引用类型的值传入方法时,传入的应该是引用的引用。

事实上,Java 使用值传递,这一点很容易证明。如下述代码所示,就算调用了 manipulate() 方法,变量 c 保存的值也没有变化,还是引用一个半径为 2 的 Circle 对象。如果 Java 是引用传递语言,那么 c 保存的值应该是一个半径为 3 的 Circle 对象。

  1. public void manipulate(Circle circle) {
  2. circle = new Circle(3);
  3. }
  4. Circle c = new Circle(2);
  5. manipulate(c);
  6. System.out.println("Radius: "+ c.getRadius());

如果我们谨慎对待这个区别,而且把对象引用当成 Java 的一种值,那么 Java 某些令人惊奇的其他功能就会显现出来。注意,有些旧资料对这一点的表述并不清晰。第 6 章介绍内存管理和垃圾回收机制时还会遇到 Java 值的这种特性。