1

假设我有一个类包含对正在读取文件的 InputStream 或正在写入文件的 OutputStream 的引用(或者另一个示例,如果您是 Android 开发人员,则为 MediaPlayer 实例)。

知道 Java 是按值传递对象的,当你有类似下面的伪代码时会发生什么?

class MyClass  {


  InputStream is;

  public void read() {
    // initialize inputstream here (assume it's reading from a file that contains the alphabet from A-z)

     is.read();

 }
 public MyClass() {
    this.read();
  }
}


class OtherClass {
  MyClass mine = new MyClass();
  public OtherClass() {
     mine.read();
     LastClass lastClass = new LastClass(mine);

  }
}


class LastClass {
   MyClass his;

   public LastClass(MyClass mc) {
       his = mc;
        his.read();
    }
}

我的问题是,既然我们按值传递对象,它们如何能够维护对开放资源的引用?另外,为了清楚起见,在执行所有操作时,存在多少 MyClass 实例?

4

1 回答 1

1

虽然 Java 确实是按值传递的,但您必须记住,对于对象,传递的是对象引用的值。

尽管通过引用传递和传递引用的值之间似乎没有区别,但它们是细微的区别。有关该主题的更深入讨论,请参阅is-java-pass-by-reference 。

因此,为了回答您的问题,在您的示例中,您将为您MyClass创建的每个实例创建一个实例OtherClass

至于输入流,由于它是在构造函数中MyClass.read()而不是在MyClass构造函数中初始化的,那么我们可以假设每次read()调用都会打开文件,并从文件中读取一个字节。将InputStream保持打开状态,但在下次read()调用时,InputStream将对新的引用分配给is成员变量,旧的将被释放以进行垃圾收集。如果没有更多代码,很难说更多。

创建OtherClass对象时,会发生以下情况:

  • 在堆中创建一个新MyClass对象,并且对该对象的引用存储在mine成员变量中。
    • MyClass构造函数调用该方法read()。所以一个新InputStream的被初始化并从文件中读取第一个字节。
  • 构造OtherClass函数调用mine.read(). 所以一个新InputStream的被初始化并从文件中读取第一个字节。
  • 创建了一个新LastClass对象。MyClass对存储在变量中的对象的引用值mine被传递给构造函数。
    • 此引用副本MyClass保存在新对象的成员变量his中。LastClass
    • 构造LastClass函数调用mine.read(). 所以一个新InputStream的被初始化并从文件中读取第一个字节。
于 2013-10-31T04:19:21.550 回答