首页 > 解决方案 > 当您想要链接构造函数时,如何处理 IO 句柄?

问题描述

我有一个简单的类,它在其构造函数中接受InputStream已知格式的。在将值分配给对象的私有成员之前,所有繁重的工作都在此构造函数中完成:

public class TestClass {
   private Integer something;
   
   public TestClass(InputStream istream) {
      // Long and complex something-something
      // ...
      
      // Assign value after lots of processing
      something = 123;
   }
}

现在我决定我还想提供一个接受File. 我可以像这样轻松地链接构造函数:

public TestClass(File file) {
   this(new FileInputStream(file));
}

哦哦!我忘记关闭流了!

public TestClass(File file) {
   InputStream istream = new FileInputStream(file);
   
   try {
      // Error: Constructor call must be the first statement in a constructor
      this(istream);
   }
   finally {
      istream.close();
   }
}

不允许以这种方式链接构造函数。Java 说从另一个构造函数调用构造函数必须是第一条语句。

我试图将所有内容都填充到一个处理初始化的方法中,但 Java 编译器仍然对我的构造函数有未初始化的变量大喊大叫:

public class TestClass {
   private Integer something;
   
   // Error: The field something may not have been initialized
   public TestClass (InputStream istream) {
      doInit();
   }
   
   // Error: The field something may not have been initialized
   public TestClass (File file) {
      InputStream istream = new FileInputStream(file);
      
      try {
         doInit(istream);
      }
      finally {
         istream.close();
      }
      
   }
   
   private void doInit(InputStream istream) {
      something = 123;
   }
}

除了简单地删除接受 aFile并且只接受流的构造函数之外,有没有办法让这个工作像呈现的那样?

我的实际代码有多个正在初始化的成员变量,因此它不像将流传递给静态方法并返回一个值那么简单,因为这最多只能初始化一个变量。

标签: javaconstructorio

解决方案


一种解决方案是使用静态方法:

public class TestClass {

  public static TestClass fromFile(File file) throws IOException {
    try (FileInputStream input = new FileInputStream(file)) {
      return new TestClass(input);
    }
  }

  public TestClass(InputStream input) throws IOException {
    // initialize instance...
  }
}

推荐阅读