exceptions - Constructors

It’s important that we always ask, “If an exception occurs, will everything be properly cleaned up?” Most of the time we’re fairly safe, but with constructors there’s a problem. The constructor puts the object into a safe starting state, but it might perform some operation—such as opening a file—that doesn’t get cleaned up until the user is finished with the object and calls a special cleanup method. If we throw an exception from inside a constructor, these cleanup behaviors might not occur properly. This means we must be especially vigilant when writing a constructor. We might think finally is the solution.

// exceptions/CleanupIdiom.java
// (c)2017 MindView LLC: see Copyright.txt
// We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information.
// Disposable objects must be followed by a try-finally

class NeedsCleanup { // Construction can't fail
  private static long counter = 1;
  private final long id = counter++;

  public void dispose() {
    System.out.println("NeedsCleanup " + id + " disposed");
  }
}

class ConstructionException extends Exception {}

class NeedsCleanup2 extends NeedsCleanup {
  // Construction can fail:
  NeedsCleanup2() throws ConstructionException {}
}

public class CleanupIdiom {
  public static void main(String[] args) {
    // [1]:
    NeedsCleanup nc1 = new NeedsCleanup();
    try {
      // ...
    } finally {
      nc1.dispose();
    }

    // [2]:
    // If construction cannot fail,
    // you can group objects:
    NeedsCleanup nc2 = new NeedsCleanup();
    NeedsCleanup nc3 = new NeedsCleanup();
    try {
      // ...
    } finally {
      nc3.dispose(); // Reverse order of construction
      nc2.dispose();
    }

    // [3]:
    // If construction can fail you must guard each one:
    try {
      NeedsCleanup2 nc4 = new NeedsCleanup2();
      try {
        NeedsCleanup2 nc5 = new NeedsCleanup2();
        try {
          // ...
        } finally {
          nc5.dispose();
        }
      } catch (ConstructionException e) { // nc5 const.
        System.out.println(e);
      } finally {
        nc4.dispose();
      }
    } catch (ConstructionException e) { // nc4 const.
      System.out.println(e);
    }
        // System.out.println(NeedsCleanup.counter); // compile error: counter has private access in
    // NeedsCleanup
  }
}
/* Output:
NeedsCleanup 1 disposed
NeedsCleanup 3 disposed
NeedsCleanup 2 disposed
NeedsCleanup 5 disposed
NeedsCleanup 4 disposed
*/

The messiness of exception handling here is a strong argument for creating constructors that cannot fail, although this is not always possible. Note that if dispose() can throw an exception you might need additional try blocks. Basically, we must think carefully about all the possibilities and guard for each one.

try-with-resources

solution:

// exceptions/InputFile2.java
// (c)2017 MindView LLC: see Copyright.txt
// We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information.

import java.io.*;
import java.nio.file.*;
import java.util.stream.*;

public class InputFile2 {
  private String fname;

  public InputFile2(String fname) {
    this.fname = fname;
  }

  public Stream<String> getLines() throws IOException {
    return Files.lines(Paths.get(fname));
  }

  public static void main(String[] args) throws IOException {
    new InputFile2("InputFile2.java").getLines().skip(16).limit(1).forEach(System.out::println);
  }
}
/* My Output:
    public Stream<String> getLines() throws IOException {
*/

references:

1. On Java 8 - Bruce Eckel

2. https://github.com/wangbingfeng/OnJava8-Examples/blob/master/exceptions/CleanupIdiom.java

3. https://github.com/wangbingfeng/OnJava8-Examples/blob/master/exceptions/InputFile2.java

4. https://docs.oracle.com/javase/8/docs/api/java/nio/file/Paths.html#get-java.lang.String-java.lang.String...-

5. https://docs.oracle.com/javase/8/docs/api/java/nio/file/Files.html#lines-java.nio.file.Path-

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值